Web Browser: changed the web browser logic inside eric to use a remote controlled web browser process.

Wed, 12 Dec 2018 19:52:24 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 12 Dec 2018 19:52:24 +0100
changeset 6625
a67fee7bc09c
parent 6624
9718755def80
child 6626
9a9e485949a4

Web Browser: changed the web browser logic inside eric to use a remote controlled web browser process.

Documentation/Help/source.qch file | annotate | diff | comparison | revisions
E5XML/ShortcutsWriter.py file | annotate | diff | comparison | revisions
Helpviewer/HelpWindow.py file | annotate | diff | comparison | revisions
Preferences/Shortcuts.py file | annotate | diff | comparison | revisions
Preferences/ShortcutsDialog.py file | annotate | diff | comparison | revisions
Toolbox/SingleApplication.py file | annotate | diff | comparison | revisions
UI/UserInterface.py file | annotate | diff | comparison | revisions
WebBrowser/Network/EricSchemeHandler.py file | annotate | diff | comparison | revisions
WebBrowser/Network/NetworkManager.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserSingleApplication.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserTabWidget.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
eric6_browser.py file | annotate | diff | comparison | revisions
Binary file Documentation/Help/source.qch has changed
--- a/E5XML/ShortcutsWriter.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/E5XML/ShortcutsWriter.py	Wed Dec 12 19:52:24 2018 +0100
@@ -33,9 +33,11 @@
         
         self.email = Preferences.getUser("Email")
         
-    def writeXML(self):
+    def writeXML(self, helpViewer=None):
         """
         Public method to write the XML to the file.
+        
+        @param helpViewer reference to the help window object
         """
         XMLStreamWriterBase.writeXML(self)
         
@@ -52,54 +54,60 @@
         self.writeStartElement("Shortcuts")
         self.writeAttribute("version", shortcutsFileFormatVersion)
         
-        self.__writeActions(
-            "Project",
-            e5App().getObject("Project").getActions())
-        self.__writeActions(
-            "General",
-            e5App().getObject("UserInterface").getActions('ui'))
-        self.__writeActions(
-            "Wizards",
-            e5App().getObject("UserInterface").getActions('wizards'))
-        self.__writeActions(
-            "Debug",
-            e5App().getObject("DebugUI").getActions())
-        self.__writeActions(
-            "Edit",
-            e5App().getObject("ViewManager").getActions('edit'))
-        self.__writeActions(
-            "File",
-            e5App().getObject("ViewManager").getActions('file'))
-        self.__writeActions(
-            "Search",
-            e5App().getObject("ViewManager").getActions('search'))
-        self.__writeActions(
-            "View",
-            e5App().getObject("ViewManager").getActions('view'))
-        self.__writeActions(
-            "Macro",
-            e5App().getObject("ViewManager").getActions('macro'))
-        self.__writeActions(
-            "Bookmarks",
-            e5App().getObject("ViewManager").getActions('bookmark'))
-        self.__writeActions(
-            "Spelling",
-            e5App().getObject("ViewManager").getActions('spelling'))
-        self.__writeActions(
-            "Window",
-            e5App().getObject("ViewManager").getActions('window'))
+        if helpViewer is None:
+            self.__writeActions(
+                "Project",
+                e5App().getObject("Project").getActions())
+            self.__writeActions(
+                "General",
+                e5App().getObject("UserInterface").getActions('ui'))
+            self.__writeActions(
+                "Wizards",
+                e5App().getObject("UserInterface").getActions('wizards'))
+            self.__writeActions(
+                "Debug",
+                e5App().getObject("DebugUI").getActions())
+            self.__writeActions(
+                "Edit",
+                e5App().getObject("ViewManager").getActions('edit'))
+            self.__writeActions(
+                "File",
+                e5App().getObject("ViewManager").getActions('file'))
+            self.__writeActions(
+                "Search",
+                e5App().getObject("ViewManager").getActions('search'))
+            self.__writeActions(
+                "View",
+                e5App().getObject("ViewManager").getActions('view'))
+            self.__writeActions(
+                "Macro",
+                e5App().getObject("ViewManager").getActions('macro'))
+            self.__writeActions(
+                "Bookmarks",
+                e5App().getObject("ViewManager").getActions('bookmark'))
+            self.__writeActions(
+                "Spelling",
+                e5App().getObject("ViewManager").getActions('spelling'))
+            self.__writeActions(
+                "Window",
+                e5App().getObject("ViewManager").getActions('window'))
+            
+            for category, ref in e5App().getPluginObjects():
+                if hasattr(ref, "getActions"):
+                    self.__writeActions(category, ref.getActions())
         
-        for category, ref in e5App().getPluginObjects():
-            if hasattr(ref, "getActions"):
-                self.__writeActions(category, ref.getActions())
-    
-        try:
+            try:
+                self.__writeActions(
+                    "HelpViewer",
+                    e5App().getObject("DummyHelpViewer").getActions())
+            except KeyError:
+                # no QtWebKit available
+                pass
+        
+        else:
             self.__writeActions(
-                "HelpViewer",
-                e5App().getObject("DummyHelpViewer").getActions())
-        except KeyError:
-            # no QtWebKit available
-            pass
+                helpViewer.getActionsCategory(),
+                helpViewer.getActions())
     
         # add the main end tag
         self.writeEndElement()
--- a/Helpviewer/HelpWindow.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/Helpviewer/HelpWindow.py	Wed Dec 12 19:52:24 2018 +0100
@@ -1598,7 +1598,16 @@
         @return list of all actions (list of E5Action)
         """
         return self.__actions[:]
-        
+    
+    def getActionsCategory(self):
+        """
+        Public method to get the category of the defined actions.
+        
+        @return category of the actions
+        @rtype str
+        """
+        return "HelpViewer"
+    
     def __initMenus(self):
         """
         Private method to create the menus.
--- a/Preferences/Shortcuts.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/Preferences/Shortcuts.py	Wed Dec 12 19:52:24 2018 +0100
@@ -37,8 +37,7 @@
             act.setAlternateShortcut(QKeySequence(accel), removeEmpty=True)
 
 
-def readShortcuts(prefClass=Prefs, helpViewer=None, pluginName=None,
-                  helpViewerCategory=""):
+def readShortcuts(prefClass=Prefs, helpViewer=None, pluginName=None):
     """
     Module function to read the keyboard shortcuts for the defined QActions.
     
@@ -46,7 +45,6 @@
     @keyparam helpViewer reference to the help window object
     @keyparam pluginName name of the plugin for which to load shortcuts
         (string)
-    @keyparam helpViewerCategory name of the help viewer category (string)
     """
     if helpViewer is None and pluginName is None:
         for act in e5App().getObject("Project").getActions():
@@ -94,8 +92,7 @@
                     __readShortcut(act, category, prefClass)
     
     if helpViewer is not None:
-        if not helpViewerCategory:
-            helpViewerCategory = "HelpViewer"
+        helpViewerCategory = helpViewer.getActionsCategory()
         for act in helpViewer.getActions():
             __readShortcut(act, helpViewerCategory, prefClass)
     
@@ -128,75 +125,94 @@
             act.alternateShortcut().toString())
 
 
-def saveShortcuts(prefClass=Prefs):
+def saveShortcuts(prefClass=Prefs, helpViewer=None):
     """
     Module function to write the keyboard shortcuts for the defined QActions.
     
     @param prefClass preferences class used as the storage area
+    @keyparam helpViewer reference to the help window object
     """
