Helpviewer/HelpBrowserWV.py

changeset 1586
b3e34806b734
parent 1584
38c0907eeea1
child 1587
714a3627a089
equal deleted inserted replaced
1584:38c0907eeea1 1586:b3e34806b734
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, QUrl, \
12 QBuffer, QIODevice, QByteArray, QFileInfo, Qt, QTimer, QEvent, QRect 12 QBuffer, QIODevice, QByteArray, QFileInfo, Qt, QTimer, QEvent, QRect
13 from PyQt4.QtGui import qApp, QDesktopServices, QStyle, QMenu, QApplication, \ 13 from PyQt4.QtGui import qApp, QDesktopServices, QStyle, QMenu, QApplication, \
14 QInputDialog, QLineEdit, QClipboard, QMouseEvent, QLabel, QToolTip, QColor, \ 14 QInputDialog, QLineEdit, QClipboard, QMouseEvent, QLabel, QToolTip, QColor, \
15 QPalette, QFrame 15 QPalette, QFrame, QPrinter, QPrintDialog, QDialog
16 from PyQt4 import QtWebKit 16 from PyQt4 import QtWebKit
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:
35 from PyQt4.QtNetwork import QSslCertificate 35 from PyQt4.QtNetwork import QSslCertificate
36 SSL_AVAILABLE = True 36 SSL_AVAILABLE = True
37 except ImportError: 37 except ImportError:
38 SSL_AVAILABLE = False 38 SSL_AVAILABLE = False
39 import Helpviewer.HelpWindow 39 import Helpviewer.HelpWindow
40 from .HelpLanguagesDialog import HelpLanguagesDialog
40 41
41 from .Network.NetworkAccessManagerProxy import NetworkAccessManagerProxy 42 from .Network.NetworkAccessManagerProxy import NetworkAccessManagerProxy
42 43
43 from .OpenSearch.OpenSearchEngineAction import OpenSearchEngineAction 44 from .OpenSearch.OpenSearchEngineAction import OpenSearchEngineAction
44 from .OpenSearch.OpenSearchEngine import OpenSearchEngine 45 from .OpenSearch.OpenSearchEngine import OpenSearchEngine
491 492
492 self.page().loadStarted.connect(self.__hideAccessKeys) 493 self.page().loadStarted.connect(self.__hideAccessKeys)
493 self.page().scrollRequested.connect(self.__hideAccessKeys) 494 self.page().scrollRequested.connect(self.__hideAccessKeys)
494 495
495 self.__rss = [] 496 self.__rss = []
497
498 self.__clickedFrame = None
496 499
497 self.grabGesture(Qt.PinchGesture) 500 self.grabGesture(Qt.PinchGesture)
498 501
499 def __addExternalBinding(self, frame=None): 502 def __addExternalBinding(self, frame=None):
500 """ 503 """
818 821
819 @param evt reference to the context menu event object (QContextMenuEvent) 822 @param evt reference to the context menu event object (QContextMenuEvent)
820 """ 823 """
821 menu = QMenu(self) 824 menu = QMenu(self)
822 825
826 frameAtPos = self.page().frameAt(evt.pos())
823 hit = self.page().mainFrame().hitTestContent(evt.pos()) 827 hit = self.page().mainFrame().hitTestContent(evt.pos())
824 if not hit.linkUrl().isEmpty(): 828 if not hit.linkUrl().isEmpty():
825 act = menu.addAction(self.trUtf8("Open Link in New Tab\tCtrl+LMB"), 829 menu.addAction(UI.PixmapCache.getIcon("openNewTab.png"),
826 self.__openLinkInNewTab) 830 self.trUtf8("Open Link in New Tab\tCtrl+LMB"),
827 act.setData(hit.linkUrl()) 831 self.__openLinkInNewTab).setData(hit.linkUrl())
828 menu.addSeparator() 832 menu.addSeparator()
829 menu.addAction(self.trUtf8("Save Lin&k"), self.__downloadLink) 833 menu.addAction(UI.PixmapCache.getIcon("download.png"),
830 act = menu.addAction(self.trUtf8("Bookmark this Link"), self.__bookmarkLink) 834 self.trUtf8("Save Lin&k"), self.__downloadLink)
831 act.setData(hit.linkUrl()) 835 menu.addAction(UI.PixmapCache.getIcon("bookmark22.png"),
836 self.trUtf8("Bookmark this Link"), self.__bookmarkLink)\
837 .setData(hit.linkUrl())
832 menu.addSeparator() 838 menu.addSeparator()
833 menu.addAction(self.trUtf8("Copy Link to Clipboard"), self.__copyLink) 839 menu.addAction(UI.PixmapCache.getIcon("editCopy.png"),
840 self.trUtf8("Copy Link to Clipboard"), self.__copyLink)
841 menu.addAction(UI.PixmapCache.getIcon("mailSend.png"),
842 self.trUtf8("Send Link"), self.__sendLink).setData(hit.linkUrl())
834 if Preferences.getHelp("VirusTotalEnabled") and \ 843 if Preferences.getHelp("VirusTotalEnabled") and \
835 Preferences.getHelp("VirusTotalServiceKey") != "": 844 Preferences.getHelp("VirusTotalServiceKey") != "":
836 act = menu.addAction(UI.PixmapCache.getIcon("virustotal.png"), 845 menu.addAction(UI.PixmapCache.getIcon("virustotal.png"),
837 self.trUtf8("Scan Link with VirusTotal"), self.__virusTotal) 846 self.trUtf8("Scan Link with VirusTotal"), self.__virusTotal)\
838 act.setData(hit.linkUrl()) 847 .setData(hit.linkUrl())
839 848
840 if not hit.imageUrl().isEmpty(): 849 if not hit.imageUrl().isEmpty():
841 if not menu.isEmpty(): 850 if not menu.isEmpty():
842 menu.addSeparator() 851 menu.addSeparator()
843 act = menu.addAction(self.trUtf8("Open Image in New Tab"), 852 menu.addAction(UI.PixmapCache.getIcon("openNewTab.png"),
844 self.__openLinkInNewTab) 853 self.trUtf8("Open Image in New Tab"),
845 act.setData(hit.imageUrl()) 854 self.__openLinkInNewTab).setData(hit.imageUrl())
846 menu.addSeparator() 855 menu.addSeparator()
847 menu.addAction(self.trUtf8("Save Image"), self.__downloadImage) 856 menu.addAction(UI.PixmapCache.getIcon("download.png"),
857 self.trUtf8("Save Image"), self.__downloadImage)
848 menu.addAction(self.trUtf8("Copy Image to Clipboard"), self.__copyImage) 858 menu.addAction(self.trUtf8("Copy Image to Clipboard"), self.__copyImage)
849 act = menu.addAction(self.trUtf8("Copy Image Location to Clipboard"), 859 menu.addAction(UI.PixmapCache.getIcon("editCopy.png"),
850 self.__copyImageLocation) 860 self.trUtf8("Copy Image Location to Clipboard"),
851 act.setData(hit.imageUrl().toString()) 861 self.__copyImageLocation).setData(hit.imageUrl().toString())
862 menu.addAction(UI.PixmapCache.getIcon("mailSend.png"),
863 self.trUtf8("Send Image Link"), self.__sendLink).setData(hit.imageUrl())
852 menu.addSeparator() 864 menu.addSeparator()
853 act = menu.addAction(self.trUtf8("Block Image"), self.__blockImage) 865 menu.addAction(UI.PixmapCache.getIcon("adBlockPlus.png"),
854 act.setData(hit.imageUrl().toString()) 866 self.trUtf8("Block Image"), self.__blockImage)\
867 .setData(hit.imageUrl().toString())
855 if Preferences.getHelp("VirusTotalEnabled") and \ 868 if Preferences.getHelp("VirusTotalEnabled") and \
856 Preferences.getHelp("VirusTotalServiceKey") != "": 869 Preferences.getHelp("VirusTotalServiceKey") != "":
857 act = menu.addAction(UI.PixmapCache.getIcon("virustotal.png"), 870 menu.addAction(UI.PixmapCache.getIcon("virustotal.png"),
858 self.trUtf8("Scan Image with VirusTotal"), self.__virusTotal) 871 self.trUtf8("Scan Image with VirusTotal"), self.__virusTotal)\
859 act.setData(hit.imageUrl()) 872 .setData(hit.imageUrl())
873
874 element = hit.element()
875 if not element.isNull() and \
876 element.tagName().lower() in ["input", "textarea", "video", "audio"]:
877 if menu.isEmpty():
878 self.page().createStandardContextMenu().exec_(evt.globalPos())
879 return
860 880
861 if not menu.isEmpty(): 881 if not menu.isEmpty():
862 menu.addSeparator() 882 menu.addSeparator()
863 menu.addAction(self.mw.newTabAct) 883 menu.addAction(self.mw.newTabAct)
864 menu.addAction(self.mw.newAct) 884 menu.addAction(self.mw.newAct)
865 menu.addSeparator() 885 menu.addSeparator()
866 menu.addAction(self.mw.saveAsAct) 886 menu.addAction(self.mw.saveAsAct)
867 menu.addSeparator() 887 menu.addSeparator()
868 menu.addAction(self.trUtf8("Bookmark this Page"), self.addBookmark) 888
889 if frameAtPos and self.page().mainFrame() != frameAtPos:
890 self.__clickedFrame = frameAtPos
891 fmenu = QMenu(self.trUtf8("This Frame"))
892 frameUrl = self.__clickedFrame.url()
893 if frameUrl.isValid():
894 fmenu.addAction(self.trUtf8("Show &only this frame"),
895 self.__loadClickedFrame)
896 fmenu.addAction(UI.PixmapCache.getIcon("openNewTab.png"),
897 self.trUtf8("Show in new &tab"),
898 self.__openLinkInNewTab).setData(self.__clickedFrame.url())
899 fmenu.addSeparator()
900 fmenu.addAction(UI.PixmapCache.getIcon("print.png"),
901 self.trUtf8("&Print"), self.__printClickedFrame)
902 fmenu.addAction(UI.PixmapCache.getIcon("printPreview.png"),
903 self.trUtf8("Print Preview"), self.__printPreviewClickedFrame)
904 fmenu.addAction(UI.PixmapCache.getIcon("printPdf.png"),
905 self.trUtf8("Print as PDF"), self.__printPdfClickedFrame)
906 fmenu.addSeparator()
907 fmenu.addAction(UI.PixmapCache.getIcon("zoomIn.png"),
908 self.trUtf8("Zoom &in"), self.__zoomInClickedFrame)
909 fmenu.addAction(UI.PixmapCache.getIcon("zoomReset.png"),
910 self.trUtf8("Zoom &reset"), self.__zoomResetClickedFrame)
911 fmenu.addAction(UI.PixmapCache.getIcon("zoomOut.png"),
912 self.trUtf8("Zoom &out"), self.__zoomOutClickedFrame)
913 fmenu.addSeparator()
914 fmenu.addAction(self.trUtf8("Show frame so&urce"),
915 self.__showClickedFrameSource)
916
917 menu.addMenu(fmenu)
918 menu.addSeparator()
919
920 menu.addAction(UI.PixmapCache.getIcon("bookmark22.png"),
921 self.trUtf8("Bookmark this Page"), self.addBookmark)
922 menu.addAction(UI.PixmapCache.getIcon("mailSend.png"),
923 self.trUtf8("Send Page Link"), self.__sendLink).setData(self.url())
869 menu.addSeparator() 924 menu.addSeparator()
870 menu.addAction(self.mw.backAct) 925 menu.addAction(self.mw.backAct)
871 menu.addAction(self.mw.forwardAct) 926 menu.addAction(self.mw.forwardAct)
872 menu.addAction(self.mw.homeAct) 927 menu.addAction(self.mw.homeAct)
873 menu.addSeparator() 928 menu.addSeparator()
874 menu.addAction(self.mw.zoomInAct) 929 menu.addAction(self.mw.zoomInAct)
930 menu.addAction(self.mw.zoomResetAct)
875 menu.addAction(self.mw.zoomOutAct) 931 menu.addAction(self.mw.zoomOutAct)
876 menu.addSeparator() 932 menu.addSeparator()
877 if self.selectedText(): 933 if self.selectedText():
878 menu.addAction(self.mw.copyAct) 934 menu.addAction(self.mw.copyAct)
935 menu.addAction(UI.PixmapCache.getIcon("mailSend.png"),
936 self.trUtf8("Send Text"), self.__sendLink).setData(self.selectedText())
879 menu.addAction(self.mw.findAct) 937 menu.addAction(self.mw.findAct)
880 menu.addSeparator() 938 menu.addSeparator()
881 if self.selectedText(): 939 if self.selectedText():
882 self.__searchMenu = menu.addMenu(self.trUtf8("Search with...")) 940 self.__searchMenu = menu.addMenu(self.trUtf8("Search with..."))
883 941
884 engineNames = self.mw.openSearchManager().allEnginesNames() 942 engineNames = self.mw.openSearchManager().allEnginesNames()
885 for engineName in engineNames: 943 for engineName in engineNames:
886 engine = self.mw.openSearchManager().engine(engineName) 944 engine = self.mw.openSearchManager().engine(engineName)
887 act = OpenSearchEngineAction(engine, self.__searchMenu) 945 self.__searchMenu.addAction(
888 self.__searchMenu.addAction(act) 946 OpenSearchEngineAction(engine, self.__searchMenu).setData(engineName))
889 act.setData(engineName)
890 self.__searchMenu.triggered.connect(self.__searchRequested) 947 self.__searchMenu.triggered.connect(self.__searchRequested)
891 948
892 menu.addSeparator() 949 menu.addSeparator()
950
951 languages = Preferences.toList(
952 Preferences.Prefs.settings.value("Help/AcceptLanguages",
953 HelpLanguagesDialog.defaultAcceptLanguages()))
954 if languages:
955 language = languages[0]
956 langCode = language.split("[")[1][:2]
957 googleTranslatorUrl = QUrl(
958 "http://translate.google.com/#auto|{0}|{1}".format(
959 langCode,self.selectedText()))
960 menu.addAction(UI.PixmapCache.getIcon("translate.png"),
961 self.trUtf8("Google Translate"), self.__openLinkInNewTab)\
962 .setData(googleTranslatorUrl)
963 wiktionaryUrl = QUrl(
964 "http://{0}.wiktionary.org/wiki/Special:Search?search={1}".format(
965 langCode, self.selectedText()))
966 menu.addAction(UI.PixmapCache.getIcon("wikipedia.png"),
967 self.trUtf8("Dictionary"), self.__openLinkInNewTab)\
968 .setData(wiktionaryUrl)
969 menu.addSeparator()
970
971 guessedUrl = QUrl.fromUserInput(self.selectedText().strip())
972 if self.__isUrlValid(guessedUrl):
973 menu.addAction(self.trUtf8("Go to web address"), self.__openLinkInNewTab)\
974 .setData(guessedUrl)
975 menu.addSeparator()
893 976
894 if hasattr(QtWebKit, 'QWebElement'): 977 if hasattr(QtWebKit, 'QWebElement'):
895 element = hit.element() 978 element = hit.element()
896 if not element.isNull() and \ 979 if not element.isNull() and \
897 element.tagName().lower() == "input" and \ 980 element.tagName().lower() == "input" and \
898 element.attribute("type", "text") == "text": 981 element.attribute("type", "text") == "text":
899 act = menu.addAction(self.trUtf8("Add to web search toolbar"), 982 menu.addAction(self.trUtf8("Add to web search toolbar"),
900 self.__addSearchEngine) 983 self.__addSearchEngine).setData(element)
901 act.setData(element)
902 menu.addSeparator() 984 menu.addSeparator()
903 985
904 menu.addAction(self.trUtf8("Web Inspector..."), self.__webInspector) 986 menu.addAction(self.trUtf8("Web Inspector..."), self.__webInspector)
905 987
906 menu.exec_(evt.globalPos()) 988 menu.exec_(evt.globalPos())
989
990 def __isUrlValid(self, url):
991 """
992 Private method to check a URL for validity.
993
994 @param url URL to be checked (QUrl)
995 @return flag indicating a valid URL (boolean)
996 """
997 return url.isValid() and \
998 bool(url.host()) and \
999 bool(url.scheme()) and \
1000 "." in url.host()
907 1001
908 def __openLinkInNewTab(self): 1002 def __openLinkInNewTab(self):
909 """ 1003 """
910 Private method called by the context menu to open a link in a new window. 1004 Private method called by the context menu to open a link in a new window.
911 """ 1005 """
928 return 1022 return
929 1023
930 dlg = AddBookmarkDialog() 1024 dlg = AddBookmarkDialog()
931 dlg.setUrl(bytes(url.toEncoded()).decode()) 1025 dlg.setUrl(bytes(url.toEncoded()).decode())
932 dlg.exec_() 1026 dlg.exec_()
1027
1028 def __sendLink(self):
1029 """
1030 Private slot to send a link via email.
1031 """
1032 act = self.sender()
1033 data = act.data()
1034 if isinstance(data, QUrl) and data.isEmpty():
1035 return
1036
1037 if isinstance(data, QUrl):
1038 data = data.toString()
1039 QDesktopServices.openUrl(QUrl("mailto:?body=" + data))
933 1040
934 def __downloadLink(self): 1041 def __downloadLink(self):
935 """ 1042 """
936 Private slot to download a link and save it to disk. 1043 Private slot to download a link and save it to disk.
937 """ 1044 """
1735 Public method to check, if the loaded page has RSS links. 1842 Public method to check, if the loaded page has RSS links.
1736 1843
1737 @return flag indicating the presence of RSS links (boolean) 1844 @return flag indicating the presence of RSS links (boolean)
1738 """ 1845 """
1739 return len(self.__rss) > 0 1846 return len(self.__rss) > 0
1847
1848 ############################################################################
1849 ## Clicked Frame slots
1850 ############################################################################
1851
1852 def __loadClickedFrame(self):
1853 """
1854 Private slot to load the selected frame only.
1855 """
1856 self.setSource(self.__clickedFrame.url())
1857
1858 def __printClickedFrame(self):
1859 """
1860 Private slot to print the selected frame.
1861 """
1862 printer = QPrinter(mode=QPrinter.HighResolution)
1863 if Preferences.getPrinter("ColorMode"):
1864 printer.setColorMode(QPrinter.Color)
1865 else:
1866 printer.setColorMode(QPrinter.GrayScale)
1867 if Preferences.getPrinter("FirstPageFirst"):
1868 printer.setPageOrder(QPrinter.FirstPageFirst)
1869 else:
1870 printer.setPageOrder(QPrinter.LastPageFirst)
1871 printer.setPageMargins(
1872 Preferences.getPrinter("LeftMargin") * 10,
1873 Preferences.getPrinter("TopMargin") * 10,
1874 Preferences.getPrinter("RightMargin") * 10,
1875 Preferences.getPrinter("BottomMargin") * 10,
1876 QPrinter.Millimeter
1877 )
1878 printer.setPrinterName(Preferences.getPrinter("PrinterName"))
1879
1880 printDialog = QPrintDialog(printer, self)
1881 if printDialog.exec_() == QDialog.Accepted:
1882 try:
1883 self.__clickedFrame.print_(printer)
1884 except AttributeError:
1885 E5MessageBox.critical(self,
1886 self.trUtf8("eric5 Web Browser"),
1887 self.trUtf8("""<p>Printing is not available due to a bug in PyQt4."""
1888 """Please upgrade.</p>"""))
1889
1890 def __printPreviewClickedFrame(self):
1891 """
1892 Private slot to show a print preview of the clicked frame.
1893 """
1894 from PyQt4.QtGui import QPrintPreviewDialog
1895
1896 printer = QPrinter(mode=QPrinter.HighResolution)
1897 if Preferences.getPrinter("ColorMode"):
1898 printer.setColorMode(QPrinter.Color)
1899 else:
1900 printer.setColorMode(QPrinter.GrayScale)
1901 if Preferences.getPrinter("FirstPageFirst"):
1902 printer.setPageOrder(QPrinter.FirstPageFirst)
1903 else:
1904 printer.setPageOrder(QPrinter.LastPageFirst)
1905 printer.setPageMargins(
1906 Preferences.getPrinter("LeftMargin") * 10,
1907 Preferences.getPrinter("TopMargin") * 10,
1908 Preferences.getPrinter("RightMargin") * 10,
1909 Preferences.getPrinter("BottomMargin") * 10,
1910 QPrinter.Millimeter
1911 )
1912 printer.setPrinterName(Preferences.getPrinter("PrinterName"))
1913
1914 preview = QPrintPreviewDialog(printer, self)
1915 preview.paintRequested.connect(self.__generatePrintPreviewClickedFrame)
1916 preview.exec_()
1917
1918 def __generatePrintPreviewClickedFrame(self, printer):
1919 """
1920 Private slot to generate a print preview of the clicked frame.
1921
1922 @param printer reference to the printer object (QPrinter)
1923 """
1924 try:
1925 self.__clickedFrame.print_(printer)
1926 except AttributeError:
1927 E5MessageBox.critical(self,
1928 self.trUtf8("eric5 Web Browser"),
1929 self.trUtf8("""<p>Printing is not available due to a bug in PyQt4."""
1930 """Please upgrade.</p>"""))
1931 return
1932
1933 def __printPdfClickedFrame(self):
1934 """
1935 Private slot to print the selected frame to PDF.
1936 """
1937 printer = QPrinter(mode=QPrinter.HighResolution)
1938 if Preferences.getPrinter("ColorMode"):
1939 printer.setColorMode(QPrinter.Color)
1940 else:
1941 printer.setColorMode(QPrinter.GrayScale)
1942 printer.setPrinterName(Preferences.getPrinter("PrinterName"))
1943 printer.setOutputFormat(QPrinter.PdfFormat)
1944 name = self.__clickedFrame.url().path().rsplit('/', 1)[-1]
1945 if name:
1946 name = name.rsplit('.', 1)[0]
1947 name += '.pdf'
1948 printer.setOutputFileName(name)
1949
1950 printDialog = QPrintDialog(printer, self)
1951 if printDialog.exec_() == QDialog.Accepted:
1952 try:
1953 self.__clickedFrame.print_(printer)
1954 except AttributeError:
1955 E5MessageBox.critical(self,
1956 self.trUtf8("eric5 Web Browser"),
1957 self.trUtf8("""<p>Printing is not available due to a bug in PyQt4."""
1958 """Please upgrade.</p>"""))
1959 return
1960
1961 def __zoomInClickedFrame(self):
1962 """
1963 Private slot to zoom into the clicked frame.
1964 """
1965 index = self.__levelForZoom(int(self.__clickedFrame.zoomFactor() * 100))
1966 if index < len(self.__zoomLevels) - 1:
1967 self.__clickedFrame.setZoomFactor(self.__zoomLevels[index + 1] / 100)
1968
1969 def __zoomResetClickedFrame(self):
1970 """
1971 Private slot to reset the zoom factor of the clicked frame.
1972 """
1973 self.__clickedFrame.setZoomFactor(self.__currentZoom / 100)
1974
1975 def __zoomOutClickedFrame(self):
1976 """
1977 Private slot to zoom out of the clicked frame.
1978 """
1979 index = self.__levelForZoom(int(self.__clickedFrame.zoomFactor() * 100))
1980 if index > 0:
1981 self.__clickedFrame.setZoomFactor(self.__zoomLevels[index - 1] / 100)
1982
1983 def __showClickedFrameSource(self):
1984 """
1985 Private slot to show the source of the clicked frame.
1986 """
1987 from QScintilla.MiniEditor import MiniEditor
1988 src = self.__clickedFrame.toHtml()
1989 editor = MiniEditor(parent=self)
1990 editor.setText(src, "Html")
1991 editor.setLanguage("dummy.html")
1992 editor.show()
1740 1993
1741 1994
1742 def contentSniff(data): 1995 def contentSniff(data):
1743 """ 1996 """
1744 Module function to do some content sniffing to check, if the data is HTML. 1997 Module function to do some content sniffing to check, if the data is HTML.

eric ide

mercurial