Continued porting the web browser. QtWebEngine

Sat, 27 Feb 2016 20:51:44 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 27 Feb 2016 20:51:44 +0100
branch
QtWebEngine
changeset 4781
15d416f1eca5
parent 4780
1d203a177b16
child 4782
4ad656e4ebec

Continued porting the web browser.

- ported the web inspector

Preferences/__init__.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserTabWidget.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserView.py file | annotate | diff | comparison | revisions
WebBrowser/WebInspector.py file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
--- a/Preferences/__init__.py	Sat Feb 27 18:19:09 2016 +0100
+++ b/Preferences/__init__.py	Sat Feb 27 20:51:44 2016 +0100
@@ -1027,6 +1027,8 @@
         "SearchLanguage": QLocale().language(),
         "RssFeeds": [],
         "ShowPreview": True,
+        "WebInspectorPort": 42024,
+        "WebInspectorEnabled": False,
         # Grease Monkey
         "GreaseMonkeyDisabledScripts": [],
         # Downloads
@@ -1258,6 +1260,7 @@
         "HexEditorGeometry": QByteArray(),
         "MainGeometry": QByteArray(),
         "MainMaximized": False,
+        "WebInspectorGeometry": QByteArray(),
     }
 
     # if true, revert layouts to factory defaults
@@ -2756,7 +2759,7 @@
                  "MinimumLogicalFontSize", "HistoryLimit",
                  "DownloadManagerRemovePolicy","SyncType", "SyncFtpPort",
                  "SyncFtpIdleTimeout", "SyncEncryptionKeyLength",
-                 "SearchLanguage",]:
+                 "SearchLanguage", "WebInspectorPort"]:
         return int(prefClass.settings.value(
             "WebBrowser/" + key, prefClass.webBrowserDefaults[key]))
 ##    elif key in ["DiskCacheEnabled", "FilterTrackingCookies",
@@ -2782,7 +2785,7 @@
                  "SyncEnabled", "SyncBookmarks", "SyncHistory",
                  "SyncPasswords", "SyncUserAgents", "SyncSpeedDial",
                  "SyncEncryptData", "SyncEncryptPasswordsOnly",
-                 "ShowPreview",
+                 "ShowPreview", "WebInspectorEnabled",
                  ]:
         return toBool(prefClass.settings.value(
             "WebBrowser/" + key, prefClass.webBrowserDefaults[key]))
--- a/WebBrowser/WebBrowserTabWidget.py	Sat Feb 27 18:19:09 2016 +0100
+++ b/WebBrowser/WebBrowserTabWidget.py	Sat Feb 27 20:51:44 2016 +0100
@@ -65,6 +65,10 @@
         
         self.__mainWindow = parent
         
+        if Preferences.getWebBrowser("WebInspectorEnabled"):
+            os.environ["QTWEBENGINE_REMOTE_DEBUGGING"] = \
+                str(Preferences.getWebBrowser("WebInspectorPort"))
+        
         self.setUsesScrollButtons(True)
         self.setDocumentMode(True)
         self.setElideMode(Qt.ElideNone)
@@ -485,8 +489,7 @@
         
         self.__closedTabsManager.recordBrowser(browser, index)
         
-        # TODO: WebInspector
-##        browser.closeWebInspector()
+        browser.closeWebInspector()
         browser.home()
         self.removeTab(index)
         self.browserClosed.emit(browser)
--- a/WebBrowser/WebBrowserView.py	Sat Feb 27 18:19:09 2016 +0100
+++ b/WebBrowser/WebBrowserView.py	Sat Feb 27 20:51:44 2016 +0100
@@ -35,6 +35,8 @@
 
 from .Network.LoadRequest import LoadRequest, LoadRequestOperations
 
+from . import WebInspector
+
 import Preferences
 import UI.PixmapCache
 import Globals
@@ -102,6 +104,7 @@
         self.__siteIcon = QIcon()
         self.__menu = QMenu(self)
         self.__clickedPos = QPoint()
+        self.__firstLoad = False
         
         self.__currentZoom = 100
         self.__zoomLevels = WebBrowserView.ZoomLevels[:]
@@ -145,11 +148,17 @@
         
         self.__mw.personalInformationManager().connectPage(self.page())
         