-    # step 1: clear all previously saved shortcuts
-    prefClass.settings.beginGroup("Shortcuts")
-    prefClass.settings.remove("")
-    prefClass.settings.endGroup()
-    
-    # step 2: save the various shortcuts
-    for act in e5App().getObject("Project").getActions():
-        __saveShortcut(act, "Project", prefClass)
-    
-    for act in e5App().getObject("UserInterface").getActions('ui'):
-        __saveShortcut(act, "General", prefClass)
-    
-    for act in e5App().getObject("UserInterface").getActions('wizards'):
-        __saveShortcut(act, "Wizards", prefClass)
-    
-    for act in e5App().getObject("DebugUI").getActions():
-        __saveShortcut(act, "Debug", prefClass)
-    
-    for act in e5App().getObject("ViewManager").getActions('edit'):
-        __saveShortcut(act, "Edit", prefClass)
-    
-    for act in e5App().getObject("ViewManager").getActions('file'):
-        __saveShortcut(act, "File", prefClass)
-    
-    for act in e5App().getObject("ViewManager").getActions('search'):
-        __saveShortcut(act, "Search", prefClass)
+    if helpViewer is None:
+        # step 1: clear all previously saved shortcuts
+        prefClass.settings.beginGroup("Shortcuts")
+        prefClass.settings.remove("")
+        prefClass.settings.endGroup()
+        
+        # step 2: save the various shortcuts
+        for act in e5App().getObject("Project").getActions():
+            __saveShortcut(act, "Project", prefClass)
+        
+        for act in e5App().getObject("UserInterface").getActions('ui'):
+            __saveShortcut(act, "General", prefClass)
+        
+        for act in e5App().getObject("UserInterface").getActions('wizards'):
+            __saveShortcut(act, "Wizards", prefClass)
+        
+        for act in e5App().getObject("DebugUI").getActions():
+            __saveShortcut(act, "Debug", prefClass)
+        
+        for act in e5App().getObject("ViewManager").getActions('edit'):
+            __saveShortcut(act, "Edit", prefClass)
+        
+        for act in e5App().getObject("ViewManager").getActions('file'):
+            __saveShortcut(act, "File", prefClass)
+        
+        for act in e5App().getObject("ViewManager").getActions('search'):
+            __saveShortcut(act, "Search", prefClass)
+        
+        for act in e5App().getObject("ViewManager").getActions('view'):
+            __saveShortcut(act, "View", prefClass)
+        
+        for act in e5App().getObject("ViewManager").getActions('macro'):
+            __saveShortcut(act, "Macro", prefClass)
+        
+        for act in e5App().getObject("ViewManager").getActions('bookmark'):
+            __saveShortcut(act, "Bookmarks", prefClass)
+        
+        for act in e5App().getObject("ViewManager").getActions('spelling'):
+            __saveShortcut(act, "Spelling", prefClass)
+        
+        actions = e5App().getObject("ViewManager").getActions('window')
+        if actions:
+            for act in actions:
+                __saveShortcut(act, "Window", prefClass)
+        
+        for category, ref in e5App().getPluginObjects():
+            if hasattr(ref, "getActions"):
+                actions = ref.getActions()
+                for act in actions:
+                    __saveShortcut(act, category, prefClass)
+        
+        try:
+            category = e5App().getObject("DummyHelpViewer")\
+                .getActionsCategory()
+            for act in e5App().getObject("DummyHelpViewer").getActions():
+                __saveShortcut(act, category, prefClass)
+        except KeyError:
+            # no QtWebKit available
+            pass
     
-    for act in e5App().getObject("ViewManager").getActions('view'):
-        __saveShortcut(act, "View", prefClass)
-    
-    for act in e5App().getObject("ViewManager").getActions('macro'):
-        __saveShortcut(act, "Macro", prefClass)
-    
-    for act in e5App().getObject("ViewManager").getActions('bookmark'):
-        __saveShortcut(act, "Bookmarks", prefClass)
-    
-    for act in e5App().getObject("ViewManager").getActions('spelling'):
-        __saveShortcut(act, "Spelling", prefClass)
-    
-    actions = e5App().getObject("ViewManager").getActions('window')
-    if actions:
-        for act in actions:
-            __saveShortcut(act, "Window", prefClass)
-    
-    for category, ref in e5App().getPluginObjects():
-        if hasattr(ref, "getActions"):
-            actions = ref.getActions()
-            for act in actions:
-                __saveShortcut(act, category, prefClass)
-    
-    try:
-        for act in e5App().getObject("DummyHelpViewer").getActions():
-            __saveShortcut(act, "HelpViewer", prefClass)
-    except KeyError:
-        # no QtWebKit available
-        pass
+    else:
+        helpViewerCategory = helpViewer.getActionsCategory()
+        
+        # step 1: clear all previously saved shortcuts
+        prefClass.settings.beginGroup(
+            "Shortcuts/{0}".format(helpViewerCategory)
+        )
+        prefClass.settings.remove("")
+        prefClass.settings.endGroup()
+        
+        # step 2: save the shortcuts
+        for act in helpViewer.getActions():
+            __saveShortcut(act, helpViewerCategory, prefClass)
 
 
-def exportShortcuts(fn):
+def exportShortcuts(fn, helpViewer=None):
     """
     Module function to export the keyboard shortcuts for the defined QActions.
     
     @param fn filename of the export file (string)
+    @param helpViewer reference to the help window object
     """
     # let the plugin manager create on demand plugin objects
     pm = e5App().getObject("PluginManager")
@@ -205,7 +221,7 @@
     f = QFile(fn)
     if f.open(QIODevice.WriteOnly):
         from E5XML.ShortcutsWriter import ShortcutsWriter
-        ShortcutsWriter(f).writeXML()
+        ShortcutsWriter(f).writeXML(helpViewer=helpViewer)
         f.close()
     else:
         E5MessageBox.critical(
@@ -219,11 +235,12 @@
             .format(fn))
 
 
-def importShortcuts(fn):
+def importShortcuts(fn, helpViewer=None):
     """
     Module function to import the keyboard shortcuts for the defined E5Actions.
     
     @param fn filename of the import file (string)
+    @param helpViewer reference to the help window object
     """
     # let the plugin manager create on demand plugin objects
     pm = e5App().getObject("PluginManager")
@@ -237,7 +254,7 @@
         f.close()
         if not reader.hasError():
             shortcuts = reader.getShortcuts()
-            setActions(shortcuts)
+            setActions(shortcuts, helpViewer=helpViewer)
             saveShortcuts()
             syncPreferences()
     else:
@@ -271,71 +288,89 @@
                 pass
 
 
-def setActions(shortcuts):
+def setActions(shortcuts, helpViewer=None):
     """
     Module function to set actions based on new format shortcuts file.
     
     @param shortcuts dictionary containing the accelerator information
         read from a XML file
+    @param helpViewer reference to the help window object
     """
-    if "Project" in shortcuts:
-        __setAction(e5App().getObject("Project").getActions(),
-                    shortcuts["Project"])
-    
-    if "General" in shortcuts:
-        __setAction(e5App().getObject("UserInterface").getActions('ui'),
-                    shortcuts["General"])
-    
-    if "Wizards" in shortcuts:
-        __setAction(e5App().getObject("UserInterface").getActions('wizards'),
-                    shortcuts["Wizards"])
-    
-    if "Debug" in shortcuts:
-        __setAction(e5App().getObject("DebugUI").getActions(),
-                    shortcuts["Debug"])
-    
-    if "Edit" in shortcuts:
-        __setAction(e5App().getObject("ViewManager").getActions('edit'),
-                    shortcuts["Edit"])
-    
-    if "File" in shortcuts:
-        __setAction(e5App().getObject("ViewManager").getActions('file'),
-                    shortcuts["File"])
-    
-    if "Search" in shortcuts:
-        __setAction(e5App().getObject("ViewManager").getActions('search'),
-                    shortcuts["Search"])
+    if helpViewer is None:
+        if "Project" in shortcuts:
+            __setAction(
+                e5App().getObject("Project").getActions(),
+                shortcuts["Project"])
+        
+        if "General" in shortcuts:
+            __setAction(
+                e5App().getObject("UserInterface").getActions('ui'),
+                shortcuts["General"])
+        
+        if "Wizards" in shortcuts:
+            __setAction(
+                e5App().getObject("UserInterface").getActions('wizards'),
+                shortcuts["Wizards"])
+        
+        if "Debug" in shortcuts:
+            __setAction(
+                e5App().getObject("DebugUI").getActions(),
+                shortcuts["Debug"])
+        
+        if "Edit" in shortcuts:
+            __setAction(
+                e5App().getObject("ViewManager").getActions('edit'),
+                shortcuts["Edit"])
+        
+        if "File" in shortcuts:
+            __setAction(
+                e5App().getObject("ViewManager").getActions('file'),
+                shortcuts["File"])
+        
+        if "Search" in shortcuts:
+            __setAction(
+                e5App().getObject("ViewManager").getActions('search'),
+                shortcuts["Search"])
+        
+        if "View" in shortcuts:
+            __setAction(
+                e5App().getObject("ViewManager").getActions('view'),
+                shortcuts["View"])
+        
+        if "Macro" in shortcuts:
+            __setAction(
+                e5App().getObject("ViewManager").getActions('macro'),
+                shortcuts["Macro"])
+        
+        if "Bookmarks" in shortcuts:
+            __setAction(
+                e5App().getObject("ViewManager").getActions('bookmark'),
+                shortcuts["Bookmarks"])
+        
+        if "Spelling" in shortcuts:
+            __setAction(
+                e5App().getObject("ViewManager").getActions('spelling'),
+                shortcuts["Spelling"])
+        
+        if "Window" in shortcuts:
+            actions = e5App().getObject("ViewManager").getActions('window')
+            if actions:
+                __setAction(actions, shortcuts["Window"])
+        
+        for category, ref in e5App().getPluginObjects():
+            if category in shortcuts and hasattr(ref, "getActions"):
+                actions = ref.getActions()
+                __setAction(actions, shortcuts[category])
+        
+        try:
+            if "HelpViewer" in shortcuts:
+                __setAction(e5App().getObject("DummyHelpViewer").getActions(),
+                            shortcuts["HelpViewer"])
+        except KeyError:
+            # no QtWebKit available
+            pass
     
