Continued porting the web browser. QtWebEngine

Fri, 12 Feb 2016 19:12:03 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 12 Feb 2016 19:12:03 +0100
branch
QtWebEngine
changeset 4733
ae291a307ea6
parent 4732
5ac4fc1dfc20
child 4734
ce0b1f024da9

Continued porting the web browser.

- added the fullscreen (partly)
- added capability to be opened from the IDE
- fixed adding a bookmark

UI/UserInterface.py file | annotate | diff | comparison | revisions
WebBrowser/Tools/Scripts.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
--- a/UI/UserInterface.py	Thu Feb 11 20:27:07 2016 +0100
+++ b/UI/UserInterface.py	Fri Feb 12 19:12:03 2016 +0100
@@ -9,7 +9,7 @@
 
 from __future__ import unicode_literals
 try:
-    str = unicode
+    str = unicode       # __IGNORE_EXCEPTION__
 except NameError:
     pass
 
@@ -32,6 +32,15 @@
     WEBKIT_AVAILABLE = True
 except ImportError:
     WEBKIT_AVAILABLE = False
+# TODO: adjust this to 5.6.0 when done
+if qVersion() < "5.5.0":
+    WEBENGINE_AVAILABLE = False
+else:
+    try:
+        from PyQt5 import QtWebEngineWidgets    # __IGNORE_WARNING__
+        WEBENGINE_AVAILABLE = True
+    except ImportError:
+        WEBENGINE_AVAILABLE = False
 
 from .Info import Version, BugAddress, Program, FeatureAddress
 from . import Config
@@ -468,10 +477,16 @@
         self.__initExternalToolsActions()
         
         # create a dummy help window for shortcuts handling
-        if WEBKIT_AVAILABLE:
+        if WEBENGINE_AVAILABLE:
+            from WebBrowser.WebBrowserWindow import WebBrowserWindow
+            self.dummyHelpViewer = \
+                WebBrowserWindow(None, '.', None, 'web_browser', True, True)
+        elif WEBKIT_AVAILABLE:
             from Helpviewer.HelpWindow import HelpWindow
             self.dummyHelpViewer = \
                 HelpWindow(None, '.', None, 'help viewer', True, True)
+        else:
+            self.dummyHelpViewer = None
         
         # register all relevant objects
         splash.showMessage(self.tr("Registering Objects..."))
@@ -486,7 +501,7 @@
         e5App().registerObject("TaskViewer", self.taskViewer)
         e5App().registerObject("TemplateViewer", self.templateViewer)
         e5App().registerObject("Shell", self.shell)
-        if WEBKIT_AVAILABLE:
+        if self.dummyHelpViewer is not None:
             e5App().registerObject("DummyHelpViewer", self.dummyHelpViewer)
         e5App().registerObject("PluginManager", self.pluginManager)
         e5App().registerObject("ToolbarManager", self.toolbarManager)
@@ -1596,7 +1611,7 @@
         self.whatsThisAct.triggered.connect(self.__whatsThis)
         self.actions.append(self.whatsThisAct)
 