-        # TODO: WebInspector
-##        self.__inspector = None
+        self.__inspector = None
+        WebInspector.registerView(self)
         
         self.grabGesture(Qt.PinchGesture)
     
+    def __del__(self):
+        """
+        Special method doing some cleanup stuff.
+        """
+        WebInspector.unregisterView(self)
+    
 ##    def __addExternalBinding(self, frame=None):
 ##        """
 ##        Private slot to add javascript bindings for adding search providers.
@@ -208,6 +217,10 @@
         """
         if isinstance(urlOrRequest, QUrl):
             super(WebBrowserView, self).load(urlOrRequest)
+            
+            if not self.__firstLoad:
+                self.__firstLoad = True
+                WebInspector.pushView(self)
         elif isinstance(urlOrRequest, LoadRequest):
             reqUrl = urlOrRequest.url()
             if reqUrl.isEmpty():
@@ -588,11 +601,10 @@
 ##        if not hitTest.isContentEditable() and not hitTest.isContentSelected():
 ##            self.__menu.addAction(self.__mw.adBlockIcon().menuAction())
         
-        # TODO: WebInspector
-##        self.__menu.addSeparator()
-##        menu.addAction(
-##            UI.PixmapCache.getIcon("webInspector.png"),
-##            self.tr("Inspect Element..."), self.__webInspector)
+        self.__menu.addSeparator()
+        self.__menu.addAction(
+            UI.PixmapCache.getIcon("webInspector.png"),
+            self.tr("Inspect Element..."), self.__webInspector)
         
         if not self.__menu.isEmpty():
             pos = evt.globalPos()
@@ -1100,30 +1112,29 @@
             lambda res: self.__mw.openSearchManager().addEngineFromForm(
                 res, self))
     
-    # TODO: WebInspector
-##    def __webInspector(self):
-##        """
-##        Private slot to show the web inspector window.
-##        """
-##        if self.__inspector is None:
-##            from .HelpInspector import HelpInspector
-##            self.__inspector = HelpInspector()
-##            self.__inspector.setPage(self.page())
-##            self.__inspector.show()
-##        elif self.__inspector.isVisible():
-##            self.__inspector.hide()
-##        else:
-##            self.__inspector.show()
-##    
-##    def closeWebInspector(self):
-##        """
-##        Public slot to close the web inspector.
-##        """
-##        if self.__inspector is not None:
-##            if self.__inspector.isVisible():
-##                self.__inspector.hide()
-##            self.__inspector.deleteLater()
-##            self.__inspector = None
+    def __webInspector(self):
+        """
+        Private slot to show the web inspector window.
+        """
+        if self.__inspector is None:
+            from .WebInspector import WebInspector
+            self.__inspector = WebInspector()
+            self.__inspector.setView(self, True)
+            self.__inspector.show()
+        elif self.__inspector.isVisible():
+            self.__inspector.hide()
+        else:
+            self.__inspector.show()
+    
+    def closeWebInspector(self):
+        """
+        Public slot to close the web inspector.
+        """
+        if self.__inspector is not None:
+            if self.__inspector.isVisible():
+                self.__inspector.hide()
+            self.__inspector.deleteLater()
+            self.__inspector = None
     
     def addBookmark(self):
         """
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/WebInspector.py	Sat Feb 27 20:51:44 2016 +0100
@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a QWebEngineView to load the web inspector in.
+"""
+
+from __future__ import unicode_literals
+try:
+    str = unicode           # __IGNORE_EXCEPTION__
+except NameError:
+    pass
+
+import json
+
+from PyQt5.QtCore import QSize, QUrl
+from PyQt5.QtNetwork import QNetworkRequest
+from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
+
+import Preferences
+
+_VIEWS = []
+
+
+class WebInspector(QWebEngineView):
+    """
+    Class implementing a QWebEngineView to load the web inspector in.
+    """
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(WebInspector, self).__init__(parent)
+        
+        self.__view = None
+        self.__inspectElement = False
+        
+        self.__reloadGeometry()
+        
+        registerView(self)
+        
+        self.page().windowCloseRequested.connect(self.close)
+        self.page().loadFinished.connect(self.__loadFinished)
+    
+    def __del__(self):
+        """
+        Special method doing some cleanup stuff.
+        """
+        unregisterView(self)
+
+    def closeEvent(self, evt):
+        """
+        Protected method to save the geometry when closed.
+        
+        @param evt event object
+        @type QCloseEvent
+        """
+        Preferences.setGeometry("WebInspectorGeometry", self.saveGeometry())
+        super(WebInspector, self).closeEvent(evt)
+
+    def __reloadGeometry(self):
+        """
+        Private method to restore the geometry.
+        """
+        geom = Preferences.getGeometry("WebInspectorGeometry")
+        if geom.isEmpty():
+            s = QSize(600, 600)
+            self.resize(s)
+        else:
+            self.restoreGeometry(geom)
+    
+    def setView(self, view, inspectElement=False):
+        """
+        Public method to connect a view to this inspector.
+        
+        @param view reference to the view object
+        @type WebBrowserView
+        @param inspectElement flag indicating to start a web inspection
+        @type bool
+        """
+        self.__view = view
+        if not self.isEnabled():
+            return
+        
+        self.__inspectElement = inspectElement
+        
+        port = Preferences.getWebBrowser("WebInspectorPort")
+        inspectorUrl = QUrl("http://localhost:{0}".format(port))
+        
+        from WebBrowser.WebBrowserWindow import WebBrowserWindow
+        self.__reply = WebBrowserWindow.networkManager().get(
+            QNetworkRequest(inspectorUrl.resolved(QUrl("json/list"))))
+        self.__reply.finished.connect(self.__inspectorReplyFinished)
+    
+    def __inspectorReplyFinished(self):
+        """
+        Private slot handling the reply.
+        """
+        result = str(self.__reply.readAll(), encoding="utf8")
+        clients = json.loads(result)
+        
+        self.__reply.deleteLater()
+        self.__replay = None
+        
+        pageUrl = QUrl()
+        try:
+            index = _VIEWS.index(self.__view)
+        except ValueError:
+            index = -1
+        if len(clients) > index:
+            port = Preferences.getWebBrowser("WebInspectorPort")
+            inspectorUrl = QUrl("http://localhost:{0}".format(port))
+            
+            client = clients[index]
+            pageUrl = inspectorUrl.resolved(
+                QUrl(client["devtoolsFrontendUrl"]))
+        self.load(pageUrl)
+        pushView(self)
+        self.show()
+    
+    def inspectElement(self):
+        """
+        Public method to inspect an element.
+        """
+        self.__inspectElement = True
+    
+    def isEnabled(self):
+        """
+        Public method to check, if the web inspector is enabled.
+        
+        @return flag indicating the enabled state
+        @rtype bool
+        """
+        return Preferences.getWebBrowser("WebInspectorEnabled")
+    
+    def __loadFinished(self):
+        """
+        Private slot handling the finished signal.
+        """
+        if self.__inspectElement:
+            # TODO: Qt 5.6
+##            self.__view.triggerPageAction(QWebEnginePage.InspectElement)
+            self.__inspectElement = False
+
+
+def registerView(view):
+    """
+    Function to register a view.
+    
+    @param view reference to the view
+    @type WebBrowserView
+    """
+    _VIEWS.insert(0, view)
+
+
+def unregisterView(view):
+    """
+    Function to unregister a view.
+    
+    @param view reference to the view
+    @type WebBrowserView
+    """
+    if view in _VIEWS:
+        _VIEWS.remove(view)
+
+
+def pushView(view):
+    """
+    Function to push a view to the front of the list.
+    
+    @param view reference to the view
+    @type WebBrowserView
+    """
+    if view in _VIEWS:
+        _VIEWS.remove(view)
+    _VIEWS.insert(0, view)
--- a/eric6.e4p	Sat Feb 27 18:19:09 2016 +0100
+++ b/eric6.e4p	Sat Feb 27 20:51:44 2016 +0100
@@ -1401,6 +1401,7 @@
     <Source>WebBrowser/WebBrowserView.py</Source>
     <Source>WebBrowser/WebBrowserWebSearchWidget.py</Source>
     <Source>WebBrowser/WebBrowserWindow.py</Source>
+    <Source>WebBrowser/WebInspector.py</Source>
     <Source>WebBrowser/ZoomManager/ZoomManager.py</Source>
     <Source>WebBrowser/ZoomManager/ZoomValuesDialog.py</Source>
     <Source>WebBrowser/ZoomManager/ZoomValuesModel.py</Source>

eric ide

mercurial