-    if "View" in shortcuts:
-        __setAction(e5App().getObject("ViewManager").getActions('view'),
-                    shortcuts["View"])
-    
-    if "Macro" in shortcuts:
-        __setAction(e5App().getObject("ViewManager").getActions('macro'),
-                    shortcuts["Macro"])
-    
-    if "Bookmarks" in shortcuts:
-        __setAction(e5App().getObject("ViewManager").getActions('bookmark'),
-                    shortcuts["Bookmarks"])
-    
-    if "Spelling" in shortcuts:
-        __setAction(e5App().getObject("ViewManager").getActions('spelling'),
-                    shortcuts["Spelling"])
-    
-    if "Window" in shortcuts:
-        actions = e5App().getObject("ViewManager").getActions('window')
-        if actions:
-            __setAction(actions, shortcuts["Window"])
-    
-    for category, ref in e5App().getPluginObjects():
-        if category in shortcuts and hasattr(ref, "getActions"):
-            actions = ref.getActions()
-            __setAction(actions, shortcuts[category])
-    
-    try:
-        if "HelpViewer" in shortcuts:
-            __setAction(e5App().getObject("DummyHelpViewer").getActions(),
-                        shortcuts["HelpViewer"])
-    except KeyError:
-        # no QtWebKit available
-        pass
+    else:
+        category = helpViewer.getActionsCategory()
+        if category in shortcuts:
+            __setAction(helpViewer.getActions(), shortcuts[category])
--- a/Preferences/ShortcutsDialog.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/Preferences/ShortcutsDialog.py	Wed Dec 12 19:52:24 2018 +0100
@@ -37,21 +37,19 @@
     noCheckRole = Qt.UserRole + 1
     objectTypeRole = Qt.UserRole + 2
     
-    def __init__(self, parent=None, name=None, modal=False):
+    def __init__(self, parent=None):
         """
         Constructor
         
-        @param parent The parent widget of this dialog. (QWidget)
-        @param name The name of this dialog. (string)
-        @param modal Flag indicating a modal dialog. (boolean)
+        @param parent parent widget of this dialog
+        @type QWidget
         """
         super(ShortcutsDialog, self).__init__(parent)
-        if name:
-            self.setObjectName(name)
-        self.setModal(modal)
         self.setupUi(self)
         self.setWindowFlags(Qt.Window)
         
+        self.__helpViewer = None
+        
         self.shortcutsList.headerItem().setText(
             self.shortcutsList.columnCount(), "")
         self.shortcutsList.header().setSortIndicator(0, Qt.AscendingOrder)
@@ -111,92 +109,104 @@
         else:
             itm.setData(0, self.objectTypeRole, None)
         
-    def populate(self):
+    def populate(self, helpViewer=None):
         """
         Public method to populate the dialog.
+        
+        @param helpViewer reference to the help window object
         """
         self.searchEdit.clear()
         self.searchEdit.setFocus()
         self.shortcutsList.clear()
         self.actionButton.setChecked(True)
         
-        # let the plugin manager create on demand plugin objects
-        pm = e5App().getObject("PluginManager")
-        pm.initOnDemandPlugins()
-        
-        # populate the various lists
-        self.projectItem = self.__generateCategoryItem(self.tr("Project"))
-        for act in e5App().getObject("Project").getActions():
-            self.__generateShortcutItem(self.projectItem, act)
-        
-        self.uiItem = self.__generateCategoryItem(self.tr("General"))
-        for act in e5App().getObject("UserInterface").getActions('ui'):
-            self.__generateShortcutItem(self.uiItem, act)
-        
-        self.wizardsItem = self.__generateCategoryItem(self.tr("Wizards"))
-        for act in e5App().getObject("UserInterface").getActions('wizards'):
-            self.__generateShortcutItem(self.wizardsItem, act)
-        
-        self.debugItem = self.__generateCategoryItem(self.tr("Debug"))
-        for act in e5App().getObject("DebugUI").getActions():
-            self.__generateShortcutItem(self.debugItem, act)
-        
-        self.editItem = self.__generateCategoryItem(self.tr("Edit"))
-        for act in e5App().getObject("ViewManager").getActions('edit'):
-            self.__generateShortcutItem(self.editItem, act)
-        
-        self.fileItem = self.__generateCategoryItem(self.tr("File"))
-        for act in e5App().getObject("ViewManager").getActions('file'):
-            self.__generateShortcutItem(self.fileItem, act)
-        
-        self.searchItem = self.__generateCategoryItem(self.tr("Search"))
-        for act in e5App().getObject("ViewManager").getActions('search'):
-            self.__generateShortcutItem(self.searchItem, act)
+        self.__helpViewer = helpViewer
         