-        if WEBKIT_AVAILABLE:
+        if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE:
             self.helpviewerAct = E5Action(
                 self.tr('Helpviewer'),
                 UI.PixmapCache.getIcon("help.png"),
@@ -1925,7 +1940,7 @@
         self.hexEditorAct.triggered.connect(self.__openHexEditor)
         self.actions.append(self.hexEditorAct)
 
-        if WEBKIT_AVAILABLE:
+        if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE:
             self.webBrowserAct = E5Action(
                 self.tr('eric6 Web Browser'),
                 UI.PixmapCache.getIcon("ericWeb.png"),
@@ -5213,12 +5228,17 @@
             if not homeUrl.scheme():
                 home = QUrl.fromLocalFile(home).toString()
         
-        if WEBKIT_AVAILABLE:
+        if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE:
             if not (useSingle or Preferences.getHelp("SingleHelpWindow")) or \
                self.helpWindow is None:
-                from Helpviewer.HelpWindow import HelpWindow
-                help = HelpWindow(home, '.', None, 'help viewer', True,
-                                  searchWord=searchWord)
+                if WEBENGINE_AVAILABLE:
+                    from WebBrowser.WebBrowserWindow import WebBrowserWindow
+                    help = WebBrowserWindow(home, '.', None, 'web_browser',
+                                            True, searchWord=searchWord)
+                elif WEBKIT_AVAILABLE:
+                    from Helpviewer.HelpWindow import HelpWindow
+                    help = HelpWindow(home, '.', None, 'help viewer', True,
+                                      searchWord=searchWord)
 
                 if QApplication.desktop().width() > 400 and \
                    QApplication.desktop().height() > 500:
@@ -5228,7 +5248,10 @@
                 
                 if useSingle or Preferences.getHelp("SingleHelpWindow"):
                     self.helpWindow = help
-                    self.helpWindow.helpClosed.connect(self.__helpClosed)
+                    try:
+                        self.helpWindow.webBrowserClosed.connect(self.__helpClosed)
+                    except AttributeError:
+                        self.helpWindow.helpClosed.connect(self.__helpClosed)
                     self.preferencesChanged.connect(
                         self.helpWindow.preferencesChanged)
                     self.masterPasswordChanged.connect(
@@ -5284,7 +5307,7 @@
             (boolean)
         @return reference to the help window instance (HelpWindow)
         """
-        if WEBKIT_AVAILABLE:
+        if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE:
             if self.helpWindow is None:
                 self.launchHelpViewer("", useSingle=True)
             self.helpWindow.raise_()
--- a/WebBrowser/Tools/Scripts.py	Thu Feb 11 20:27:07 2016 +0100
+++ b/WebBrowser/Tools/Scripts.py	Fri Feb 12 19:12:03 2016 +0100
@@ -154,3 +154,27 @@
             return res;
         }})()"""
     return source.format(pos.x(), pos.y())
+
+
+def getAllMetaAttributes():
+    """
+    Function generating a script to extract all meta attributes of a web page.
+    
+    @return script to extract meta attributes
+    @rtype str
+    """
+    source = """
+        (function() {
+            var out = [];
+            var meta = document.getElementsByTagName('meta');
+            for (var i = 0; i < meta.length; ++i) {
+                var e = meta[i];
+                out.push({
+                    name: e.getAttribute('name'),
+                    content: e.getAttribute('content'),
+                    httpequiv: e.getAttribute('http-equiv')
+                });
+            }
+            return out;
+            })()"""
+    return source
--- a/WebBrowser/WebBrowserWindow.py	Thu Feb 11 20:27:07 2016 +0100
+++ b/WebBrowser/WebBrowserWindow.py	Fri Feb 12 19:12:03 2016 +0100
@@ -1190,17 +1190,17 @@
             self.pageSourceAct.triggered.connect(self.__showPageSource)
         self.__actions.append(self.pageSourceAct)
         self.addAction(self.pageSourceAct)
-##        
-##        self.fullScreenAct = E5Action(
-##            self.tr('Full Screen'),
-##            UI.PixmapCache.getIcon("windowFullscreen.png"),
-##            self.tr('&Full Screen'),
-##            QKeySequence(self.tr('F11')), 0,
-##            self, 'webbrowser_view_full_scree')
-##        if not self.__initShortcutsOnly:
-##            self.fullScreenAct.triggered.connect(self.__viewFullScreen)
-##        self.__actions.append(self.fullScreenAct)
-##        self.addAction(self.fullScreenAct)
+        
+        self.fullScreenAct = E5Action(
+            self.tr('Full Screen'),
+            UI.PixmapCache.getIcon("windowFullscreen.png"),
+            self.tr('&Full Screen'),
+            QKeySequence(self.tr('F11')), 0,
+            self, 'webbrowser_view_full_scree')
+        if not self.__initShortcutsOnly:
+            self.fullScreenAct.triggered.connect(self.__viewFullScreen)
+        self.__actions.append(self.fullScreenAct)
+        self.addAction(self.fullScreenAct)
         
         self.nextTabAct = E5Action(
             self.tr('Show next tab'),
@@ -1246,7 +1246,8 @@
         if not self.__initShortcutsOnly:
             self.prefAct.triggered.connect(self.__showPreferences)
         self.__actions.append(self.prefAct)
-
+        
+        # TODO: Languages
 ##        self.acceptedLanguagesAct = E5Action(
 ##            self.tr('Languages'),
 ##            UI.PixmapCache.getIcon("flag.png"),
@@ -1295,6 +1296,7 @@
 ##                self.__showFlashCookiesManagement)
 ##        self.__actions.append(self.flashCookiesAct)
         
+        # TODO: Offline Storage
 ##        self.offlineStorageAct = E5Action(
 ##            self.tr('Offline Storage'),
 ##            UI.PixmapCache.getIcon("preferences-html5.png"),
@@ -1311,6 +1313,7 @@
 ##                self.__showOfflineStorageConfiguration)
 ##        self.__actions.append(self.offlineStorageAct)
         
+        # TODO: PIM
 ##        self.personalDataAct = E5Action(
 ##            self.tr('Personal Information'),
 ##            UI.PixmapCache.getIcon("pim.png"),
@@ -1329,6 +1332,7 @@
 ##                self.__showPersonalInformationDialog)
 ##        self.__actions.append(self.personalDataAct)
         
+        # TODO: GreaseMonkey
 ##        self.greaseMonkeyAct = E5Action(
 ##            self.tr('GreaseMonkey Scripts'),
 ##            UI.PixmapCache.getIcon("greaseMonkey.png"),
@@ -1490,6 +1494,7 @@
 ##                    self.__searchEngine.reindexDocumentation)
 ##            self.__actions.append(self.reindexDocumentationAct)
         
+        # TODO: Clear Private Data
 ##        self.clearPrivateDataAct = E5Action(
 ##            self.tr('Clear private data'),
 ##            self.tr('&Clear private data'),
@@ -1506,7 +1511,7 @@
 ##            self.clearPrivateDataAct.triggered.connect(
 ##                self.__clearPrivateData)
 ##        self.__actions.append(self.clearPrivateDataAct)
-        
+##        
 ##        self.clearIconsAct = E5Action(
 ##            self.tr('Clear icons database'),
 ##            self.tr('Clear &icons database'),
@@ -1802,7 +1807,7 @@
 ##            menu.addAction(self.zoomTextOnlyAct)
         menu.addSeparator()
         menu.addAction(self.pageSourceAct)
-##        menu.addAction(self.fullScreenAct)
+        menu.addAction(self.fullScreenAct)
         self.__textEncodingMenu = menu.addMenu(
             self.tr("Text Encoding"))
         self.__textEncodingMenu.aboutToShow.connect(
@@ -1965,8 +1970,8 @@
         viewtb.addAction(self.zoomInAct)
         viewtb.addAction(self.zoomResetAct)
         viewtb.addAction(self.zoomOutAct)
-##        viewtb.addSeparator()
-##        viewtb.addAction(self.fullScreenAct)
+        viewtb.addSeparator()
+        viewtb.addAction(self.fullScreenAct)
         
         findtb = self.addToolBar(self.tr("Find"))
         findtb.setObjectName("FindToolBar")
@@ -2318,12 +2323,29 @@
         Private slot called to add the displayed file to the bookmarks.
         """
         view = self.currentBrowser()
-        url = bytes(view.url().toEncoded()).decode()
+        urlStr = bytes(view.url().toEncoded()).decode()
         title = view.title()
+        
+        script = Scripts.getAllMetaAttributes()
+        view.page().runJavaScript(
+            script,
+            lambda res: self.__addBookmarkCallback(urlStr, title, res))
+    
+    def __addBookmarkCallback(self, url, title, res):
+        """
+        Private callback method of __addBookmark().
+        
+        @param url URL for the bookmark
+        @type str
+        @param title title for the bookmark
+        @type str
+        @param res result of the JavaScript
+        @type list
+        """
         description = ""
-        meta = view.page().mainFrame().metaData()
-        if "description" in meta:
-            description = meta["description"][0]
+        for meta in res:
+            if meta["name"] == "description":
+                description = meta["content"]
         
         from .Bookmarks.AddBookmarkDialog import AddBookmarkDialog
         dlg = AddBookmarkDialog()
@@ -2371,16 +2393,41 @@
         if folder is None:
             return
         
+        for view in self.__tabWidget.browsers():
+            urlStr = bytes(view.url().toEncoded()).decode()
+            title = view.title()
+            
+            script = Scripts.getAllMetaAttributes()
+            view.page().runJavaScript(
+                script,
+                lambda res: self.__bookmarkAllCallback(folder, urlStr,
+                                                       title, res))
+    
+    def __bookmarkAllCallback(self, folder, url, title, res):
+        """
+        Private callback method of __addBookmark().
+        
+        @param folder reference to the bookmarks folder
+        @type BookmarkNode
+        @param url URL for the bookmark
+        @type str
+        @param title title for the bookmark
+        @type str
+        @param res result of the JavaScript
+        @type list
+        """
+        description = ""
+        for meta in res:
+            if meta["name"] == "description":
+                description = meta["content"]
+        
         from .Bookmarks.BookmarkNode import BookmarkNode
-        for browser in self.__tabWidget.browsers():
-            bookmark = BookmarkNode(BookmarkNode.Bookmark)
-            bookmark.url = bytes(browser.url().toEncoded()).decode()
-            bookmark.title = browser.title()
-            meta = browser.page().mainFrame().metaData()
-            if "description" in meta:
-                bookmark.desc = meta["description"][0]
-            
-            self.bookmarksManager().addBookmark(folder, bookmark)
+        bookmark = BookmarkNode(BookmarkNode.Bookmark)
+        bookmark.url = url
+        bookmark.title = title
+        bookmark.desc = description
+        
+        self.bookmarksManager().addBookmark(folder, bookmark)
         
     def __find(self):
         """
@@ -2565,25 +2612,26 @@
 ##            QWebSettings.ZoomTextOnly, textOnly)
 ##        self.zoomTextOnlyChanged.emit(textOnly)
 ##    
-    # TODO: Full Screen
-##    def __viewFullScreen(self):
-##        """
-##        Private slot called to toggle fullscreen mode.
-##        """
-##        if self.__isFullScreen():
-##            # switch back to normal
-##            self.setWindowState(self.windowState() & ~Qt.WindowFullScreen)
-##            self.menuBar().show()
-##            self.fullScreenAct.setIcon(
-##                UI.PixmapCache.getIcon("windowFullscreen.png"))
-##            self.fullScreenAct.setIconText(self.tr('Full Screen'))
-##        else:
-##            # switch to full screen
-##            self.setWindowState(self.windowState() | Qt.WindowFullScreen)
-##            self.menuBar().hide()
-##            self.fullScreenAct.setIcon(
-##                UI.PixmapCache.getIcon("windowRestore.png"))
-##            self.fullScreenAct.setIconText(self.tr('Restore Window'))
+    def __viewFullScreen(self):
+        """
+        Private slot called to toggle fullscreen mode.
+        """
+        if self.__isFullScreen():
+            # TODO: Full Screen - web pages need to be toggled separately (Qt 5.6)
+            # switch back to normal
+            self.setWindowState(self.windowState() & ~Qt.WindowFullScreen)
+            self.menuBar().show()
+            self.fullScreenAct.setIcon(
+                UI.PixmapCache.getIcon("windowFullscreen.png"))
+            self.fullScreenAct.setIconText(self.tr('Full Screen'))
+        else:
+            # switch to full screen
+            self.setWindowState(self.windowState() | Qt.WindowFullScreen)
+            self.menuBar().hide()
+            self.fullScreenAct.setIcon(
+                UI.PixmapCache.getIcon("windowRestore.png"))
+            self.fullScreenAct.setIconText(self.tr('Restore Window'))
+            # TODO: Full Screen - web pages need to be toggled separately (Qt 5.6)
     
     def __isFullScreen(self):
         """
@@ -2723,6 +2771,7 @@
         """
         Private slot to set the preferences.
         """
+        # TODO: Preferences
 ##        from Preferences.ConfigurationDialog import ConfigurationDialog
 ##        dlg = ConfigurationDialog(
 ##            self, 'Configuration', True, fromEric=self.__fromEric,
@@ -2752,14 +2801,18 @@
         
         self.__initWebEngineSettings()
         
+        # TODO: NetworkManager
 ##        self.networkAccessManager().preferencesChanged()
 ##        
+        # TODO: History
 ##        self.historyManager().preferencesChanged()
 ##        
         self.__tabWidget.preferencesChanged()
         
+        # TODO: OpenSearch
 ##        self.searchEdit.preferencesChanged()
 ##        
+        # TODO: VirusTotal
 ##        self.__virusTotal.preferencesChanged()
 ##        if not Preferences.getWebBrowser("VirusTotalEnabled") or \
 ##           Preferences.getWebBrowser("VirusTotalServiceKey") == "":
@@ -2778,6 +2831,7 @@
         @param oldPassword current master password (string)
         @param newPassword new master password (string)
         """
+        # TODO: PasswordManager
 ##        from Preferences.ConfigurationDialog import ConfigurationDialog
 ##        self.passwordManager().masterPasswordChanged(oldPassword, newPassword)
 ##        if self.__fromEric and isinstance(self.sender(), ConfigurationDialog):

eric ide

mercurial