-        self.viewItem = self.__generateCategoryItem(self.tr("View"))
-        for act in e5App().getObject("ViewManager").getActions('view'):
-            self.__generateShortcutItem(self.viewItem, act)
-        
-        self.macroItem = self.__generateCategoryItem(self.tr("Macro"))
-        for act in e5App().getObject("ViewManager").getActions('macro'):
-            self.__generateShortcutItem(self.macroItem, act)
-        
-        self.bookmarkItem = self.__generateCategoryItem(
-            self.tr("Bookmarks"))
-        for act in e5App().getObject("ViewManager").getActions('bookmark'):
-            self.__generateShortcutItem(self.bookmarkItem, act)
-        
-        self.spellingItem = self.__generateCategoryItem(
-            self.tr("Spelling"))
-        for act in e5App().getObject("ViewManager").getActions('spelling'):
-            self.__generateShortcutItem(self.spellingItem, act)
+        if helpViewer is None:
+            # let the plugin manager create on demand plugin objects
+            pm = e5App().getObject("PluginManager")
+            pm.initOnDemandPlugins()
+            
+            # populate the various lists
+            self.projectItem = self.__generateCategoryItem(self.tr("Project"))
+            for act in e5App().getObject("Project").getActions():
+                self.__generateShortcutItem(self.projectItem, act)
+            
+            self.uiItem = self.__generateCategoryItem(self.tr("General"))
+            for act in e5App().getObject("UserInterface").getActions('ui'):
+                self.__generateShortcutItem(self.uiItem, act)
+            
+            self.wizardsItem = self.__generateCategoryItem(self.tr("Wizards"))
+            for act in e5App().getObject("UserInterface")\
+                    .getActions('wizards'):
+                self.__generateShortcutItem(self.wizardsItem, act)
+            
+            self.debugItem = self.__generateCategoryItem(self.tr("Debug"))
+            for act in e5App().getObject("DebugUI").getActions():
+                self.__generateShortcutItem(self.debugItem, act)
+            
+            self.editItem = self.__generateCategoryItem(self.tr("Edit"))
+            for act in e5App().getObject("ViewManager").getActions('edit'):
+                self.__generateShortcutItem(self.editItem, act)
+            
+            self.fileItem = self.__generateCategoryItem(self.tr("File"))
+            for act in e5App().getObject("ViewManager").getActions('file'):
+                self.__generateShortcutItem(self.fileItem, act)
+            
+            self.searchItem = self.__generateCategoryItem(self.tr("Search"))
+            for act in e5App().getObject("ViewManager").getActions('search'):
+                self.__generateShortcutItem(self.searchItem, act)
+            
+            self.viewItem = self.__generateCategoryItem(self.tr("View"))
+            for act in e5App().getObject("ViewManager").getActions('view'):
+                self.__generateShortcutItem(self.viewItem, act)
+            
+            self.macroItem = self.__generateCategoryItem(self.tr("Macro"))
+            for act in e5App().getObject("ViewManager").getActions('macro'):
+                self.__generateShortcutItem(self.macroItem, act)
+            
+            self.bookmarkItem = self.__generateCategoryItem(
+                self.tr("Bookmarks"))
+            for act in e5App().getObject("ViewManager").getActions('bookmark'):
+                self.__generateShortcutItem(self.bookmarkItem, act)
+            
+            self.spellingItem = self.__generateCategoryItem(
+                self.tr("Spelling"))
+            for act in e5App().getObject("ViewManager").getActions('spelling'):
+                self.__generateShortcutItem(self.spellingItem, act)
+            
+            actions = e5App().getObject("ViewManager").getActions('window')
+            if actions:
+                self.windowItem = self.__generateCategoryItem(
+                    self.tr("Window"))
+                for act in actions:
+                    self.__generateShortcutItem(self.windowItem, act)
+            
+            self.pluginCategoryItems = []
+            for category, ref in e5App().getPluginObjects():
+                if hasattr(ref, "getActions"):
+                    categoryItem = self.__generateCategoryItem(category)
+                    objectType = e5App().getPluginObjectType(category)
+                    for act in ref.getActions():
+                        self.__generateShortcutItem(categoryItem, act,
+                                                    objectType=objectType)
+                    self.pluginCategoryItems.append(categoryItem)
+            
+            try:
+                dummyHelpViewer = e5App().getObject("DummyHelpViewer")
+                self.helpViewerItem = self.__generateCategoryItem(
+                    self.tr("eric6 Web Browser"))
+                for act in dummyHelpViewer.getActions():
+                    self.__generateShortcutItem(self.helpViewerItem, act, True)
+            except KeyError:
+                # no QtWebKit available
+                pass
         
-        actions = e5App().getObject("ViewManager").getActions('window')
-        if actions:
-            self.windowItem = self.__generateCategoryItem(
-                self.tr("Window"))
-            for act in actions:
-                self.__generateShortcutItem(self.windowItem, act)
-        
-        self.pluginCategoryItems = []
-        for category, ref in e5App().getPluginObjects():
-            if hasattr(ref, "getActions"):
-                categoryItem = self.__generateCategoryItem(category)
-                objectType = e5App().getPluginObjectType(category)
-                for act in ref.getActions():
-                    self.__generateShortcutItem(categoryItem, act,
-                                                objectType=objectType)
-                self.pluginCategoryItems.append(categoryItem)
-        
-        try:
-            dummyHelpViewer = e5App().getObject("DummyHelpViewer")
+        else:
             self.helpViewerItem = self.__generateCategoryItem(
                 self.tr("eric6 Web Browser"))
-            for act in dummyHelpViewer.getActions():
+            for act in helpViewer.getActions():
                 self.__generateShortcutItem(self.helpViewerItem, act, True)
-        except KeyError:
-            # no QtWebKit available
-            pass
         
         self.__resort()
         self.__resizeColumns()
@@ -392,59 +402,66 @@
         """
         Private slot to handle the OK button press.
         """
-        self.__saveCategoryActions(
-            self.projectItem,
-            e5App().getObject("Project").getActions())
-        self.__saveCategoryActions(
-            self.uiItem,
-            e5App().getObject("UserInterface").getActions('ui'))
-        self.__saveCategoryActions(
-            self.wizardsItem,
-            e5App().getObject("UserInterface").getActions('wizards'))
-        self.__saveCategoryActions(
-            self.debugItem,
-            e5App().getObject("DebugUI").getActions())
-        self.__saveCategoryActions(
-            self.editItem,
-            e5App().getObject("ViewManager").getActions('edit'))
-        self.__saveCategoryActions(
-            self.fileItem,
-            e5App().getObject("ViewManager").getActions('file'))
-        self.__saveCategoryActions(
-            self.searchItem,
-            e5App().getObject("ViewManager").getActions('search'))
-        self.__saveCategoryActions(
-            self.viewItem,
-            e5App().getObject("ViewManager").getActions('view'))
-        self.__saveCategoryActions(
-            self.macroItem,
-            e5App().getObject("ViewManager").getActions('macro'))
-        self.__saveCategoryActions(
-            self.bookmarkItem,
-            e5App().getObject("ViewManager").getActions('bookmark'))
-        self.__saveCategoryActions(
-            self.spellingItem,
-            e5App().getObject("ViewManager").getActions('spelling'))
+        if self.__helpViewer is None:
+            self.__saveCategoryActions(
+                self.projectItem,
+                e5App().getObject("Project").getActions())
+            self.__saveCategoryActions(
+                self.uiItem,
+                e5App().getObject("UserInterface").getActions('ui'))
+            self.__saveCategoryActions(
+                self.wizardsItem,
+                e5App().getObject("UserInterface").getActions('wizards'))
+            self.__saveCategoryActions(
+                self.debugItem,
+                e5App().getObject("DebugUI").getActions())
+            self.__saveCategoryActions(
+                self.editItem,
+                e5App().getObject("ViewManager").getActions('edit'))
+            self.__saveCategoryActions(
+                self.fileItem,
+                e5App().getObject("ViewManager").getActions('file'))
+            self.__saveCategoryActions(
+                self.searchItem,
+                e5App().getObject("ViewManager").getActions('search'))
+            self.__saveCategoryActions(
+                self.viewItem,
+                e5App().getObject("ViewManager").getActions('view'))
+            self.__saveCategoryActions(
+                self.macroItem,
+                e5App().getObject("ViewManager").getActions('macro'))
+            self.__saveCategoryActions(
+                self.bookmarkItem,
+                e5App().getObject("ViewManager").getActions('bookmark'))
+            self.__saveCategoryActions(
+                self.spellingItem,
+                e5App().getObject("ViewManager").getActions('spelling'))
+            
+            actions = e5App().getObject("ViewManager").getActions('window')
+            if actions:
+                self.__saveCategoryActions(self.windowItem, actions)
+            
+            for categoryItem in self.pluginCategoryItems:
+                category = categoryItem.text(0)
+                ref = e5App().getPluginObject(category)
+                if ref is not None and hasattr(ref, "getActions"):
+                    self.__saveCategoryActions(categoryItem, ref.getActions())
+            
+            try:
+                dummyHelpViewer = e5App().getObject("DummyHelpViewer")
+                self.__saveCategoryActions(
+                    self.helpViewerItem, dummyHelpViewer.getActions())
+            except KeyError:
+                # no QtWebKit available
+                pass
+            
+            Shortcuts.saveShortcuts()
         
-        actions = e5App().getObject("ViewManager").getActions('window')
-        if actions:
-            self.__saveCategoryActions(self.windowItem, actions)
-        
-        for categoryItem in self.pluginCategoryItems:
-            category = categoryItem.text(0)
-            ref = e5App().getPluginObject(category)
-            if ref is not None and hasattr(ref, "getActions"):
-                self.__saveCategoryActions(categoryItem, ref.getActions())
+        else:
+            self.__saveCategoryActions(
+                self.helpViewerItem, self.__helpViewer.getActions())
+            Shortcuts.saveShortcuts(helpViewer=self.__helpViewer)
         
-        try:
-            dummyHelpViewer = e5App().getObject("DummyHelpViewer")
-            self.__saveCategoryActions(
-                self.helpViewerItem, dummyHelpViewer.getActions())
-        except KeyError:
-            # no QtWebKit available
-            pass
-        
-        Shortcuts.saveShortcuts()
         Preferences.syncPreferences()
         
         self.updateShortcuts.emit()
--- a/Toolbox/SingleApplication.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/Toolbox/SingleApplication.py	Wed Dec 12 19:52:24 2018 +0100
@@ -135,10 +135,12 @@
         self.name = name
         self.connected = False
         
-    def connect(self):
+    def connect(self, timeout=10000):
         """
         Public method to connect the single application client to its server.
         
+        @param timeout connection timeout value in milliseconds
+        @type int
         @return value indicating success or an error number. Value is one of:
             <table>
                 <tr><td>0</td><td>No application is running</td></tr>
@@ -147,7 +149,7 @@
         """
         self.sock = QLocalSocket()
         self.sock.connectToServer(self.name)
-        if self.sock.waitForConnected(10000):
+        if self.sock.waitForConnected(timeout):
             self.connected = True
             return 1
         else:
--- a/UI/UserInterface.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/UI/UserInterface.py	Wed Dec 12 19:52:24 2018 +0100
@@ -19,7 +19,7 @@
 
 from PyQt5.QtCore import pyqtSlot, QTimer, QFile, QFileInfo, pyqtSignal, \
     PYQT_VERSION_STR, QDate, QIODevice, qVersion, QProcess, QSize, QUrl, \
-    QObject, Qt
+    QObject, Qt, QUuid, QThread
 from PyQt5.QtGui import QKeySequence, QDesktopServices
 from PyQt5.QtWidgets import QSizePolicy, QWidget, QWhatsThis, QToolBar, \
     QDialog, QSplitter, QApplication, QMenu, QVBoxLayout, QDockWidget, \
@@ -282,6 +282,10 @@
         self.templateViewer = None
         self.numbersViewer = None
         
+        self.__webBrowserProcess = None
+        self.__webBrowserClient = None
+        self.__webBrowserSAName = QUuid.createUuid().toString()[1:-1]
+        
         # Create the main window now so that we can connect QActions to it.
         logging.debug("Creating Layout...")
         self.__createLayout(debugServer)
@@ -572,11 +576,8 @@
         self.__initExternalToolsActions()
         
         # create a dummy help window for shortcuts handling
-        if WEBENGINE_AVAILABLE:
-            from WebBrowser.WebBrowserWindow import WebBrowserWindow
-            self.dummyHelpViewer = \
-                WebBrowserWindow(None, '.', None, 'web_browser', True, True)
-        elif WEBKIT_AVAILABLE:
+        # TODO: remove this in favour of standalone web browser
+        if WEBKIT_AVAILABLE:
             from Helpviewer.HelpWindow import HelpWindow
             self.dummyHelpViewer = \
                 HelpWindow(None, '.', None, 'help viewer', True, True)
@@ -5654,19 +5655,16 @@
             if not homeUrl.scheme():
                 home = QUrl.fromLocalFile(home).toString()
         
-        if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE:
+        if WEBENGINE_AVAILABLE:
+            self.__launchExternalWebBrowser(home, searchWord=searchWord)
+        
+        elif WEBKIT_AVAILABLE:
+            # TODO: change to use external web browser in single mode
             single = useSingle
-            if WEBENGINE_AVAILABLE:
-                single = single or \
-                    Preferences.getWebBrowser("SingleWebBrowserWindow")
-            elif WEBKIT_AVAILABLE:
+            if WEBKIT_AVAILABLE:
                 single = single or Preferences.getHelp("SingleHelpWindow")
             if not single or self.helpWindow is None:
-                if WEBENGINE_AVAILABLE:
-                    from WebBrowser.WebBrowserWindow import WebBrowserWindow
-                    browser = WebBrowserWindow(home, '.', None, 'web_browser',
-                                               True, searchWord=searchWord)
-                elif WEBKIT_AVAILABLE:
+                if WEBKIT_AVAILABLE:
                     from Helpviewer.HelpWindow import HelpWindow
                     browser = HelpWindow(home, '.', None, 'help viewer', True,
                                          searchWord=searchWord)
@@ -5694,9 +5692,90 @@
             else:
                 self.helpWindow.newTab(home)
                 self.helpWindow.raise_()
+        
         else:
             self.__webBrowser(home)
     
+    def __launchExternalWebBrowser(self, home, searchWord=None):
+        """
+        Private method to start an external web browser and communicate with
+        it.
+        
+        @param home filename of file to be shown or URL to be opened
+        @type str
+        @keyparam searchWord word to search for
+        @type str
+        """
+        from WebBrowser.WebBrowserSingleApplication import \
+            WebBrowserSingleApplicationClient
+        
+        clientArgs = []
+        if searchWord:
+            clientArgs.append("--search={0}".format(searchWord))
+        
+        if self.__webBrowserProcess is None:
+            process = QProcess()
+            args = [
+                os.path.join(
+                    os.path.dirname(__file__), "..", "eric6_browser.py"),
+                "--qthelp",
+                "--single",
+                "--name={0}".format(self.__webBrowserSAName)
+            ]
+            process.start(sys.executable, args)
+            if not process.waitForStarted():
+                E5MessageBox.warning(
+                    self,
+                    self.tr("Start Web Browser"),
+                    self.tr("""The eric6 web browser could not be started."""))
+                return
+            
+            process.finished.connect(self.__webBrowserFinished)
+            self.__webBrowserProcess = process
+            
+            self.__webBrowserClient = WebBrowserSingleApplicationClient(
+                self.__webBrowserSAName)
+            connectCount = 30
+            while connectCount:
+                res = self.__webBrowserClient.connect()
+                if res != 0:
+                    break
+                else:
+                    connectCount -= 1
+                    QThread.msleep(1000)
+            if res <= 0:
+                E5MessageBox.warning(
+                    self,
+                    self.tr("Start Web Browser"),
+                    self.tr("""<p>The eric6 web browser is not started.</p>"""
+                            """<p>Reason: {0}</p>""").format(
+                        self.__webBrowserClient.errstr())
+                )
+                return
+            
+            if home:
+                clientArgs.append(home)
+        else:
+            clientArgs.append("--newtab={0}".format(home))
+        
+        if clientArgs:
+            self.__webBrowserClient.processArgs(clientArgs, disconnect=False)
+    
+    def __webBrowserFinished(self):
+        """
+        Private slot handling the end of the external web browser process.
+        """
+        self.__webBrowserProcess.deleteLater()
+        
+        self.__webBrowserProcess = None
+        self.__webBrowserClient = None
+    
+    def __webBrowserShutdown(self):
+        """
+        Private method to shut down the web browser.
+        """
+        self.__webBrowserClient.processArgs(["--shutdown"], disconnect=False)
+    
     def __helpClosed(self):
         """
         Private slot to handle the helpClosed signal of the help window.
@@ -5743,6 +5822,7 @@
             (boolean)
         @return reference to the help window instance (HelpWindow)
         """
+        # TODO: check if this method is used somewhere
         if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE:
             if self.helpWindow is None:
                 self.launchHelpViewer("", useSingle=True)
@@ -5937,7 +6017,7 @@
         """
         if self.shortcutsDialog is None:
             from Preferences.ShortcutsDialog import ShortcutsDialog
-            self.shortcutsDialog = ShortcutsDialog(self, 'Shortcuts')
+            self.shortcutsDialog = ShortcutsDialog(self)
         self.shortcutsDialog.populate()
         self.shortcutsDialog.show()
         
@@ -6568,6 +6648,9 @@
             if not self.helpWindow.shutdown():
                 return False
         
+        if self.__webBrowserProcess is not None:
+            self.__webBrowserShutdown()
+        
         if self.irc is not None:
             if not self.irc.shutdown():
                 return False
--- a/WebBrowser/Network/EricSchemeHandler.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/WebBrowser/Network/EricSchemeHandler.py	Wed Dec 12 19:52:24 2018 +0100
@@ -103,6 +103,8 @@
         if self.__loaded:
             return
         
+        lock = QMutexLocker(self.__mutex)
+        
         if self.__pageName == "adblock":
             contents = self.__adBlockPage()
         elif self.__pageName in ["home", "start", "startpage"]:
@@ -112,7 +114,6 @@
         else:
             contents = ""
         
-        lock = QMutexLocker(self.__mutex)
         self.__buffer.setData(contents.encode("utf-8"))
         self.__buffer.open(QIODevice.ReadOnly)
         self.open(QIODevice.ReadOnly)
--- a/WebBrowser/Network/NetworkManager.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/WebBrowser/Network/NetworkManager.py	Wed Dec 12 19:52:24 2018 +0100
@@ -50,16 +50,15 @@
         """
         super(NetworkManager, self).__init__(parent)
         
-        if not WebBrowserWindow._fromEric:
-            from E5Network.E5NetworkProxyFactory import E5NetworkProxyFactory
-            
-            self.__proxyFactory = E5NetworkProxyFactory()
-            if Preferences.getUI("UseSystemProxy"):
-                QNetworkProxyFactory.setUseSystemConfiguration(True)
-            else:
-                QNetworkProxyFactory.setApplicationProxyFactory(
-                    self.__proxyFactory)
-                QNetworkProxyFactory.setUseSystemConfiguration(False)
+        from E5Network.E5NetworkProxyFactory import E5NetworkProxyFactory
+        
+        self.__proxyFactory = E5NetworkProxyFactory()
+        if Preferences.getUI("UseSystemProxy"):
+            QNetworkProxyFactory.setUseSystemConfiguration(True)
+        else:
+            QNetworkProxyFactory.setApplicationProxyFactory(
+                self.__proxyFactory)
+            QNetworkProxyFactory.setUseSystemConfiguration(False)
         
         self.languagesChanged()
         
@@ -340,13 +339,12 @@
         """
         self.__interceptor.preferencesChanged()
             
-        if not WebBrowserWindow._fromEric:
-            if Preferences.getUI("UseSystemProxy"):
-                QNetworkProxyFactory.setUseSystemConfiguration(True)
-            else:
-                QNetworkProxyFactory.setApplicationProxyFactory(
-                    self.__proxyFactory)
-                QNetworkProxyFactory.setUseSystemConfiguration(False)
+        if Preferences.getUI("UseSystemProxy"):
+            QNetworkProxyFactory.setUseSystemConfiguration(True)
+        else:
+            QNetworkProxyFactory.setApplicationProxyFactory(
+                self.__proxyFactory)
+            QNetworkProxyFactory.setUseSystemConfiguration(False)
     
     def createRequest(self, op, request, data):
         """
--- a/WebBrowser/WebBrowserSingleApplication.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/WebBrowser/WebBrowserSingleApplication.py	Wed Dec 12 19:52:24 2018 +0100
@@ -26,7 +26,9 @@
 
 # define the protocol tokens
 SALoadUrl = 'LoadUrl'
+SANewTab = 'NewTab'
 SASearch = 'Search'
+SAShutdown = 'Shutdown'
 
 
 class WebBrowserSingleApplicationServer(SingleApplicationServer):
@@ -34,17 +36,27 @@
     Class implementing the single application server embedded within the
     Web Browser.
     
-    @signal loadUrl(str) emitted to load a URL
+    @signal loadUrl(str) emitted to load an URL
+    @signal newTab(str) emitted to load an URL in a new tab
     @signal search(str) emitted to search for a given word
+    @signal shutdown() emitted to shut down the browser
     """
     loadUrl = pyqtSignal(str)
+    newTab = pyqtSignal(str)
     search = pyqtSignal(str)
+    shutdown = pyqtSignal()
     
-    def __init__(self):
+    def __init__(self, name=""):
         """
         Constructor
+        
+        @param name name to be used by the single application server
+        @type str
         """
-        SingleApplicationServer.__init__(self, SAFile)
+        if not name:
+            name = SAFile
+        
+        SingleApplicationServer.__init__(self, name)
 
     def handleCommand(self, command, arguments):
         """
@@ -57,19 +69,34 @@
         """
         if command == SALoadUrl:
             self.__saLoadUrl(arguments[0])
-
+        
+        elif command == SANewTab:
+            self.__saNewTab(arguments[0])
+        
         elif command == SASearch:
             self.__saSearch(arguments[0])
+        
+        elif command == SAShutdown:
+            self.__saShutdown()
     
     def __saLoadUrl(self, url):
         """
-        Private method to load an URL.
+        Private method to load an URL in a new tab.
         
         @param url URL to be loaded
         @type str
         """
         self.loadUrl.emit(url)
     
+    def __saNewTab(self, url):
+        """
+        Private method to load an URL .
+        
+        @param url URL to be loaded
+        @type str
+        """
+        self.newTab.emit(url)
+    
     def __saSearch(self, word):
         """
         Private method to search for a given word.
@@ -78,6 +105,12 @@
         @type str
         """
         self.search.emit(word)
+    
+    def __saShutdown(self):
+        """
+        Private method to shut down the web browser.
+        """
+        self.shutdown.emit()
 
 
 class WebBrowserSingleApplicationClient(SingleApplicationClient):
@@ -85,17 +118,26 @@
     Class implementing the single application client of the Translations
     Previewer.
     """
-    def __init__(self):
+    def __init__(self, name=""):
         """
         Constructor
+        
+        @param name name to be used by the single application server
+        @type str
         """
-        SingleApplicationClient.__init__(self, SAFile)
+        if not name:
+            name = SAFile
         
-    def processArgs(self, args):
+        SingleApplicationClient.__init__(self, name)
+    
+    def processArgs(self, args, disconnect=True):
         """
         Public method to process the command line args passed to the UI.
         
-        @param args list of files to open
+        @param args list of command line arguments
+        @type list of str
+        @param disconnect flag indicating to disconnect when done
+        @type bool
         """
         # no args, return
         if args is None:
@@ -109,11 +151,16 @@
         for arg in args:
             if arg.startswith("--search="):
                 self.__search(arg.replace("--search=", ""))
+            elif arg.startswith("--newtab="):
+                self.__newTab(arg.replace("--newtab=", ""))
+            elif arg == "--shutdown":
+                self.__shutdown()
             elif not arg.startswith(argChars):
                 # it is an URL
                 self.__loadUrl(arg)
         
-        self.disconnect()
+        if disconnect:
+            self.disconnect()
     
     def __loadUrl(self, url):
         """
@@ -124,6 +171,15 @@
         """
         self.sendCommand(SALoadUrl, [url])
     
+    def __newTab(self, url):
+        """
+        Private method to send an URL to be loaded in a new tab.
+        
+        @param url URL to be loaded
+        @type str
+        """
+        self.sendCommand(SANewTab, [url])
+    
     def __search(self, word):
         """
         Private method to send a word to search for.
@@ -132,3 +188,9 @@
         @type str
         """
         self.sendCommand(SASearch, [word])
+    
+    def __shutdown(self):
+        """
+        Private method to signal a shutdown request to the browser.
+        """
+        self.sendCommand(SAShutdown, [])
--- a/WebBrowser/WebBrowserTabWidget.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/WebBrowser/WebBrowserTabWidget.py	Wed Dec 12 19:52:24 2018 +0100
@@ -1022,14 +1022,9 @@
                         """You have %n tab(s) open.""", "", self.count()),
                 modal=True,
                 parent=self)
-            if self.__mainWindow.fromEric:
-                quitButton = mb.addButton(
-                    self.tr("&Close"), E5MessageBox.AcceptRole)
-                quitButton.setIcon(UI.PixmapCache.getIcon("close.png"))
-            else:
-                quitButton = mb.addButton(
-                    self.tr("&Quit"), E5MessageBox.AcceptRole)
-                quitButton.setIcon(UI.PixmapCache.getIcon("exit.png"))
+            quitButton = mb.addButton(
+                self.tr("&Quit"), E5MessageBox.AcceptRole)
+            quitButton.setIcon(UI.PixmapCache.getIcon("exit.png"))
             closeTabButton = mb.addButton(
                 self.tr("C&lose Current Tab"), E5MessageBox.AcceptRole)
             closeTabButton.setIcon(UI.PixmapCache.getIcon("tabClose.png"))
--- a/WebBrowser/WebBrowserWindow.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/WebBrowser/WebBrowserWindow.py	Wed Dec 12 19:52:24 2018 +0100
@@ -84,7 +84,6 @@
     
     BrowserWindows = []
 
-    _fromEric = False
     _useQtHelp = QTHELP_AVAILABLE
     _isPrivate = False
     
@@ -116,10 +115,10 @@
     _performingShutdown = False
     _lastActiveWindow = None
     
-    def __init__(self, home, path, parent, name, fromEric=False,
+    def __init__(self, home, path, parent, name,
                  initShortcutsOnly=False, searchWord=None,
                  private=False, qthelp=False, settingsDir="",
-                 restoreSession=False, single=False):
+                 restoreSession=False, single=False, saname=""):
         """
         Constructor
         
@@ -131,9 +130,6 @@
         @type QWidget
         @param name name of this window
         @type str
-        @param fromEric flag indicating whether it was called from within
-            eric6
-        @type bool
         @keyparam initShortcutsOnly flag indicating to just initialize the
             keyboard shortcuts
         @type bool
@@ -149,6 +145,8 @@
         @type bool
         @param single flag indicating to start in single application mode
         @type bool
+        @param saname name to be used for the single application server
+        @type str
         """
         self.__hideNavigationTimer = None
         
@@ -160,8 +158,6 @@
             self.setWindowTitle(self.tr("eric6 Web Browser"))
         
         self.__settingsDir = settingsDir
-        self.__fromEric = fromEric
-        WebBrowserWindow._fromEric = fromEric
         self.__initShortcutsOnly = initShortcutsOnly
         self.setWindowIcon(UI.PixmapCache.getIcon("ericWeb.png"))
 
@@ -170,12 +166,13 @@
         
         WebBrowserWindow._isPrivate = private
         
+        self.__shortcutsDialog = None
+        
         self.__eventMouseButtons = Qt.NoButton
         self.__eventKeyboardModifiers = Qt.NoModifier
         
         if self.__initShortcutsOnly:
-            WebBrowserWindow.setUseQtHelp(
-                self.__fromEric or qthelp or bool(searchWord))
+            WebBrowserWindow.setUseQtHelp(qthelp or bool(searchWord))
             self.__initActions()
         else:
             if qVersionTuple() < (5, 11, 0) and \
@@ -183,8 +180,7 @@
                 os.environ["QTWEBENGINE_REMOTE_DEBUGGING"] = \
                     str(Preferences.getWebBrowser("WebInspectorPort"))
             
-            WebBrowserWindow.setUseQtHelp(
-                self.__fromEric or qthelp or bool(searchWord))
+            WebBrowserWindow.setUseQtHelp(qthelp or bool(searchWord))
             
             self.webProfile(private)
             self.networkManager()
@@ -207,13 +203,12 @@
             from .Navigation.NavigationContainer import NavigationContainer
             from .Bookmarks.BookmarksToolBar import BookmarksToolBar
             
-            if not self.__fromEric:
-                self.setStyle(Preferences.getUI("Style"),
-                              Preferences.getUI("StyleSheet"))
-                
-                # initialize some SSL stuff
-                from E5Network.E5SslUtilities import initSSL
-                initSSL()
+            self.setStyle(Preferences.getUI("Style"),
+                          Preferences.getUI("StyleSheet"))
+            
+            # initialize some SSL stuff
+            from E5Network.E5SslUtilities import initSSL
+            initSSL()
             
             if WebBrowserWindow._useQtHelp:
                 self.__helpEngine = QHelpEngine(
@@ -415,7 +410,7 @@
             if not Preferences.getWebBrowser("StatusBarVisible"):
                 self.statusBar().hide()
             
-            if not self.__fromEric and len(WebBrowserWindow.BrowserWindows):
+            if len(WebBrowserWindow.BrowserWindows):
                 QDesktopServices.setUrlHandler(
                     "http", WebBrowserWindow.BrowserWindows[0].urlHandler)
                 QDesktopServices.setUrlHandler(
@@ -471,9 +466,11 @@
             self.__toolbarStates = self.saveState()
             
             if single:
-                self.SAServer = WebBrowserSingleApplicationServer()
+                self.SAServer = WebBrowserSingleApplicationServer(saname)
                 self.SAServer.loadUrl.connect(self.__saLoadUrl)
+                self.SAServer.newTab.connect(self.__saNewTab)
                 self.SAServer.search.connect(self.__saSearchWord)
+                self.SAServer.shutdown.connect(self.shutdown)
             else:
                 self.SAServer = None
             
@@ -517,16 +514,6 @@
         """
         return self.__tabWidget
     
-    def fromEric(self):
-        """
-        Public method to check, if the web browser was called from within the
-        eric IDE.
-        
-        @return flag indicating that the browserw as opened from within eric
-        @rtype bool
-        """
-        return self.__fromEric
-    
     def __setIconDatabasePath(self, enable=True):
         """
         Private method to set the favicons path.
@@ -969,10 +956,7 @@
             """<p>Quit the eric6 Web Browser.</p>"""
         ))
         if not self.__initShortcutsOnly:
-            if self.__fromEric:
-                self.exitAct.triggered.connect(self.close)
-            else:
-                self.exitAct.triggered.connect(self.shutdown)
+            self.exitAct.triggered.connect(self.shutdown)
         self.__actions.append(self.exitAct)
         
         self.backAct = E5Action(
@@ -1989,13 +1973,28 @@
             self.virustotalScanCurrentAct.setEnabled(False)
             self.virustotalIpReportAct.setEnabled(False)
             self.virustotalDomainReportAct.setEnabled(False)
+
+        self.shortcutsAct = E5Action(
+            self.tr('Keyboard Shortcuts'),
+            UI.PixmapCache.getIcon("configureShortcuts.png"),
+            self.tr('Keyboard &Shortcuts...'),
+            0, 0,
+            self, 'webbrowser_keyboard_shortcuts')
+        self.shortcutsAct.setStatusTip(self.tr(
+            'Set the keyboard shortcuts'))
+        self.shortcutsAct.setWhatsThis(self.tr(
+            """<b>Keyboard Shortcuts</b>"""
+            """<p>Set the keyboard shortcuts of the application"""
+            """ with your prefered values.</p>"""
+        ))
+        self.shortcutsAct.triggered.connect(self.__configShortcuts)
+        self.__actions.append(self.shortcutsAct)
         
         self.backAct.setEnabled(False)
         self.forwardAct.setEnabled(False)
         
         # now read the keyboard shortcuts for the actions
-        Shortcuts.readShortcuts(
-            helpViewer=self, helpViewerCategory="webBrowser")
+        Shortcuts.readShortcuts(helpViewer=self)
     
     def getActions(self):
         """
@@ -2004,7 +2003,16 @@
         @return list of all actions (list of E5Action)
         """
         return self.__actions[:]
-        
+    
+    def getActionsCategory(self):
+        """
+        Public method to get the category of the defined actions.
+        
+        @return category of the actions
+        @rtype str
+        """
+        return "WebBrowser"
+    
     def __initMenus(self):
         """
         Private method to create the menus.
@@ -2117,6 +2125,9 @@
         
         menu = mb.addMenu(self.tr('&Settings'))
         menu.addAction(self.prefAct)
+        menu.addSeparator()
+        menu.addAction(self.shortcutsAct)
+        menu.addSeparator()
         menu.addAction(self.acceptedLanguagesAct)
         menu.addAction(self.cookiesAct)
         menu.addAction(self.flashCookiesAct)
@@ -2240,6 +2251,8 @@
         self.__superMenu.addAction(self.prefAct)
         
         menu = self.__superMenu.addMenu(self.tr('Settings'))
+        menu.addAction(self.shortcutsAct)
+        menu.addSeparator()
         menu.addAction(self.acceptedLanguagesAct)
         menu.addAction(self.cookiesAct)
         menu.addAction(self.flashCookiesAct)
@@ -2522,7 +2535,7 @@
         else:
             linkName = link
         h = WebBrowserWindow(linkName, ".", self.parent(), "webbrowser",
-                             self.__fromEric, private=self.isPrivate(),
+                             private=self.isPrivate(),
                              restoreSession=restoreSession)
         h.show()
         
@@ -2850,13 +2863,12 @@
         
         self.__isClosing = True
         
-        if not self.__fromEric:
-            if not WebBrowserWindow._performingShutdown and \
-                len(WebBrowserWindow.BrowserWindows) == 1 and \
-                    not WebBrowserWindow.isPrivate():
-                # shut down the session manager in case the last window is
-                # about to be closed
-                self.sessionManager().shutdown()
+        if not WebBrowserWindow._performingShutdown and \
+            len(WebBrowserWindow.BrowserWindows) == 1 and \
+                not WebBrowserWindow.isPrivate():
+            # shut down the session manager in case the last window is
+            # about to be closed
+            self.sessionManager().shutdown()
         
         self.__bookmarksToolBar.setModel(None)
         
@@ -2887,7 +2899,7 @@
         
         try:
             browserIndex = WebBrowserWindow.BrowserWindows.index(self)
-            if not self.__fromEric and len(WebBrowserWindow.BrowserWindows):
+            if len(WebBrowserWindow.BrowserWindows):
                 if browserIndex == 0:
                     if len(WebBrowserWindow.BrowserWindows) > 1:
                         # first window will be deleted
@@ -2900,18 +2912,17 @@
                     else:
                         QDesktopServices.unsetUrlHandler("http")
                         QDesktopServices.unsetUrlHandler("https")
-            if self.__fromEric or len(WebBrowserWindow.BrowserWindows) > 0:
+            if len(WebBrowserWindow.BrowserWindows) > 0:
                 del WebBrowserWindow.BrowserWindows[browserIndex]
         except ValueError:
             pass
         
-        if not self.__fromEric:
-            Preferences.syncPreferences()
-            if not WebBrowserWindow._performingShutdown and \
-                    len(WebBrowserWindow.BrowserWindows) == 0:
-                # shut down the browser in case the last window was
-                # simply closed
-                self.shutdown()
+        Preferences.syncPreferences()
+        if not WebBrowserWindow._performingShutdown and \
+                len(WebBrowserWindow.BrowserWindows) == 0:
+            # shut down the browser in case the last window was
+            # simply closed
+            self.shutdown()
         
         return True
     
@@ -2938,14 +2949,9 @@
                     .format(windowCount, tabCount),
                     modal=True,
                     parent=self)
-                if self.fromEric:
-                    quitButton = mb.addButton(
-                        self.tr("&Close"), E5MessageBox.AcceptRole)
-                    quitButton.setIcon(UI.PixmapCache.getIcon("close.png"))
-                else:
-                    quitButton = mb.addButton(
-                        self.tr("&Quit"), E5MessageBox.AcceptRole)
-                    quitButton.setIcon(UI.PixmapCache.getIcon("exit.png"))
+                quitButton = mb.addButton(
+                    self.tr("&Quit"), E5MessageBox.AcceptRole)
+                quitButton.setIcon(UI.PixmapCache.getIcon("exit.png"))
                 mb.addButton(E5MessageBox.Cancel)
                 mb.exec_()
                 return mb.clickedButton() == quitButton
@@ -3272,9 +3278,8 @@
         """
         Public slot to handle a change of preferences.
         """
-        if not self.__fromEric:
-            self.setStyle(Preferences.getUI("Style"),
-                          Preferences.getUI("StyleSheet"))
+        self.setStyle(Preferences.getUI("Style"),
+                      Preferences.getUI("StyleSheet"))
         
         self.__initWebEngineSettings()
         
@@ -3336,7 +3341,7 @@
         @type bool
         """
         self.passwordManager().masterPasswordChanged(oldPassword, newPassword)
-        if self.__fromEric and local:
+        if local:
             # we were called from our local configuration dialog
             Preferences.convertPasswords(oldPassword, newPassword)
             Utilities.crypto.changeRememberedMaster(newPassword)
@@ -4798,23 +4803,19 @@
             (None = use configured timeout, 0 = indefinitely)
         @type int
         """
-        if cls._fromEric:
-            e5App().getObject("UserInterface").showNotification(
-                icon, heading, text, timeout)
-        else:
-            if Preferences.getUI("NotificationsEnabled"):
-                if cls._notification is None:
-                    from UI.NotificationWidget import NotificationWidget
-                    cls._notification = NotificationWidget()
-                cls._notification.setPixmap(icon)
-                cls._notification.setHeading(heading)
-                cls._notification.setText(text)
-                if timeout is None:
-                    timeout = Preferences.getUI("NotificationTimeout")
-                cls._notification.setTimeout(timeout)
-                cls._notification.move(
-                    Preferences.getUI("NotificationPosition"))
-                cls._notification.show()
+        if Preferences.getUI("NotificationsEnabled"):
+            if cls._notification is None:
+                from UI.NotificationWidget import NotificationWidget
+                cls._notification = NotificationWidget()
+            cls._notification.setPixmap(icon)
+            cls._notification.setHeading(heading)
+            cls._notification.setText(text)
+            if timeout is None:
+                timeout = Preferences.getUI("NotificationTimeout")
+            cls._notification.setTimeout(timeout)
+            cls._notification.move(
+                Preferences.getUI("NotificationPosition"))
+            cls._notification.show()
     
     @classmethod
     def notificationsEnabled(cls):
@@ -4823,10 +4824,7 @@
         
         @return flag indicating, if notifications are enabled (boolean)
         """
-        if cls._fromEric:
-            return e5App().getObject("UserInterface").notificationsEnabled()
-        else:
-            return Preferences.getUI("NotificationsEnabled")
+        return Preferences.getUI("NotificationsEnabled")
     
     ######################################
     ## Support for global status bar below
@@ -4846,8 +4844,6 @@
         """
         if cls.BrowserWindows:
             return cls.BrowserWindows[0].statusBar()
-        elif cls._fromEric:
-            return e5App().getObject("UserInterface").statusBar()
         else:
             return None
     
@@ -5026,6 +5022,18 @@
         self.__linkActivated(url)
     
     @pyqtSlot(str)
+    def __saNewTab(self, urlStr):
+        """
+        Private slot to load an URL received via the single application
+        protocol in a new tab.
+        
+        @param urlStr URL to be loaded
+        @type str
+        """
+        url = QUrl.fromUserInput(urlStr)
+        self.newTab(url)
+    
+    @pyqtSlot(str)
     def __saSearchWord(self, word):
         """
         Private slot to search for the given word.
@@ -5036,3 +5044,17 @@
         if WebBrowserWindow._useQtHelp:
             self.__searchWord = word
             self.__searchForWord()
+    
+    ######################################################
+    ## Methods below implement shortcuts related functions
+    ######################################################
+    
+    def __configShortcuts(self):
+        """
+        Private slot to configure the keyboard shortcuts.
+        """
+        if self.__shortcutsDialog is None:
+            from Preferences.ShortcutsDialog import ShortcutsDialog
+            self.__shortcutsDialog = ShortcutsDialog(self)
+        self.__shortcutsDialog.populate(helpViewer=self)
+        self.__shortcutsDialog.show()
--- a/eric6_browser.py	Wed Dec 12 19:43:53 2018 +0100
+++ b/eric6_browser.py	Wed Dec 12 19:52:24 2018 +0100
@@ -111,11 +111,18 @@
     private = False
     qthelp = False
     single = False
+    name = ""
     
     for arg in reversed(argv):
         if arg.startswith("--search="):
             searchWord = argv[1].split("=", 1)[1]
             argv.remove(arg)
+        elif arg.startswith("--name="):
+            name = arg.replace("--name=", "")
+            argv.remove(arg)
+        elif arg.startswith("--newtab="):
+            # only used for single application client
+            argv.remove(arg)
         elif arg == "--private":
             private = True
             argv.remove(arg)
@@ -136,7 +143,7 @@
     browser = WebBrowserWindow(home, '.', None, 'web_browser',
                                searchWord=searchWord, private=private,
                                settingsDir=SettingsDir, qthelp=qthelp,
-                               single=single)
+                               single=single, saname=name)
     return browser
 
 
@@ -163,12 +170,11 @@
     if not Globals.checkBlacklistedVersions():
         sys.exit(100)
     
-    
     # set the library paths for plugins
     Startup.setLibraryPaths()
     
     app = E5Application(sys.argv)
-    if not "--private" in sys.argv:
+    if "--private" not in sys.argv:
         client = WebBrowserSingleApplicationClient()
         res = client.connect()
         if res > 0:
@@ -176,7 +182,8 @@
                 client.processArgs(sys.argv[1:])
             sys.exit(0)
         elif res < 0:
-            print("eric6_trpreviewer: {0}".format(client.errstr()))
+            print("eric6_browser: {0}".format(client.errstr()))
+            # __IGNORE_WARNING_M801__
             sys.exit(res)
     
     res = Startup.simpleAppStartup(sys.argv,

eric ide

mercurial