Web Browser (QtWebKit): applied the changes of the new Web Brwoser to the QtWebKit based variant.

Sat, 15 Dec 2018 16:21:38 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 15 Dec 2018 16:21:38 +0100
changeset 6630
bddd12f27a4c
parent 6629
643ec3a53d17
child 6631
0a2f0feac79d

Web Browser (QtWebKit): applied the changes of the new Web Brwoser to the QtWebKit based variant.

E5XML/ShortcutsWriter.py file | annotate | diff | comparison | revisions
Globals/__init__.py file | annotate | diff | comparison | revisions
Helpviewer/HelpSingleApplication.py file | annotate | diff | comparison | revisions
Helpviewer/HelpWindow.py file | annotate | diff | comparison | revisions
Helpviewer/QtHelpDocumentationDialog.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationDialog.py file | annotate | diff | comparison | revisions
Preferences/ConfigurationPages/HelpViewersPage.py file | annotate | diff | comparison | revisions
Preferences/Shortcuts.py file | annotate | diff | comparison | revisions
Preferences/ShortcutsDialog.py file | annotate | diff | comparison | revisions
Tools/TrayStarter.py file | annotate | diff | comparison | revisions
Tools/webBrowserSupport.py file | annotate | diff | comparison | revisions
UI/UserInterface.py file | annotate | diff | comparison | revisions
WebBrowser/Tools/WebBrowserTools.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserSingleApplication.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
changelog file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
eric6_browser.py file | annotate | diff | comparison | revisions
eric6_configure.py file | annotate | diff | comparison | revisions
eric6_tray.py file | annotate | diff | comparison | revisions
eric6_webbrowser.py file | annotate | diff | comparison | revisions
--- a/E5XML/ShortcutsWriter.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/E5XML/ShortcutsWriter.py	Sat Dec 15 16:21:38 2018 +0100
@@ -96,14 +96,6 @@
                 if hasattr(ref, "getActions"):
                     self.__writeActions(category, ref.getActions())
         
-            try:
-                self.__writeActions(
-                    "HelpViewer",
-                    e5App().getObject("DummyHelpViewer").getActions())
-            except KeyError:
-                # no QtWebKit available
-                pass
-        
         else:
             self.__writeActions(
                 helpViewer.getActionsCategory(),
--- a/Globals/__init__.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/Globals/__init__.py	Sat Dec 15 16:21:38 2018 +0100
@@ -12,6 +12,10 @@
 #
 
 from __future__ import unicode_literals
+try:
+    str = unicode       # __IGNORE_EXCEPTION__
+except NameError:
+    pass
 
 import sys
 import os
@@ -19,7 +23,7 @@
 import shutil
 
 from PyQt5.QtCore import QDir, QLibraryInfo, QByteArray, QCoreApplication, \
-    QT_VERSION_STR, QT_VERSION
+    QT_VERSION_STR, QT_VERSION, QProcess, qVersion
 
 # names of the various settings objects
 settingsNameOrganization = "Eric6"
@@ -468,5 +472,29 @@
     else:
         return value
 
+
+###############################################################################
+## functions for web browser variant detection
+###############################################################################
+
+
+def getWebBrowserSupport():
+    """
+    Module function to determine the supported web browser variant.
+    
+    @return string indicating the supported web browser variant ("QtWebEngine",
+        "QtWebKit" or "None")
+    @rtype str
+    """
+    from eric6config import getConfig
+    scriptPath = os.path.join(getConfig("ericDir"), "Tools",
+                              "webBrowserSupport.py")
+    proc = QProcess()
+    proc.start(sys.executable, [scriptPath, qVersion()])
+    if proc.waitForFinished(10000):
+        variant = str(proc.readAllStandardOutput(), "utf-8", 'replace').strip()
+    else:
+        variant = "None"
+    return variant
 #
 # eflag: noqa = M801
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Helpviewer/HelpSingleApplication.py	Sat Dec 15 16:21:38 2018 +0100
@@ -0,0 +1,195 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+
+"""
+Module implementing the single application server and client for the web
+browser.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSignal
+
+from Toolbox.SingleApplication import SingleApplicationClient, \
+    SingleApplicationServer
+
+import Globals
+
+###########################################################################
+## define some module global stuff
+###########################################################################
+
+SAFile = "eric6_help"
+
+# define the protocol tokens
+SALoadUrl = 'LoadUrl'
+SANewTab = 'NewTab'
+SASearch = 'Search'
+SAShutdown = 'Shutdown'
+
+
+class HelpSingleApplicationServer(SingleApplicationServer):
+    """
+    Class implementing the single application server embedded within the
+    Help viewer.
+    
+    @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, name=""):
+        """
+        Constructor
+        
+        @param name name to be used by the single application server
+        @type str
+        """
+        if not name:
+            name = SAFile
+        
+        SingleApplicationServer.__init__(self, name)
+
+    def handleCommand(self, command, arguments):
+        """
+        Public slot to handle the command sent by the client.
+        
+        @param command command sent by the client
+        @type str
+        @param arguments list of command arguments
+        @type list of str
+        """
+        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 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.
+        
+        @param word word to be searched for
+        @type str
+        """
+        self.search.emit(word)
+    
+    def __saShutdown(self):
+        """
+        Private method to shut down the web browser.
+        """
+        self.shutdown.emit()
+
+
+class HelpSingleApplicationClient(SingleApplicationClient):
+    """
+    Class implementing the single application client of the help viewer.
+    """
+    def __init__(self, name=""):
+        """
+        Constructor
+        
+        @param name name to be used by the single application server
+        @type str
+        """
+        if not name:
+            name = SAFile
+        
+        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 command line arguments
+        @type list of str
+        @param disconnect flag indicating to disconnect when done
+        @type bool
+        """
+        # no args, return
+        if args is None:
+            return
+        
+        if Globals.isWindowsPlatform():
+            argChars = ('-', '/')
+        else:
+            argChars = ('-', )
+        
+        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)
+        
+        if disconnect:
+            self.disconnect()
+    
+    def __loadUrl(self, url):
+        """
+        Private method to send an URL to be loaded.
+        
+        @param url URL to be loaded
+        @type str
+        """
+        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.
+        
+        @param word to to be searched for
+        @type str
+        """
+        self.sendCommand(SASearch, [word])
+    
+    def __shutdown(self):
+        """
+        Private method to signal a shutdown request to the browser.
+        """
+        self.sendCommand(SAShutdown, [])
--- a/Helpviewer/HelpWindow.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/Helpviewer/HelpWindow.py	Sat Dec 15 16:21:38 2018 +0100
@@ -16,7 +16,7 @@
 import os
 
 from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QByteArray, QSize, QTimer, \
-    QUrl, QThread, QTextCodec
+    QUrl, QThread, QTextCodec, QFileInfo
 from PyQt5.QtGui import QDesktopServices, QKeySequence, QFont, QFontMetrics, \
     QIcon
 from PyQt5.QtWidgets import QWidget, QVBoxLayout, QSizePolicy, QDockWidget, \
@@ -56,6 +56,8 @@
 import UI.Config
 from UI.Info import Version
 
+from .HelpSingleApplication import HelpSingleApplicationServer
+
 
 class HelpWindow(E5MainWindow):
     """
@@ -72,7 +74,6 @@
     
     helpwindows = []
 
-    _fromEric = False
     _useQtHelp = QTHELP_AVAILABLE
     
     _networkAccessManager = None
@@ -94,218 +95,231 @@
     _flashCookieManager = None
     _zoomManager = None
     
-    def __init__(self, home, path, parent, name, fromEric=False,
-                 initShortcutsOnly=False, searchWord=None):
+    def __init__(self, home, path, parent, name,
+                 searchWord=None, qthelp=False, single=False, saname=""):
         """
         Constructor
         
-        @param home the URL to be shown (string)
-        @param path the path of the working dir (usually '.') (string)
-        @param parent parent widget of this window (QWidget)
-        @param name name of this window (string)
-        @param fromEric flag indicating whether it was called from within
-            eric6 (boolean)
-        @keyparam initShortcutsOnly flag indicating to just initialize the
-            keyboard shortcuts (boolean)
-        @keyparam searchWord word to search for (string)
+        @param home the URL to be shown
+        @type str
+        @param path the path of the working dir (usually '.')
+        @type str
+        @param parent parent widget of this window
+        @type QWidget
+        @param name name of this window
+        @type str
+        @param searchWord word to search for
+        @type str
+        @param qthelp flag indicating to enable the QtHelp support
+        @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
         """
         super(HelpWindow, self).__init__(parent)
         self.setObjectName(name)
         self.setWindowTitle(self.tr("eric6 Web Browser"))
         
-        self.fromEric = fromEric
-        self.__class__._fromEric = fromEric
-        self.initShortcutsOnly = initShortcutsOnly
         self.setWindowIcon(UI.PixmapCache.getIcon("ericWeb.png"))
 
         self.mHistory = []
         self.__lastConfigurationPageName = ""
         self.__lastActiveWindow = None
         
+        self.__shortcutsDialog = None
+        
         self.__eventMouseButtons = Qt.NoButton
         self.__eventKeyboardModifiers = Qt.NoModifier
         
-        if self.initShortcutsOnly:
-            self.__initActions()
-        else:
-            from .SearchWidget import SearchWidget
-            from .HelpTocWidget import HelpTocWidget
-            from .HelpIndexWidget import HelpIndexWidget
-            from .HelpSearchWidget import HelpSearchWidget
-            from .HelpBrowserWV import HelpBrowser
-            from .HelpTabWidget import HelpTabWidget
-            from .AdBlock.AdBlockIcon import AdBlockIcon
-            from .VirusTotal.VirusTotalApi import VirusTotalAPI
-            
-            HelpWindow.setUseQtHelp(self.fromEric)
-            
-            if not self.fromEric:
-                self.setStyle(Preferences.getUI("Style"),
-                              Preferences.getUI("StyleSheet"))
-                
-                # initialize some SSL stuff
-                from E5Network.E5SslUtilities import initSSL
-                initSSL()
-            
-            if HelpWindow._useQtHelp:
-                self.__helpEngine = QHelpEngine(
-                    HelpWindow.getQtHelpCollectionFileName(),
-                    self)
-                self.__removeOldDocumentation()
-                self.__helpEngine.warning.connect(self.__warning)
-            else:
-                self.__helpEngine = None
-            self.__helpInstaller = None
-            
-            self.__zoomWidget = E5ZoomWidget(
-                UI.PixmapCache.getPixmap("zoomOut.png"),
-                UI.PixmapCache.getPixmap("zoomIn.png"),
-                UI.PixmapCache.getPixmap("zoomReset.png"), self)
-            self.statusBar().addPermanentWidget(self.__zoomWidget)
-            self.__zoomWidget.setMapping(
-                HelpBrowser.ZoomLevels, HelpBrowser.ZoomLevelDefault)
-            self.__zoomWidget.valueChanged.connect(self.__zoomValueChanged)
+        HelpWindow.setUseQtHelp(qthelp or bool(searchWord))
             
-            self.tabWidget = HelpTabWidget(self)
-            self.tabWidget.currentChanged[int].connect(self.__currentChanged)
-            self.tabWidget.titleChanged.connect(self.__titleChanged)
-            self.tabWidget.showMessage.connect(self.statusBar().showMessage)
-            self.tabWidget.browserZoomValueChanged.connect(
-                self.__zoomWidget.setValue)
-            
-            self.findDlg = SearchWidget(self, self)
-            centralWidget = QWidget()
-            layout = QVBoxLayout()
-            layout.setContentsMargins(1, 1, 1, 1)
-            layout.addWidget(self.tabWidget)
-            layout.addWidget(self.findDlg)
-            self.tabWidget.setSizePolicy(
-                QSizePolicy.Preferred, QSizePolicy.Expanding)
-            centralWidget.setLayout(layout)
-            self.setCentralWidget(centralWidget)
-            self.findDlg.hide()
+        from .SearchWidget import SearchWidget
+        from .HelpTocWidget import HelpTocWidget
+        from .HelpIndexWidget import HelpIndexWidget
+        from .HelpSearchWidget import HelpSearchWidget
+        from .HelpBrowserWV import HelpBrowser
+        from .HelpTabWidget import HelpTabWidget
+        from .AdBlock.AdBlockIcon import AdBlockIcon
+        from .VirusTotal.VirusTotalApi import VirusTotalAPI
+    
+        self.setStyle(Preferences.getUI("Style"),
+                      Preferences.getUI("StyleSheet"))
+        
+        # initialize some SSL stuff
+        from E5Network.E5SslUtilities import initSSL
+        initSSL()
+        
+        if HelpWindow._useQtHelp:
+            self.__helpEngine = QHelpEngine(
+                HelpWindow.getQtHelpCollectionFileName(),
+                self)
+            self.__removeOldDocumentation()
+            self.__helpEngine.warning.connect(self.__warning)
+        else:
+            self.__helpEngine = None
+        self.__helpInstaller = None
+        
+        self.__zoomWidget = E5ZoomWidget(
+            UI.PixmapCache.getPixmap("zoomOut.png"),
+            UI.PixmapCache.getPixmap("zoomIn.png"),
+            UI.PixmapCache.getPixmap("zoomReset.png"), self)
+        self.statusBar().addPermanentWidget(self.__zoomWidget)
+        self.__zoomWidget.setMapping(
+            HelpBrowser.ZoomLevels, HelpBrowser.ZoomLevelDefault)
+        self.__zoomWidget.valueChanged.connect(self.__zoomValueChanged)
+        
+        self.tabWidget = HelpTabWidget(self)
+        self.tabWidget.currentChanged[int].connect(self.__currentChanged)
+        self.tabWidget.titleChanged.connect(self.__titleChanged)
+        self.tabWidget.showMessage.connect(self.statusBar().showMessage)
+        self.tabWidget.browserZoomValueChanged.connect(
+            self.__zoomWidget.setValue)
+        
+        self.findDlg = SearchWidget(self, self)
+        centralWidget = QWidget()
+        layout = QVBoxLayout()
+        layout.setContentsMargins(1, 1, 1, 1)
+        layout.addWidget(self.tabWidget)
+        layout.addWidget(self.findDlg)
+        self.tabWidget.setSizePolicy(
+            QSizePolicy.Preferred, QSizePolicy.Expanding)
+        centralWidget.setLayout(layout)
+        self.setCentralWidget(centralWidget)
+        self.findDlg.hide()
+        
+        if HelpWindow._useQtHelp:
+            # setup the TOC widget
+            self.__tocWindow = HelpTocWidget(self.__helpEngine, self)
+            self.__tocDock = QDockWidget(self.tr("Contents"), self)
+            self.__tocDock.setObjectName("TocWindow")
+            self.__tocDock.setWidget(self.__tocWindow)
+            self.addDockWidget(Qt.LeftDockWidgetArea, self.__tocDock)
             
-            if HelpWindow._useQtHelp:
-                # setup the TOC widget
-                self.__tocWindow = HelpTocWidget(self.__helpEngine, self)
-                self.__tocDock = QDockWidget(self.tr("Contents"), self)
-                self.__tocDock.setObjectName("TocWindow")
-                self.__tocDock.setWidget(self.__tocWindow)
-                self.addDockWidget(Qt.LeftDockWidgetArea, self.__tocDock)
-                
-                # setup the index widget
-                self.__indexWindow = HelpIndexWidget(self.__helpEngine, self)
-                self.__indexDock = QDockWidget(self.tr("Index"), self)
-                self.__indexDock.setObjectName("IndexWindow")
-                self.__indexDock.setWidget(self.__indexWindow)
-                self.addDockWidget(Qt.LeftDockWidgetArea, self.__indexDock)
-                
-                # setup the search widget
-                self.__searchWord = searchWord
-                self.__indexing = False
-                self.__indexingProgress = None
-                self.__searchEngine = self.__helpEngine.searchEngine()
-                self.__searchEngine.indexingStarted.connect(
-                    self.__indexingStarted)
-                self.__searchEngine.indexingFinished.connect(
-                    self.__indexingFinished)
-                self.__searchWindow = HelpSearchWidget(
-                    self.__searchEngine, self)
-                self.__searchDock = QDockWidget(self.tr("Search"), self)
-                self.__searchDock.setObjectName("SearchWindow")
-                self.__searchDock.setWidget(self.__searchWindow)
-                self.addDockWidget(Qt.LeftDockWidgetArea, self.__searchDock)
+            # setup the index widget
+            self.__indexWindow = HelpIndexWidget(self.__helpEngine, self)
+            self.__indexDock = QDockWidget(self.tr("Index"), self)
+            self.__indexDock.setObjectName("IndexWindow")
+            self.__indexDock.setWidget(self.__indexWindow)
+            self.addDockWidget(Qt.LeftDockWidgetArea, self.__indexDock)
             
-            if Preferences.getHelp("SaveGeometry"):
-                g = Preferences.getGeometry("HelpViewerGeometry")
-            else:
-                g = QByteArray()
-            if g.isEmpty():
-                s = QSize(800, 800)
-                self.resize(s)
-            else:
-                self.restoreGeometry(g)
-            
-            self.__setIconDatabasePath()
-            self.__initWebSettings()
-            
-            self.__initActions()
-            self.__initMenus()
-            self.__initToolbars()
-            
-            self.historyManager()
-            
-            syncMgr = self.syncManager()
-            syncMgr.syncMessage.connect(self.statusBar().showMessage)
-            syncMgr.syncError.connect(self.statusBar().showMessage)
-            
-            self.tabWidget.newBrowser(home)
-            self.tabWidget.currentBrowser().setFocus()
-            
-            self.__class__.helpwindows.append(self)
-            
-            self.__adBlockIcon = AdBlockIcon(self)
-            self.statusBar().addPermanentWidget(self.__adBlockIcon)
-            self.__adBlockIcon.setEnabled(
-                Preferences.getHelp("AdBlockEnabled"))
-            self.tabWidget.currentChanged[int].connect(
-                self.__adBlockIcon.currentChanged)
-            self.tabWidget.sourceChanged.connect(
-                self.__adBlockIcon.sourceChanged)
-            
-            self.networkIcon = E5NetworkIcon(self)
-            self.statusBar().addPermanentWidget(self.networkIcon)
+            # setup the search widget
+            self.__searchWord = searchWord
+            self.__indexing = False
+            self.__indexingProgress = None
+            self.__searchEngine = self.__helpEngine.searchEngine()
+            self.__searchEngine.indexingStarted.connect(
+                self.__indexingStarted)
+            self.__searchEngine.indexingFinished.connect(
+                self.__indexingFinished)
+            self.__searchWindow = HelpSearchWidget(
+                self.__searchEngine, self)
+            self.__searchDock = QDockWidget(self.tr("Search"), self)
+            self.__searchDock.setObjectName("SearchWindow")
+            self.__searchDock.setWidget(self.__searchWindow)
+            self.addDockWidget(Qt.LeftDockWidgetArea, self.__searchDock)
+        
+        if Preferences.getHelp("SaveGeometry"):
+            g = Preferences.getGeometry("HelpViewerGeometry")
+        else:
+            g = QByteArray()
+        if g.isEmpty():
+            s = QSize(800, 800)
+            self.resize(s)
+        else:
+            self.restoreGeometry(g)
+        
+        self.__setIconDatabasePath()
+        self.__initWebSettings()
+        
+        self.__initActions()
+        self.__initMenus()
+        self.__initToolbars()
+        
+        self.historyManager()
+        
+        syncMgr = self.syncManager()
+        syncMgr.syncMessage.connect(self.statusBar().showMessage)
+        syncMgr.syncError.connect(self.statusBar().showMessage)
+        
+        self.tabWidget.newBrowser(home)
+        self.tabWidget.currentBrowser().setFocus()
+        
+        self.__class__.helpwindows.append(self)
+        
+        self.__adBlockIcon = AdBlockIcon(self)
+        self.statusBar().addPermanentWidget(self.__adBlockIcon)
+        self.__adBlockIcon.setEnabled(
+            Preferences.getHelp("AdBlockEnabled"))
+        self.tabWidget.currentChanged[int].connect(
+            self.__adBlockIcon.currentChanged)
+        self.tabWidget.sourceChanged.connect(
+            self.__adBlockIcon.sourceChanged)
+        
+        self.networkIcon = E5NetworkIcon(self)
+        self.statusBar().addPermanentWidget(self.networkIcon)
+        
+        if len(HelpWindow.helpwindows):
+            QDesktopServices.setUrlHandler(
+                "http", HelpWindow.helpwindows[0].urlHandler)
+            QDesktopServices.setUrlHandler(
+                "https", HelpWindow.helpwindows[0].urlHandler)
+        
+        # setup connections
+        self.__activating = False
+        if HelpWindow._useQtHelp:
+            # TOC window
+            self.__tocWindow.linkActivated.connect(self.__linkActivated)
+            self.__tocWindow.escapePressed.connect(
+                self.__activateCurrentBrowser)
             
-            if not self.fromEric and len(HelpWindow.helpwindows):
-                QDesktopServices.setUrlHandler(
-                    "http", HelpWindow.helpwindows[0].urlHandler)
-                QDesktopServices.setUrlHandler(
-                    "https", HelpWindow.helpwindows[0].urlHandler)
-            
-            # setup connections
-            self.__activating = False
-            if HelpWindow._useQtHelp:
-                # TOC window
-                self.__tocWindow.linkActivated.connect(self.__linkActivated)
-                self.__tocWindow.escapePressed.connect(
-                    self.__activateCurrentBrowser)
-                # index window
-                self.__indexWindow.linkActivated.connect(self.__linkActivated)
-                self.__indexWindow.linksActivated.connect(
-                    self.__linksActivated)
-                self.__indexWindow.escapePressed.connect(
-                    self.__activateCurrentBrowser)
-                # search window
-                self.__searchWindow.linkActivated.connect(
-                    self.__linkActivated)
-                self.__searchWindow.escapePressed.connect(
-                    self.__activateCurrentBrowser)
+            # index window
+            self.__indexWindow.linkActivated.connect(self.__linkActivated)
+            self.__indexWindow.linksActivated.connect(
+                self.__linksActivated)
+            self.__indexWindow.escapePressed.connect(
+                self.__activateCurrentBrowser)
             
-            state = Preferences.getHelp("HelpViewerState")
-            self.restoreState(state)
-            
-            self.__initHelpDb()
-            
-            self.__virusTotal = VirusTotalAPI(self)
-            self.__virusTotal.submitUrlError.connect(
-                self.__virusTotalSubmitUrlError)
-            self.__virusTotal.urlScanReport.connect(
-                self.__virusTotalUrlScanReport)
-            self.__virusTotal.fileScanReport.connect(
-                self.__virusTotalFileScanReport)
-            
-            self.__shutdownCalled = False
-            
-            self.flashCookieManager()
-            
-            if HelpWindow._useQtHelp:
-                QTimer.singleShot(0, self.__lookForNewDocumentation)
-                if self.__searchWord is not None:
-                    QTimer.singleShot(0, self.__searchForWord)
-            
-            e5App().focusChanged.connect(self.__appFocusChanged)
-            
-            QTimer.singleShot(0, syncMgr.loadSettings)
+            # search window
+            self.__searchWindow.linkActivated.connect(
+                self.__linkActivated)
+            self.__searchWindow.escapePressed.connect(
+                self.__activateCurrentBrowser)
+        
+        state = Preferences.getHelp("HelpViewerState")
+        self.restoreState(state)
+        
+        self.__initHelpDb()
+        
+        self.__virusTotal = VirusTotalAPI(self)
+        self.__virusTotal.submitUrlError.connect(
+            self.__virusTotalSubmitUrlError)
+        self.__virusTotal.urlScanReport.connect(
+            self.__virusTotalUrlScanReport)
+        self.__virusTotal.fileScanReport.connect(
+            self.__virusTotalFileScanReport)
+        
+        self.__shutdownCalled = False
+        
+        self.flashCookieManager()
+        
+        if single:
+            self.SAServer = HelpSingleApplicationServer(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
+        
+        if HelpWindow._useQtHelp:
+            QTimer.singleShot(50, self.__lookForNewDocumentation)
+            if self.__searchWord is not None:
+                QTimer.singleShot(0, self.__searchForWord)
+        
+        e5App().focusChanged.connect(self.__appFocusChanged)
+        
+        QTimer.singleShot(0, syncMgr.loadSettings)
     
     def __del__(self):
         """
@@ -467,8 +481,7 @@
             """<b>New Tab</b>"""
             """<p>This opens a new help window tab.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.newTabAct.triggered.connect(self.newTab)
+        self.newTabAct.triggered.connect(self.newTab)
         self.__actions.append(self.newTabAct)
         
         self.newAct = E5Action(
@@ -482,8 +495,7 @@
             """<b>New Window</b>"""
             """<p>This opens a new help browser window.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.newAct.triggered.connect(self.newWindow)
+        self.newAct.triggered.connect(self.newWindow)
         self.__actions.append(self.newAct)
         
         self.openAct = E5Action(
@@ -498,8 +510,7 @@
             """<p>This opens a new help file for display."""
             """ It pops up a file selection dialog.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.openAct.triggered.connect(self.__openFile)
+        self.openAct.triggered.connect(self.__openFile)
         self.__actions.append(self.openAct)
         
         self.openTabAct = E5Action(
@@ -515,8 +526,7 @@
             """<p>This opens a new help file for display in a new tab."""
             """ It pops up a file selection dialog.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.openTabAct.triggered.connect(self.__openFileNewTab)
+        self.openTabAct.triggered.connect(self.__openFileNewTab)
         self.__actions.append(self.openTabAct)
         
         self.saveAsAct = E5Action(
@@ -531,8 +541,7 @@
             """<b>Save As...</b>"""
             """<p>Saves the current page to disk.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.saveAsAct.triggered.connect(self.__savePageAs)
+        self.saveAsAct.triggered.connect(self.__savePageAs)
         self.__actions.append(self.saveAsAct)
         
         self.savePageScreenAct = E5Action(
@@ -546,8 +555,7 @@
             """<b>Save Page Screen...</b>"""
             """<p>Saves the current page as a screen shot.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.savePageScreenAct.triggered.connect(self.__savePageScreen)
+        self.savePageScreenAct.triggered.connect(self.__savePageScreen)
         self.__actions.append(self.savePageScreenAct)
         
         self.saveVisiblePageScreenAct = E5Action(
@@ -563,9 +571,8 @@
             """<p>Saves the visible part of the current page as a"""
             """ screen shot.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.saveVisiblePageScreenAct.triggered.connect(
-                self.__saveVisiblePageScreen)
+        self.saveVisiblePageScreenAct.triggered.connect(
+            self.__saveVisiblePageScreen)
         self.__actions.append(self.saveVisiblePageScreenAct)
         
         bookmarksManager = self.bookmarksManager()
@@ -579,9 +586,8 @@
             """<b>Import Bookmarks</b>"""
             """<p>Import bookmarks from other browsers.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.importBookmarksAct.triggered.connect(
-                bookmarksManager.importBookmarks)
+        self.importBookmarksAct.triggered.connect(
+            bookmarksManager.importBookmarks)
         self.__actions.append(self.importBookmarksAct)
         
         self.exportBookmarksAct = E5Action(
@@ -594,9 +600,8 @@
             """<b>Export Bookmarks</b>"""
             """<p>Export the bookmarks into a file.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.exportBookmarksAct.triggered.connect(
-                bookmarksManager.exportBookmarks)
+        self.exportBookmarksAct.triggered.connect(
+            bookmarksManager.exportBookmarks)
         self.__actions.append(self.exportBookmarksAct)
         
         self.printAct = E5Action(
@@ -610,8 +615,7 @@
             """<b>Print</b>"""
             """<p>Print the displayed help text.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.printAct.triggered.connect(self.tabWidget.printBrowser)
+        self.printAct.triggered.connect(self.tabWidget.printBrowser)
         self.__actions.append(self.printAct)
         
         if Globals.isLinuxPlatform():
@@ -626,9 +630,8 @@
                 """<b>Print as PDF</b>"""
                 """<p>Print the displayed help text as a PDF file.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.printPdfAct.triggered.connect(
-                    self.tabWidget.printBrowserPdf)
+            self.printPdfAct.triggered.connect(
+                self.tabWidget.printBrowserPdf)
             self.__actions.append(self.printPdfAct)
         else:
             self.printPdfAct = None
@@ -644,9 +647,8 @@
             """<b>Print Preview</b>"""
             """<p>Print preview of the displayed help text.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.printPreviewAct.triggered.connect(
-                self.tabWidget.printPreviewBrowser)
+        self.printPreviewAct.triggered.connect(
+            self.tabWidget.printPreviewBrowser)
         self.__actions.append(self.printPreviewAct)
         
         self.closeAct = E5Action(
@@ -661,8 +663,7 @@
             """<b>Close</b>"""
             """<p>Closes the current help window.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.closeAct.triggered.connect(self.tabWidget.closeBrowser)
+        self.closeAct.triggered.connect(self.tabWidget.closeBrowser)
         self.__actions.append(self.closeAct)
         
         self.closeAllAct = E5Action(
@@ -674,9 +675,8 @@
             """<b>Close All</b>"""
             """<p>Closes all help windows except the first one.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.closeAllAct.triggered.connect(
-                self.tabWidget.closeAllBrowsers)
+        self.closeAllAct.triggered.connect(
+            self.tabWidget.closeAllBrowsers)
         self.__actions.append(self.closeAllAct)
         
         self.privateBrowsingAct = E5Action(
@@ -690,9 +690,8 @@
             """<p>Enables private browsing. In this mode no history is"""
             """ recorded anymore.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.privateBrowsingAct.triggered.connect(
-                self.__privateBrowsing)
+        self.privateBrowsingAct.triggered.connect(
+            self.__privateBrowsing)
         self.privateBrowsingAct.setCheckable(True)
         self.__actions.append(self.privateBrowsingAct)
         
@@ -707,11 +706,7 @@
             """<b>Quit</b>"""
             """<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.__closeAllWindows)
+        self.exitAct.triggered.connect(self.__closeAllWindows)
         self.__actions.append(self.exitAct)
         
         self.backAct = E5Action(
@@ -727,8 +722,7 @@
             """<p>Moves one help screen backward. If none is"""
             """ available, this action is disabled.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.backAct.triggered.connect(self.__backward)
+        self.backAct.triggered.connect(self.__backward)
         self.__actions.append(self.backAct)
         
         self.forwardAct = E5Action(
@@ -745,8 +739,7 @@
             """<p>Moves one help screen forward. If none is"""
             """ available, this action is disabled.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.forwardAct.triggered.connect(self.__forward)
+        self.forwardAct.triggered.connect(self.__forward)
         self.__actions.append(self.forwardAct)
         
         self.homeAct = E5Action(
@@ -761,8 +754,7 @@
             """<b>Home</b>"""
             """<p>Moves to the initial help screen.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.homeAct.triggered.connect(self.__home)
+        self.homeAct.triggered.connect(self.__home)
         self.__actions.append(self.homeAct)
         
         self.reloadAct = E5Action(
@@ -778,8 +770,7 @@
             """<b>Reload</b>"""
             """<p>Reloads the current help screen.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.reloadAct.triggered.connect(self.__reload)
+        self.reloadAct.triggered.connect(self.__reload)
         self.__actions.append(self.reloadAct)
         
         self.stopAct = E5Action(
@@ -794,8 +785,7 @@
             """<b>Stop</b>"""
             """<p>Stops loading of the current tab.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.stopAct.triggered.connect(self.__stopLoading)
+        self.stopAct.triggered.connect(self.__stopLoading)
         self.__actions.append(self.stopAct)
         
         self.copyAct = E5Action(
@@ -809,8 +799,7 @@
             """<b>Copy</b>"""
             """<p>Copy the selected text to the clipboard.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.copyAct.triggered.connect(self.__copy)
+        self.copyAct.triggered.connect(self.__copy)
         self.__actions.append(self.copyAct)
         
         self.findAct = E5Action(
@@ -824,8 +813,7 @@
             """<b>Find</b>"""
             """<p>Find text in the current page.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.findAct.triggered.connect(self.__find)
+        self.findAct.triggered.connect(self.__find)
         self.__actions.append(self.findAct)
         
         self.findNextAct = E5Action(
@@ -840,8 +828,7 @@
             """<b>Find next</b>"""
             """<p>Find the next occurrence of text in the current page.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.findNextAct.triggered.connect(self.findDlg.findNext)
+        self.findNextAct.triggered.connect(self.findDlg.findNext)
         self.__actions.append(self.findNextAct)
         
         self.findPrevAct = E5Action(
@@ -857,8 +844,7 @@
             """<p>Find the previous occurrence of text in the current"""
             """ page.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.findPrevAct.triggered.connect(self.findDlg.findPrevious)
+        self.findPrevAct.triggered.connect(self.findDlg.findPrevious)
         self.__actions.append(self.findPrevAct)
         
         self.bookmarksManageAct = E5Action(
@@ -872,9 +858,8 @@
             """<b>Manage Bookmarks...</b>"""
             """<p>Open a dialog to manage the bookmarks.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.bookmarksManageAct.triggered.connect(
-                self.__showBookmarksDialog)
+        self.bookmarksManageAct.triggered.connect(
+            self.__showBookmarksDialog)
         self.__actions.append(self.bookmarksManageAct)
         
         self.bookmarksAddAct = E5Action(
@@ -890,8 +875,7 @@
             """<b>Add Bookmark</b>"""
             """<p>Open a dialog to add the current URL as a bookmark.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.bookmarksAddAct.triggered.connect(self.__addBookmark)
+        self.bookmarksAddAct.triggered.connect(self.__addBookmark)
         self.__actions.append(self.bookmarksAddAct)
         
         self.bookmarksAddFolderAct = E5Action(
@@ -904,9 +888,8 @@
             """<b>Add Folder...</b>"""
             """<p>Open a dialog to add a new bookmarks folder.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.bookmarksAddFolderAct.triggered.connect(
-                self.__addBookmarkFolder)
+        self.bookmarksAddFolderAct.triggered.connect(
+            self.__addBookmarkFolder)
         self.__actions.append(self.bookmarksAddFolderAct)
         
         self.bookmarksAllTabsAct = E5Action(
@@ -920,8 +903,7 @@
             """<p>Open a dialog to add a new bookmarks folder for"""
             """ all open tabs.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.bookmarksAllTabsAct.triggered.connect(self.bookmarkAll)
+        self.bookmarksAllTabsAct.triggered.connect(self.bookmarkAll)
         self.__actions.append(self.bookmarksAllTabsAct)
         
         self.whatsThisAct = E5Action(
@@ -939,8 +921,7 @@
             """ to use them. In dialogs, this feature can be accessed using"""
             """ the context help button in the titlebar.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.whatsThisAct.triggered.connect(self.__whatsThis)
+        self.whatsThisAct.triggered.connect(self.__whatsThis)
         self.__actions.append(self.whatsThisAct)
         
         self.aboutAct = E5Action(
@@ -953,8 +934,7 @@
             """<b>About</b>"""
             """<p>Display some information about this software.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.aboutAct.triggered.connect(self.__about)
+        self.aboutAct.triggered.connect(self.__about)
         self.__actions.append(self.aboutAct)
         
         self.aboutQtAct = E5Action(
@@ -967,8 +947,7 @@
             """<b>About Qt</b>"""
             """<p>Display some information about the Qt toolkit.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.aboutQtAct.triggered.connect(self.__aboutQt)
+        self.aboutQtAct.triggered.connect(self.__aboutQt)
         self.__actions.append(self.aboutQtAct)
         
         self.zoomInAct = E5Action(
@@ -983,8 +962,7 @@
             """<b>Zoom in</b>"""
             """<p>Zoom in on the text. This makes the text bigger.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.zoomInAct.triggered.connect(self.__zoomIn)
+        self.zoomInAct.triggered.connect(self.__zoomIn)
         self.__actions.append(self.zoomInAct)
         
         self.zoomOutAct = E5Action(
@@ -999,8 +977,7 @@
             """<b>Zoom out</b>"""
             """<p>Zoom out on the text. This makes the text smaller.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.zoomOutAct.triggered.connect(self.__zoomOut)
+        self.zoomOutAct.triggered.connect(self.__zoomOut)
         self.__actions.append(self.zoomOutAct)
         
         self.zoomResetAct = E5Action(
@@ -1016,8 +993,7 @@
             """<p>Reset the zoom of the text. """
             """This sets the zoom factor to 100%.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.zoomResetAct.triggered.connect(self.__zoomReset)
+        self.zoomResetAct.triggered.connect(self.__zoomReset)
         self.__actions.append(self.zoomResetAct)
         
         if hasattr(QWebSettings, 'ZoomTextOnly'):
@@ -1032,9 +1008,8 @@
                 """<b>Zoom text only</b>"""
                 """<p>Zoom text only; pictures remain constant.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.zoomTextOnlyAct.triggered[bool].connect(
-                    self.__zoomTextOnly)
+            self.zoomTextOnlyAct.triggered[bool].connect(
+                self.__zoomTextOnly)
             self.__actions.append(self.zoomTextOnlyAct)
         else:
             self.zoomTextOnlyAct = None
@@ -1050,8 +1025,7 @@
             """<b>Show page source</b>"""
             """<p>Show the page source in an editor.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.pageSourceAct.triggered.connect(self.__showPageSource)
+        self.pageSourceAct.triggered.connect(self.__showPageSource)
         self.__actions.append(self.pageSourceAct)
         self.addAction(self.pageSourceAct)
         
@@ -1061,8 +1035,7 @@
             self.tr('&Full Screen'),
             QKeySequence(self.tr('F11')), 0,
             self, 'help_view_full_scree')
-        if not self.initShortcutsOnly:
-            self.fullScreenAct.triggered.connect(self.__viewFullScreen)
+        self.fullScreenAct.triggered.connect(self.__viewFullScreen)
         self.__actions.append(self.fullScreenAct)
         self.addAction(self.fullScreenAct)
         
@@ -1071,8 +1044,7 @@
             self.tr('Show next tab'),
             QKeySequence(self.tr('Ctrl+Alt+Tab')), 0,
             self, 'help_view_next_tab')
-        if not self.initShortcutsOnly:
-            self.nextTabAct.triggered.connect(self.__nextTab)
+        self.nextTabAct.triggered.connect(self.__nextTab)
         self.__actions.append(self.nextTabAct)
         self.addAction(self.nextTabAct)
         
@@ -1081,8 +1053,7 @@
             self.tr('Show previous tab'),
             QKeySequence(self.tr('Shift+Ctrl+Alt+Tab')), 0,
             self, 'help_view_previous_tab')
-        if not self.initShortcutsOnly:
-            self.prevTabAct.triggered.connect(self.__prevTab)
+        self.prevTabAct.triggered.connect(self.__prevTab)
         self.__actions.append(self.prevTabAct)
         self.addAction(self.prevTabAct)
         
@@ -1091,8 +1062,7 @@
             self.tr('Switch between tabs'),
             QKeySequence(self.tr('Ctrl+1')), 0,
             self, 'help_switch_tabs')
-        if not self.initShortcutsOnly:
-            self.switchTabAct.triggered.connect(self.__switchTab)
+        self.switchTabAct.triggered.connect(self.__switchTab)
         self.__actions.append(self.switchTabAct)
         self.addAction(self.switchTabAct)
         
@@ -1107,8 +1077,7 @@
             """<p>Set the configuration items of the application"""
             """ with your prefered values.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.prefAct.triggered.connect(self.__showPreferences)
+        self.prefAct.triggered.connect(self.__showPreferences)
         self.__actions.append(self.prefAct)
 
         self.acceptedLanguagesAct = E5Action(
@@ -1122,9 +1091,8 @@
             """<b>Languages</b>"""
             """<p>Configure the accepted languages for web pages.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.acceptedLanguagesAct.triggered.connect(
-                self.__showAcceptedLanguages)
+        self.acceptedLanguagesAct.triggered.connect(
+            self.__showAcceptedLanguages)
         self.__actions.append(self.acceptedLanguagesAct)
         
         self.cookiesAct = E5Action(
@@ -1137,9 +1105,8 @@
             """<b>Cookies</b>"""
             """<p>Configure cookies handling.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.cookiesAct.triggered.connect(
-                self.__showCookiesConfiguration)
+        self.cookiesAct.triggered.connect(
+            self.__showCookiesConfiguration)
         self.__actions.append(self.cookiesAct)
         
         self.flashCookiesAct = E5Action(
@@ -1152,9 +1119,8 @@
             """<b>Flash Cookies</b>"""
             """<p>Show a dialog to manage the flash cookies.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.flashCookiesAct.triggered.connect(
-                self.__showFlashCookiesManagement)
+        self.flashCookiesAct.triggered.connect(
+            self.__showFlashCookiesManagement)
         self.__actions.append(self.flashCookiesAct)
         
         self.offlineStorageAct = E5Action(
@@ -1168,9 +1134,8 @@
             """<b>Offline Storage</b>"""
             """<p>Opens a dialog to configure offline storage.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.offlineStorageAct.triggered.connect(
-                self.__showOfflineStorageConfiguration)
+        self.offlineStorageAct.triggered.connect(
+            self.__showOfflineStorageConfiguration)
         self.__actions.append(self.offlineStorageAct)
         
         self.personalDataAct = E5Action(
@@ -1186,9 +1151,8 @@
             """<p>Opens a dialog to configure the personal information"""
             """ used for completing form fields.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.personalDataAct.triggered.connect(
-                self.__showPersonalInformationDialog)
+        self.personalDataAct.triggered.connect(
+            self.__showPersonalInformationDialog)
         self.__actions.append(self.personalDataAct)
         
         self.greaseMonkeyAct = E5Action(
@@ -1204,9 +1168,8 @@
             """<p>Opens a dialog to configure the available GreaseMonkey"""
             """ Scripts.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.greaseMonkeyAct.triggered.connect(
-                self.__showGreaseMonkeyConfigDialog)
+        self.greaseMonkeyAct.triggered.connect(
+            self.__showGreaseMonkeyConfigDialog)
         self.__actions.append(self.greaseMonkeyAct)
         
         self.editMessageFilterAct = E5Action(
@@ -1222,9 +1185,8 @@
             """ suppress unwanted messages been shown in an error"""
             """ window.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.editMessageFilterAct.triggered.connect(
-                E5ErrorMessage.editMessageFilters)
+        self.editMessageFilterAct.triggered.connect(
+            E5ErrorMessage.editMessageFilters)
         self.__actions.append(self.editMessageFilterAct)
 
         self.featurePermissionAct = E5Action(
@@ -1239,12 +1201,11 @@
             """<p>Opens a dialog to edit the remembered HTML5"""
             """ feature permissions.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.featurePermissionAct.triggered.connect(
-                self.__showFeaturePermissionDialog)
+        self.featurePermissionAct.triggered.connect(
+            self.__showFeaturePermissionDialog)
         self.__actions.append(self.featurePermissionAct)
 
-        if HelpWindow._useQtHelp or self.initShortcutsOnly:
+        if HelpWindow._useQtHelp:
             self.syncTocAct = E5Action(
                 self.tr('Sync with Table of Contents'),
                 UI.PixmapCache.getIcon("syncToc.png"),
@@ -1257,8 +1218,7 @@
                 """<p>Synchronizes the table of contents with current"""
                 """ page.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.syncTocAct.triggered.connect(self.__syncTOC)
+            self.syncTocAct.triggered.connect(self.__syncTOC)
             self.__actions.append(self.syncTocAct)
             
             self.showTocAct = E5Action(
@@ -1271,8 +1231,7 @@
                 """<b>Table of Contents</b>"""
                 """<p>Shows the table of contents window.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.showTocAct.triggered.connect(self.__showTocWindow)
+            self.showTocAct.triggered.connect(self.__showTocWindow)
             self.__actions.append(self.showTocAct)
             
             self.showIndexAct = E5Action(
@@ -1285,8 +1244,7 @@
                 """<b>Index</b>"""
                 """<p>Shows the index window.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.showIndexAct.triggered.connect(self.__showIndexWindow)
+            self.showIndexAct.triggered.connect(self.__showIndexWindow)
             self.__actions.append(self.showIndexAct)
             
             self.showSearchAct = E5Action(
@@ -1299,9 +1257,8 @@
                 """<b>Search</b>"""
                 """<p>Shows the search window.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.showSearchAct.triggered.connect(
-                    self.__showSearchWindow)
+            self.showSearchAct.triggered.connect(
+                self.__showSearchWindow)
             self.__actions.append(self.showSearchAct)
             
             self.manageQtHelpDocsAct = E5Action(
@@ -1315,9 +1272,8 @@
                 """<p>Shows a dialog to manage the QtHelp documentation"""
                 """ set.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.manageQtHelpDocsAct.triggered.connect(
-                    self.__manageQtHelpDocumentation)
+            self.manageQtHelpDocsAct.triggered.connect(
+                self.__manageQtHelpDocumentation)
             self.__actions.append(self.manageQtHelpDocsAct)
             
             self.manageQtHelpFiltersAct = E5Action(
@@ -1330,9 +1286,8 @@
                 """<b>Manage QtHelp Filters</b>"""
                 """<p>Shows a dialog to manage the QtHelp filters.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.manageQtHelpFiltersAct.triggered.connect(
-                    self.__manageQtHelpFilters)
+            self.manageQtHelpFiltersAct.triggered.connect(
+                self.__manageQtHelpFilters)
             self.__actions.append(self.manageQtHelpFiltersAct)
             
             self.reindexDocumentationAct = E5Action(
@@ -1345,9 +1300,8 @@
                 """<b>Reindex Documentation</b>"""
                 """<p>Reindexes the documentation set.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.reindexDocumentationAct.triggered.connect(
-                    self.__searchEngine.reindexDocumentation)
+            self.reindexDocumentationAct.triggered.connect(
+                self.__searchEngine.reindexDocumentation)
             self.__actions.append(self.reindexDocumentationAct)
         
         self.clearPrivateDataAct = E5Action(
@@ -1363,9 +1317,8 @@
             """<p>Clears the private data like browsing history, search"""
             """ history or the favicons database.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.clearPrivateDataAct.triggered.connect(
-                self.__clearPrivateData)
+        self.clearPrivateDataAct.triggered.connect(
+            self.__clearPrivateData)
         self.__actions.append(self.clearPrivateDataAct)
         
         self.clearIconsAct = E5Action(
@@ -1380,8 +1333,7 @@
             """<p>Clears the database of favicons of previously visited"""
             """ URLs.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.clearIconsAct.triggered.connect(self.__clearIconsDatabase)
+        self.clearIconsAct.triggered.connect(self.__clearIconsDatabase)
         self.__actions.append(self.clearIconsAct)
         
         self.searchEnginesAct = E5Action(
@@ -1396,9 +1348,8 @@
             """<p>Opens a dialog to configure the available search"""
             """ engines.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.searchEnginesAct.triggered.connect(
-                self.__showEnginesConfigurationDialog)
+        self.searchEnginesAct.triggered.connect(
+            self.__showEnginesConfigurationDialog)
         self.__actions.append(self.searchEnginesAct)
         
         self.passwordsAct = E5Action(
@@ -1413,8 +1364,7 @@
             """<b>Manage Saved Passwords...</b>"""
             """<p>Opens a dialog to manage the saved passwords.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.passwordsAct.triggered.connect(self.__showPasswordsDialog)
+        self.passwordsAct.triggered.connect(self.__showPasswordsDialog)
         self.__actions.append(self.passwordsAct)
         
         self.adblockAct = E5Action(
@@ -1430,8 +1380,7 @@
             """<p>Opens a dialog to configure AdBlock subscriptions and"""
             """ rules.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.adblockAct.triggered.connect(self.__showAdBlockDialog)
+        self.adblockAct.triggered.connect(self.__showAdBlockDialog)
         self.__actions.append(self.adblockAct)
         
         self.flashblockAct = E5Action(
@@ -1447,9 +1396,8 @@
             """<p>Opens a dialog to configure the ClickToFlash"""
             """ whitelist.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.flashblockAct.triggered.connect(
-                self.__showClickToFlashDialog)
+        self.flashblockAct.triggered.connect(
+            self.__showClickToFlashDialog)
         self.__actions.append(self.flashblockAct)
         
         if SSL_AVAILABLE:
@@ -1466,9 +1414,8 @@
                 """<p>Opens a dialog to manage the saved SSL"""
                 """ certificates.</p>"""
             ))
-            if not self.initShortcutsOnly:
-                self.certificatesAct.triggered.connect(
-                    self.__showCertificatesDialog)
+            self.certificatesAct.triggered.connect(
+                self.__showCertificatesDialog)
             self.__actions.append(self.certificatesAct)
         
         self.toolsMonitorAct = E5Action(
@@ -1482,9 +1429,8 @@
             """<b>Network Monitor...</b>"""
             """<p>Shows the network monitor dialog.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.toolsMonitorAct.triggered.connect(
-                self.__showNetworkMonitor)
+        self.toolsMonitorAct.triggered.connect(
+            self.__showNetworkMonitor)
         self.__actions.append(self.toolsMonitorAct)
         
         self.showDownloadManagerAct = E5Action(
@@ -1497,9 +1443,8 @@
             """<b>Downloads</b>"""
             """<p>Shows the downloads window.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.showDownloadManagerAct.triggered.connect(
-                self.__showDownloadsWindow)
+        self.showDownloadManagerAct.triggered.connect(
+            self.__showDownloadsWindow)
         self.__actions.append(self.showDownloadManagerAct)
         
         self.feedsManagerAct = E5Action(
@@ -1516,8 +1461,7 @@
             """ It can be used to mange the feeds and to show their"""
             """ contents.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.feedsManagerAct.triggered.connect(self.__showFeedsManager)
+        self.feedsManagerAct.triggered.connect(self.__showFeedsManager)
         self.__actions.append(self.feedsManagerAct)
         
         self.siteInfoAct = E5Action(
@@ -1533,8 +1477,7 @@
             """<p>Opens a dialog showing some information about the current"""
             """ site.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.siteInfoAct.triggered.connect(self.__showSiteinfoDialog)
+        self.siteInfoAct.triggered.connect(self.__showSiteinfoDialog)
         self.__actions.append(self.siteInfoAct)
         
         self.userAgentManagerAct = E5Action(
@@ -1547,9 +1490,8 @@
             """<b>Manage User Agent Settings</b>"""
             """<p>Shows a dialog to manage the User Agent settings.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.userAgentManagerAct.triggered.connect(
-                self.__showUserAgentsDialog)
+        self.userAgentManagerAct.triggered.connect(
+            self.__showUserAgentsDialog)
         self.__actions.append(self.userAgentManagerAct)
         
         self.synchronizationAct = E5Action(
@@ -1564,9 +1506,8 @@
             """<p>This shows a dialog to synchronize data via the"""
             """ network.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.synchronizationAct.triggered.connect(
-                self.__showSyncDialog)
+        self.synchronizationAct.triggered.connect(
+            self.__showSyncDialog)
         self.__actions.append(self.synchronizationAct)
         
         self.zoomValuesAct = E5Action(
@@ -1581,9 +1522,52 @@
             """<b>Manage Saved Zoom Values...</b>"""
             """<p>Opens a dialog to manage the saved zoom values.</p>"""
         ))
-        if not self.initShortcutsOnly:
-            self.zoomValuesAct.triggered.connect(self.__showZoomValuesDialog)
+        self.zoomValuesAct.triggered.connect(self.__showZoomValuesDialog)
         self.__actions.append(self.zoomValuesAct)
+
+        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.exportShortcutsAct = E5Action(
+            self.tr('Export Keyboard Shortcuts'),
+            UI.PixmapCache.getIcon("exportShortcuts.png"),
+            self.tr('&Export Keyboard Shortcuts...'),
+            0, 0, self, 'export_keyboard_shortcuts')
+        self.exportShortcutsAct.setStatusTip(self.tr(
+            'Export the keyboard shortcuts'))
+        self.exportShortcutsAct.setWhatsThis(self.tr(
+            """<b>Export Keyboard Shortcuts</b>"""
+            """<p>Export the keyboard shortcuts of the application.</p>"""
+        ))
+        self.exportShortcutsAct.triggered.connect(self.__exportShortcuts)
+        self.__actions.append(self.exportShortcutsAct)
+
+        self.importShortcutsAct = E5Action(
+            self.tr('Import Keyboard Shortcuts'),
+            UI.PixmapCache.getIcon("importShortcuts.png"),
+            self.tr('&Import Keyboard Shortcuts...'),
+            0, 0, self, 'import_keyboard_shortcuts')
+        self.importShortcutsAct.setStatusTip(self.tr(
+            'Import the keyboard shortcuts'))
+        self.importShortcutsAct.setWhatsThis(self.tr(
+            """<b>Import Keyboard Shortcuts</b>"""
+            """<p>Import the keyboard shortcuts of the application.</p>"""
+        ))
+        self.importShortcutsAct.triggered.connect(self.__importShortcuts)
+        self.__actions.append(self.importShortcutsAct)
         
         self.backAct.setEnabled(False)
         self.forwardAct.setEnabled(False)
@@ -1703,6 +1687,11 @@
         menu = mb.addMenu(self.tr('&Settings'))
         menu.setTearOffEnabled(True)
         menu.addAction(self.prefAct)
+        menu.addSeparator()
+        menu.addAction(self.shortcutsAct)
+        menu.addAction(self.exportShortcutsAct)
+        menu.addAction(self.importShortcutsAct)
+        menu.addSeparator()
         menu.addAction(self.acceptedLanguagesAct)
         menu.addAction(self.cookiesAct)
         menu.addAction(self.flashCookiesAct)
@@ -1837,6 +1826,7 @@
         settingstb.setObjectName("SettingsToolBar")
         settingstb.setIconSize(UI.Config.ToolBarIconSize)
         settingstb.addAction(self.prefAct)
+        settingstb.addAction(self.shortcutsAct)
         settingstb.addAction(self.acceptedLanguagesAct)
         settingstb.addAction(self.cookiesAct)
         settingstb.addAction(self.flashCookiesAct)
@@ -2011,7 +2001,7 @@
             linkName = link.toString()
         else:
             linkName = link
-        h = HelpWindow(linkName, ".", self.parent(), "qbrowser", self.fromEric)
+        h = HelpWindow(linkName, ".", self.parent(), "qbrowser")
         h.show()
     
     def __openFile(self):
@@ -2298,7 +2288,7 @@
         
         try:
             browserIndex = HelpWindow.helpwindows.index(self)
-            if not self.fromEric and len(HelpWindow.helpwindows):
+            if len(HelpWindow.helpwindows):
                 if browserIndex == 0:
                     if len(HelpWindow.helpwindows) > 1:
                         # first window will be deleted
@@ -2311,13 +2301,12 @@
                     else:
                         QDesktopServices.unsetUrlHandler("http")
                         QDesktopServices.unsetUrlHandler("https")
-            if self.fromEric or len(HelpWindow.helpwindows) > 0:
+            if len(HelpWindow.helpwindows) > 0:
                 del HelpWindow.helpwindows[browserIndex]
         except ValueError:
             pass
         
-        if not self.fromEric:
-            Preferences.syncPreferences()
+        Preferences.syncPreferences()
         
         self.__shutdownCalled = True
         return True
@@ -2510,7 +2499,7 @@
         """
         from Preferences.ConfigurationDialog import ConfigurationDialog
         dlg = ConfigurationDialog(
-            self, 'Configuration', True, fromEric=self.fromEric,
+            self, 'Configuration', True, fromEric=False,
             displayMode=ConfigurationDialog.HelpBrowserMode)
         dlg.preferencesChanged.connect(self.preferencesChanged)
         dlg.masterPasswordChanged.connect(
@@ -2532,9 +2521,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.__initWebSettings()
         
@@ -2570,7 +2558,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)
@@ -2919,10 +2907,11 @@
         """
         Private slot to remove non-existing documentation from the help engine.
         """
-        for namespace in self.__helpEngine.registeredDocumentations():
-            docFile = self.__helpEngine.documentationFileName(namespace)
-            if not os.path.exists(docFile):
-                self.__helpEngine.unregisterDocumentation(namespace)
+        if HelpWindow._useQtHelp:
+            for namespace in self.__helpEngine.registeredDocumentations():
+                docFile = self.__helpEngine.documentationFileName(namespace)
+                if not os.path.exists(docFile):
+                    self.__helpEngine.unregisterDocumentation(namespace)
         
     def __lookForNewDocumentation(self):
         """
@@ -3918,22 +3907,18 @@
         @param heading heading of the notification (string)
         @param text text of the notification (string)
         """
-        if cls._fromEric:
-            e5App().getObject("UserInterface").showNotification(
-                icon, heading, text)
-        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)
-                cls._notification.setTimeout(
-                    Preferences.getUI("NotificationTimeout"))
-                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)
+            cls._notification.setTimeout(
+                Preferences.getUI("NotificationTimeout"))
+            cls._notification.move(
+                Preferences.getUI("NotificationPosition"))
+            cls._notification.show()
     
     @classmethod
     def notificationsEnabled(cls):
@@ -3942,7 +3927,96 @@
         
         @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")
+    
+    ###############################################################
+    ## Methods below implement single application related functions
+    ###############################################################
+    
+    @pyqtSlot(str)
+    def __saLoadUrl(self, urlStr):
+        """
+        Private slot to load an URL received via the single application
+        protocol.
+        
+        @param urlStr URL to be loaded
+        @type str
+        """
+        url = QUrl.fromUserInput(urlStr)
+        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.
+        
+        @param word word to be searched for
+        @type str
+        """
+        if HelpWindow._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()
+    
+    def __exportShortcuts(self):
+        """
+        Private slot to export the keyboard shortcuts.
+        """
+        fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
+            None,
+            self.tr("Export Keyboard Shortcuts"),
+            "",
+            self.tr("Keyboard shortcut file (*.e4k)"),
+            "",
+            E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
+        
+        if not fn:
+            return
+        
+        ext = QFileInfo(fn).suffix()
+        if not ext:
+            ex = selectedFilter.split("(*")[1].split(")")[0]
+            if ex:
+                fn += ex
+        
+        from Preferences import Shortcuts
+        Shortcuts.exportShortcuts(fn, helpViewer=self)
+
+    def __importShortcuts(self):
+        """
+        Private slot to import the keyboard shortcuts.
+        """
+        fn = E5FileDialog.getOpenFileName(
+            None,
+            self.tr("Import Keyboard Shortcuts"),
+            "",
+            self.tr("Keyboard shortcut file (*.e4k)"))
+        
+        if fn:
+            from Preferences import Shortcuts
+            Shortcuts.importShortcuts(fn, helpViewer=self)
--- a/Helpviewer/QtHelpDocumentationDialog.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/Helpviewer/QtHelpDocumentationDialog.py	Sat Dec 15 16:21:38 2018 +0100
@@ -50,8 +50,10 @@
                 e5App().getObject("PluginManager").getPluginQtHelpFiles()
         except KeyError:
             from PluginManager.PluginManager import PluginManager
-            self.__pluginHelpDocuments = \
-                PluginManager(self).getPluginQtHelpFiles()
+            pluginManager = PluginManager(self, doLoadPlugins=False)
+            pluginManager.loadDocumentationSetPlugins()
+            pluginManager.activatePlugins()
+            self.__pluginHelpDocuments = pluginManager.getPluginQtHelpFiles()
         self.addPluginButton.setEnabled(bool(self.__pluginHelpDocuments))
     
     @pyqtSlot()
--- a/Preferences/ConfigurationDialog.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/Preferences/ConfigurationDialog.py	Sat Dec 15 16:21:38 2018 +0100
@@ -24,7 +24,7 @@
 from E5Gui import E5MessageBox
 from E5Gui.E5MainWindow import E5MainWindow
 
-from Globals import isMacPlatform, qVersionTuple
+from Globals import isMacPlatform, qVersionTuple, getWebBrowserSupport
 
 import Preferences
 
@@ -83,7 +83,7 @@
     WebBrowserMode = 4
     
     def __init__(self, parent=None, fromEric=True, displayMode=DefaultMode,
-                 expandedEntries=None, webEngine=False):
+                 expandedEntries=None):
         """
         Constructor
         
@@ -96,7 +96,6 @@
         @exception RuntimeError raised to indicate an invalid dialog mode
         @keyparam expandedEntries list of entries to be shown expanded
             (list of strings)
-        @keyparam webEngine flag indicating QtWebEngine is used (bool)
         """
         assert displayMode in (
             ConfigurationWidget.DefaultMode,
@@ -109,7 +108,7 @@
         super(ConfigurationWidget, self).__init__(parent)
         self.fromEric = fromEric
         self.displayMode = displayMode
-        self.__webEngine = webEngine
+        self.__webEngine = getWebBrowserSupport() == "QtWebEngine"
         expandedEntries = [] if expandedEntries is None else expandedEntries[:]
         
         self.__setupUi()
@@ -339,7 +338,7 @@
                 [self.tr("Viewmanager"), "preferences-viewmanager.png",
                  "ViewmanagerPage", "0interfacePage", None],
             }
-            if webEngine:
+            if self.__webEngine:
                 self.configItems.update({
                     "0webBrowserPage":
                     [self.tr("Web Browser"), "ericWeb.png",
@@ -972,7 +971,7 @@
     
     def __init__(self, parent=None, name=None, modal=False,
                  fromEric=True, displayMode=ConfigurationWidget.DefaultMode,
-                 expandedEntries=None, webEngine=False):
+                 expandedEntries=None):
         """
         Constructor
         
@@ -986,7 +985,6 @@
              WebBrowserMode)
         @keyparam expandedEntries list of entries to be shown expanded
             (list of strings)
-        @keyparam webEngine flag indicating QtWebEngine is used (bool)
         """
         super(ConfigurationDialog, self).__init__(parent)
         if name:
@@ -1000,8 +998,7 @@
         
         self.cw = ConfigurationWidget(self, fromEric=fromEric,
                                       displayMode=displayMode,
-                                      expandedEntries=expandedEntries,
-                                      webEngine=webEngine)
+                                      expandedEntries=expandedEntries)
         size = self.cw.size()
         self.layout.addWidget(self.cw)
         self.resize(size)
@@ -1069,17 +1066,15 @@
     """
     Main window class for the standalone dialog.
     """
-    def __init__(self, parent=None, webEngine=False):
+    def __init__(self, parent=None):
         """
         Constructor
         
         @param parent reference to the parent widget (QWidget)
-        @keyparam webEngine flag indicating QtWebEngine is used (bool)
         """
         super(ConfigurationWindow, self).__init__(parent)
         
-        self.cw = ConfigurationWidget(self, fromEric=False,
-                                      webEngine=webEngine)
+        self.cw = ConfigurationWidget(self, fromEric=False)
         size = self.cw.size()
         self.setCentralWidget(self.cw)
         self.resize(size)
--- a/Preferences/ConfigurationPages/HelpViewersPage.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/Preferences/ConfigurationPages/HelpViewersPage.py	Sat Dec 15 16:21:38 2018 +0100
@@ -16,15 +16,7 @@
 except ImportError:
     WEBKIT_AVAILABLE = False
 
-from Globals import qVersionTuple
-if qVersionTuple() < (5, 6, 0):
-    WEBENGINE_AVAILABLE = False
-else:
-    try:
-        from PyQt5 import QtWebEngineWidgets    # __IGNORE_WARNING__
-        WEBENGINE_AVAILABLE = True
-    except ImportError:
-        WEBENGINE_AVAILABLE = False
+from Globals import getWebBrowserSupport
 
 from E5Gui.E5PathPicker import E5PathPickerModes
 
@@ -55,14 +47,13 @@
         self.helpViewerGroup.addButton(self.customViewerButton)
         
         # set initial values
-        if WEBENGINE_AVAILABLE:
+        webBrowserVariant = getWebBrowserSupport()
+        if webBrowserVariant == "QtWebEngine":
             hvId = Preferences.getWebBrowser("HelpViewerType")
-        else:
+        elif webBrowserVariant == "QtWebKit":
             hvId = Preferences.getHelp("HelpViewerType")
-        if not WEBENGINE_AVAILABLE and not WEBKIT_AVAILABLE:
-            if hvId == 1:
-                hvId = Preferences.Prefs.webBrowserDefaultsDefaults[
-                    "HelpViewerType"]
+        else:
+            hvId = 3
             self.helpBrowserButton.setEnabled(False)
         
         if hvId == 1:
--- a/Preferences/Shortcuts.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/Preferences/Shortcuts.py	Sat Dec 15 16:21:38 2018 +0100
@@ -182,15 +182,6 @@
                 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
     
     else:
         helpViewerCategory = helpViewer.getActionsCategory()
@@ -361,14 +352,6 @@
             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()
--- a/Preferences/ShortcutsDialog.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/Preferences/ShortcutsDialog.py	Sat Dec 15 16:21:38 2018 +0100
@@ -191,16 +191,6 @@
                         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
         
         else:
             self.helpViewerItem = self.__generateCategoryItem(
@@ -447,14 +437,6 @@
                 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()
         
         else:
--- a/Tools/TrayStarter.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/Tools/TrayStarter.py	Sat Dec 15 16:21:38 2018 +0100
@@ -32,7 +32,7 @@
     """
     Class implementing a starter for the system tray.
     """
-    def __init__(self, usePyQt4, settingsDir, webEngine=False):
+    def __init__(self, usePyQt4, settingsDir):
         """
         Constructor
         
@@ -40,8 +40,6 @@
         @type bool
         @param settingsDir directory to be used for the settings files
         @type str
-        @keyparam webEngine flag indicating QtWebEngine is used
-        @type bool
         """
         super(TrayStarter, self).__init__(
             UI.PixmapCache.getIcon(
@@ -49,7 +47,6 @@
         
         self.usePyQt4 = usePyQt4
         self.settingsDir = settingsDir
-        self.__webEngine = webEngine
         
         self.maxMenuFilePathLen = 75
         
@@ -317,9 +314,10 @@
         """
         Private slot to start the eric6 web browser.
         """
-        if self.__webEngine:
+        variant = Globals.getWebBrowserSupport()
+        if variant == "QtWebEngine":
             self.__startProc("eric6_browser.py")
-        else:
+        elif variant == "QtWebKit":
             self.__startProc("eric6_webbrowser.py")
 
     def __startUIPreviewer(self):
@@ -536,12 +534,14 @@
             .format(sip_version_str)
         versionText += """<tr><td><b>QScintilla</b></td><td>{0}</td></tr>"""\
             .format(QSCINTILLA_VERSION_STR)
-        if self.__webEngine:
+        try:
             from WebBrowser.Tools import WebBrowserTools
             chromeVersion = WebBrowserTools.getWebEngineVersions()[0]
             versionText += \
                 """<tr><td><b>WebEngine</b></td><td>{0}</td></tr>"""\
                 .format(chromeVersion)
+        except ImportError:
+            pass
         try:
             from PyQt5.QtWebKit import qWebKitVersion
             versionText += """<tr><td><b>WebKit</b></td><td>{0}</td></tr>"""\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tools/webBrowserSupport.py	Sat Dec 15 16:21:38 2018 +0100
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Script to determine the supported web browser variant.
+
+It looks for QtWebEngine first and the old QtWebKit thereafter. It reports the
+variant found or the string 'None' if both are absent.
+"""
+
+from __future__ import unicode_literals
+
+import sys
+
+variant = "None"
+
+try:
+    from PyQt5 import QtWebEngineWidgets    # __IGNORE_WARNING__
+    variant = "QtWebEngine"
+except ImportError:
+    if sys.argv[-1].startswith("4."):
+        try:
+            from PyQt4 import QtWebKit      # __IGNORE_WARNING__
+            variant = "QtWebKit"
+        except ImportError:
+            pass
+    else:
+        try:
+            from PyQt5 import QtWebKit      # __IGNORE_WARNING__
+            variant = "QtWebKit"
+        except ImportError:
+            pass
+
+print(variant)      # __IGNORE_WARNING_M801__
+
+sys.exit(0)
--- a/UI/UserInterface.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/UI/UserInterface.py	Sat Dec 15 16:21:38 2018 +0100
@@ -28,21 +28,6 @@
 from PyQt5.QtNetwork import QNetworkProxyFactory, QNetworkAccessManager, \
     QNetworkRequest, QNetworkReply
 
-from Globals import qVersionTuple
-try:
-    from PyQt5 import QtWebKit      # __IGNORE_WARNING__
-    WEBKIT_AVAILABLE = True
-except ImportError:
-    WEBKIT_AVAILABLE = False
-if qVersionTuple() < (5, 6, 0):
-    WEBENGINE_AVAILABLE = False
-else:
-    try:
-        from PyQt5 import QtWebEngineWidgets    # __IGNORE_WARNING__
-        WEBENGINE_AVAILABLE = True
-    except ImportError:
-        WEBENGINE_AVAILABLE = False
-
 from .Info import Version, VersionOnly, BugAddress, Program, FeatureAddress
 from . import Config
 
@@ -72,6 +57,8 @@
 
 from eric6config import getConfig
 
+from Globals import qVersionTuple
+
 
 class Redirector(QObject):
     """
@@ -575,19 +562,9 @@
         self.toolProcs = []
         self.__initExternalToolsActions()
         
-        # create a dummy help window for shortcuts handling
-        # 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)
-        else:
-            self.dummyHelpViewer = None
-        
         # redirect handling of http and https URLs to ourselves
-        if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE:
-            QDesktopServices.setUrlHandler("http", self.handleUrl)
-            QDesktopServices.setUrlHandler("https", self.handleUrl)
+        QDesktopServices.setUrlHandler("http", self.handleUrl)
+        QDesktopServices.setUrlHandler("https", self.handleUrl)
         
         # register all relevant objects
         splash.showMessage(self.tr("Registering Objects..."))
@@ -603,8 +580,6 @@
         if self.templateViewer is not None:
             e5App().registerObject("TemplateViewer", self.templateViewer)
         e5App().registerObject("Shell", self.shell)
-        if self.dummyHelpViewer is not None:
-            e5App().registerObject("DummyHelpViewer", self.dummyHelpViewer)
         e5App().registerObject("PluginManager", self.pluginManager)
         e5App().registerObject("ToolbarManager", self.toolbarManager)
         if self.cooperation is not None:
@@ -722,9 +697,6 @@
             self.__networkManager.sslErrors.connect(self.__sslErrors)
         self.__replies = []
         
-        # attribute for the help window
-        self.helpWindow = None
-        
         # set spellchecker defaults
         from QScintilla.SpellChecker import SpellChecker
         SpellChecker.setDefaultLanguage(
@@ -1818,29 +1790,28 @@
         self.whatsThisAct.triggered.connect(self.__whatsThis)
         self.actions.append(self.whatsThisAct)
 
-        if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE:
-            self.helpviewerAct = E5Action(
-                self.tr('Helpviewer'),
-                UI.PixmapCache.getIcon("help.png"),
-                self.tr('&Helpviewer...'),
-                QKeySequence(self.tr("F1")),
-                0, self, 'helpviewer')
-            self.helpviewerAct.setStatusTip(self.tr(
-                'Open the helpviewer window'))
-            self.helpviewerAct.setWhatsThis(self.tr(
-                """<b>Helpviewer</b>"""
-                """<p>Display the eric6 web browser. This window will show"""
-                """ HTML help files and help from Qt help collections. It"""
-                """ has the capability to navigate to links, set bookmarks,"""
-                """ print the displayed help and some more features. You may"""
-                """ use it to browse the internet as well</p><p>If called"""
-                """ with a word selected, this word is search in the Qt help"""
-                """ collection.</p>"""
-            ))
-            self.helpviewerAct.triggered.connect(self.__helpViewer)
-            self.actions.append(self.helpviewerAct)
-        else:
-            self.helpviewerAct = None
+        self.helpviewerAct = E5Action(
+            self.tr('Helpviewer'),
+            UI.PixmapCache.getIcon("help.png"),
+            self.tr('&Helpviewer...'),
+            QKeySequence(self.tr("F1")),
+            0, self, 'helpviewer')
+        self.helpviewerAct.setStatusTip(self.tr(
+            'Open the helpviewer window'))
+        self.helpviewerAct.setWhatsThis(self.tr(
+            """<b>Helpviewer</b>"""
+            """<p>Display the eric6 web browser. This window will show"""
+            """ HTML help files and help from Qt help collections. It"""
+            """ has the capability to navigate to links, set bookmarks,"""
+            """ print the displayed help and some more features. You may"""
+            """ use it to browse the internet as well</p><p>If called"""
+            """ with a word selected, this word is search in the Qt help"""
+            """ collection.</p>"""
+        ))
+        self.helpviewerAct.triggered.connect(self.__helpViewer)
+        self.actions.append(self.helpviewerAct)
+##        else:
+##            self.helpviewerAct = None
         
         self.__initQtDocActions()
         self.__initPythonDocActions()
@@ -2147,22 +2118,21 @@
         self.hexEditorAct.triggered.connect(self.__openHexEditor)
         self.actions.append(self.hexEditorAct)
 
-        if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE:
-            self.webBrowserAct = E5Action(
-                self.tr('eric6 Web Browser'),
-                UI.PixmapCache.getIcon("ericWeb.png"),
-                self.tr('eric6 &Web Browser...'),
-                0, 0, self, 'web_browser')
-            self.webBrowserAct.setStatusTip(self.tr(
-                'Start the eric6 Web Browser'))
-            self.webBrowserAct.setWhatsThis(self.tr(
-                """<b>eric6 Web Browser</b>"""
-                """<p>Browse the Internet with the eric6 Web Browser.</p>"""
-            ))
-            self.webBrowserAct.triggered.connect(self.__startWebBrowser)
-            self.actions.append(self.webBrowserAct)
-        else:
-            self.webBrowserAct = None
+        self.webBrowserAct = E5Action(
+            self.tr('eric6 Web Browser'),
+            UI.PixmapCache.getIcon("ericWeb.png"),
+            self.tr('eric6 &Web Browser...'),
+            0, 0, self, 'web_browser')
+        self.webBrowserAct.setStatusTip(self.tr(
+            'Start the eric6 Web Browser'))
+        self.webBrowserAct.setWhatsThis(self.tr(
+            """<b>eric6 Web Browser</b>"""
+            """<p>Browse the Internet with the eric6 Web Browser.</p>"""
+        ))
+        self.webBrowserAct.triggered.connect(self.__startWebBrowser)
+        self.actions.append(self.webBrowserAct)
+##        else:
+##            self.webBrowserAct = None
 
         self.iconEditorAct = E5Action(
             self.tr('Icon Editor'),
@@ -3368,16 +3338,20 @@
             .format(sip_version_str)
         versionText += """<tr><td><b>QScintilla</b></td><td>{0}</td></tr>"""\
             .format(QSCINTILLA_VERSION_STR)
-        if WEBENGINE_AVAILABLE:
+        try:
             from WebBrowser.Tools import WebBrowserTools
             chromeVersion = WebBrowserTools.getWebEngineVersions()[0]
             versionText += \
                 """<tr><td><b>WebEngine</b></td><td>{0}</td></tr>"""\
                 .format(chromeVersion)
-        if WEBKIT_AVAILABLE:
+        except ImportError:
+            pass
+        try:
             from PyQt5.QtWebKit import qWebKitVersion
             versionText += """<tr><td><b>WebKit</b></td><td>{0}</td></tr>"""\
                 .format(qWebKitVersion())
+        except ImportError:
+            pass
         versionText += """<tr><td><b>{0}</b></td><td>{1}</td></tr>"""\
             .format(Program, Version)
         versionText += self.tr("""</table>""")
@@ -5236,10 +5210,7 @@
         if home.endswith(".chm"):
             self.__chmViewer(home)
         else:
-            if WEBENGINE_AVAILABLE:
-                hvType = Preferences.getWebBrowser("HelpViewerType")
-            else:
-                hvType = Preferences.getHelp("HelpViewerType")
+            hvType = Preferences.getWebBrowser("HelpViewerType")
             if hvType == 1:
                 self.launchHelpViewer(home)
             elif hvType == 2:
@@ -5300,10 +5271,7 @@
         if home.endswith(".chm"):
             self.__chmViewer(home)
         else:
-            if WEBENGINE_AVAILABLE:
-                hvType = Preferences.getWebBrowser("HelpViewerType")
-            else:
-                hvType = Preferences.getHelp("HelpViewerType")
+            hvType = Preferences.getWebBrowser("HelpViewerType")
             if hvType == 1:
                 self.launchHelpViewer(home)
             elif hvType == 2:
@@ -5369,10 +5337,7 @@
             else:
                 home = "file://" + home
         
-        if WEBENGINE_AVAILABLE:
-            hvType = Preferences.getWebBrowser("HelpViewerType")
-        else:
-            hvType = Preferences.getHelp("HelpViewerType")
+        hvType = Preferences.getWebBrowser("HelpViewerType")
         if hvType == 1:
             self.launchHelpViewer(home)
         elif hvType == 2:
@@ -5434,10 +5399,7 @@
         else:
             home = pyqt4DocDir
         
-        if WEBENGINE_AVAILABLE:
-            hvType = Preferences.getWebBrowser("HelpViewerType")
-        else:
-            hvType = Preferences.getHelp("HelpViewerType")
+        hvType = Preferences.getWebBrowser("HelpViewerType")
         if hvType == 1:
             self.launchHelpViewer(home)
         elif hvType == 2:
@@ -5501,10 +5463,7 @@
         else:
             home = pyqt5DocDir
         
-        if WEBENGINE_AVAILABLE:
-            hvType = Preferences.getWebBrowser("HelpViewerType")
-        else:
-            hvType = Preferences.getHelp("HelpViewerType")
+        hvType = Preferences.getWebBrowser("HelpViewerType")
         if hvType == 1:
             self.launchHelpViewer(home)
         elif hvType == 2:
@@ -5541,10 +5500,7 @@
             else:
                 home = "file://" + home
         
-        if WEBENGINE_AVAILABLE:
-            hvType = Preferences.getWebBrowser("HelpViewerType")
-        else:
-            hvType = Preferences.getHelp("HelpViewerType")
+        hvType = Preferences.getWebBrowser("HelpViewerType")
         if hvType == 1:
             self.launchHelpViewer(home)
         elif hvType == 2:
@@ -5610,10 +5566,7 @@
         else:
             home = pysideDocDir
         
-        if WEBENGINE_AVAILABLE:
-            hvType = Preferences.getWebBrowser("HelpViewerType")
-        else:
-            hvType = Preferences.getHelp("HelpViewerType")
+        hvType = Preferences.getWebBrowser("HelpViewerType")
         if hvType == 1:
             self.launchHelpViewer(home)
         elif hvType == 2:
@@ -5655,45 +5608,9 @@
             if not homeUrl.scheme():
                 home = QUrl.fromLocalFile(home).toString()
         
-        if WEBENGINE_AVAILABLE:
-            self.__launchExternalWebBrowser(home, searchWord=searchWord)
-        
-        elif WEBKIT_AVAILABLE:
-            # TODO: change to use external web browser in single mode
-            single = useSingle
-            if WEBKIT_AVAILABLE:
-                single = single or Preferences.getHelp("SingleHelpWindow")
-            if not single or self.helpWindow is None:
-                if WEBKIT_AVAILABLE:
-                    from Helpviewer.HelpWindow import HelpWindow
-                    browser = HelpWindow(home, '.', None, 'help viewer', True,
-                                         searchWord=searchWord)
-
-                if QApplication.desktop().width() > 400 and \
-                   QApplication.desktop().height() > 500:
-                    browser.show()
-                else:
-                    browser.showMaximized()
-                
-                if single:
-                    self.helpWindow = browser
-                    try:
-                        self.helpWindow.webBrowserWindowClosed.connect(
-                            self.__helpClosed)
-                    except AttributeError:
-                        self.helpWindow.helpClosed.connect(self.__helpClosed)
-                    self.preferencesChanged.connect(
-                        self.helpWindow.preferencesChanged)
-                    self.masterPasswordChanged.connect(
-                        self.helpWindow.masterPasswordChanged)
-            elif searchWord is not None:
-                self.helpWindow.search(searchWord)
-                self.helpWindow.raise_()
-            else:
-                self.helpWindow.newTab(home)
-                self.helpWindow.raise_()
-        
-        else:
+        launchResult = self.__launchExternalWebBrowser(
+            home, searchWord=searchWord)
+        if not launchResult:
             self.__webBrowser(home)
     
     def __launchExternalWebBrowser(self, home, searchWord=None):
@@ -5705,54 +5622,53 @@
         @type str
         @keyparam searchWord word to search for
         @type str
-        """
-        from WebBrowser.WebBrowserSingleApplication import \
-            WebBrowserSingleApplicationClient
-        
+        @return flag indicating a successful launch
+        @rtype bool
+        """
         clientArgs = []
         if searchWord:
             clientArgs.append("--search={0}".format(searchWord))
         
         if self.__webBrowserProcess is None:
-            process = QProcess()
-            args = [
+            webBrowsers = [
                 os.path.join(
                     os.path.dirname(__file__), "..", "eric6_browser.py"),
-                "--qthelp",
-                "--single",
-                "--name={0}".format(self.__webBrowserSAName)
+                # QtWebEngine based web browser
+                os.path.join(
+                    os.path.dirname(__file__), "..", "eric6_webbrowser.py"),
+                # QtWebKit based web browser
             ]
-            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 = QProcess()
+            for browser in webBrowsers:
+                args = [
+                    browser,
+                    "--quiet",
+                    "--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 False
+                
+                res = self.__connectToWebBrowser(process)
+                if res == 1:
+                    # connection unsuccessful
+                    return False
+                elif res == 0:
+                    # successful
+                    break
+            else:
+                return False
             
             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:
@@ -5760,6 +5676,50 @@
         
         if clientArgs:
             self.__webBrowserClient.processArgs(clientArgs, disconnect=False)
+        
+        return True
+    
+    def __connectToWebBrowser(self, process):
+        """
+        Private method to connect to a started web browser.
+        
+        @param process reference to the started web browser process
+        @type QProcess
+        @return error indication (1 = connection not possible, 0 = ok,
+            -1 = server exited with an error code)
+        @rtype int
+        """
+        from WebBrowser.WebBrowserSingleApplication import \
+            WebBrowserSingleApplicationClient
+        
+        webBrowserClient = WebBrowserSingleApplicationClient(
+            self.__webBrowserSAName)
+        connectCount = 30
+        while connectCount:
+            res = webBrowserClient.connect()
+            if res != 0:
+                break
+            else:
+                connectCount -= 1
+                QThread.msleep(1000)
+                QApplication.processEvents()
+            if process.state() == QProcess.NotRunning and \
+               process.exitStatus() == QProcess.NormalExit and \
+               process.exitCode() == 100:
+                # Process exited prematurely due to missing pre-requisites
+                return -1
+        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(
+                    webBrowserClient.errstr())
+            )
+            return 1
+        
+        self.__webBrowserClient = webBrowserClient
+        return 0
     
     def __webBrowserFinished(self):
         """
@@ -5776,21 +5736,6 @@
         """
         self.__webBrowserClient.processArgs(["--shutdown"], disconnect=False)
     
-    def __helpClosed(self):
-        """
-        Private slot to handle the helpClosed signal of the help window.
-        """
-        if WEBENGINE_AVAILABLE:
-            single = Preferences.getWebBrowser("SingleWebBrowserWindow")
-        elif WEBKIT_AVAILABLE:
-            single = Preferences.getHelp("SingleHelpWindow")
-        if single:
-            self.preferencesChanged.disconnect(
-                self.helpWindow.preferencesChanged)
-            self.masterPasswordChanged.disconnect(
-                self.helpWindow.masterPasswordChanged)
-            self.helpWindow = None
-    
     def __helpViewer(self):
         """
         Private slot to start an empty help viewer/web browser.
@@ -5814,23 +5759,6 @@
                 self.tr('Open Browser'),
                 self.tr('Could not start a web browser'))
 
-    def getHelpViewer(self, preview=False):
-        """
-        Public method to get a reference to the help window instance.
-        
-        @keyparam preview flag indicating to get a help window for preview
-            (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)
-            self.helpWindow.raise_()
-            return self.helpWindow
-        else:
-            return None
-    
     @pyqtSlot()
     @pyqtSlot(str)
     def showPreferences(self, pageName=None):
@@ -5843,7 +5771,6 @@
         dlg = ConfigurationDialog(
             self, 'Configuration',
             expandedEntries=self.__expandedConfigurationEntries,
-            webEngine=WEBENGINE_AVAILABLE,
         )
         dlg.preferencesChanged.connect(self.__preferencesChanged)
         dlg.masterPasswordChanged.connect(self.__masterPasswordChanged)
@@ -5953,19 +5880,21 @@
         @param oldPassword current master password (string)
         @param newPassword new master password (string)
         """
+        import Globals
+        
         self.masterPasswordChanged.emit(oldPassword, newPassword)
         Preferences.convertPasswords(oldPassword, newPassword)
-        if self.helpWindow is None:
-            if WEBENGINE_AVAILABLE:
-                from WebBrowser.Passwords.PasswordManager import \
-                    PasswordManager
-                pwManager = PasswordManager()
-                pwManager.masterPasswordChanged(oldPassword, newPassword)
-            elif WEBKIT_AVAILABLE:
-                from Helpviewer.Passwords.PasswordManager import \
-                    PasswordManager
-                pwManager = PasswordManager()
-                pwManager.masterPasswordChanged(oldPassword, newPassword)
+        variant = Globals.getWebBrowserSupport()
+        if variant == "QtWebEngine":
+            from WebBrowser.Passwords.PasswordManager import \
+                PasswordManager
+            pwManager = PasswordManager()
+            pwManager.masterPasswordChanged(oldPassword, newPassword)
+        elif variant == "QtWebKit":
+            from Helpviewer.Passwords.PasswordManager import \
+                PasswordManager
+            pwManager = PasswordManager()
+            pwManager.masterPasswordChanged(oldPassword, newPassword)
         Utilities.crypto.changeRememberedMaster(newPassword)
         
     def __reloadAPIs(self):
@@ -6644,10 +6573,6 @@
         if self.shutdownCalled:
             return True
         
-        if self.helpWindow is not None:
-            if not self.helpWindow.shutdown():
-                return False
-        
         if self.__webBrowserProcess is not None:
             self.__webBrowserShutdown()
         
--- a/WebBrowser/Tools/WebBrowserTools.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/WebBrowser/Tools/WebBrowserTools.py	Sat Dec 15 16:21:38 2018 +0100
@@ -196,8 +196,9 @@
     @return tuple containing the Chrome version and the QtWebEngine version
     @rtype tuple of str
     """
-    from WebBrowser.WebBrowserWindow import WebBrowserWindow
-    useragent = WebBrowserWindow.webProfile().defaultUserAgent
+    from PyQt5.QtWebEngineWidgets import QWebEngineProfile
+    
+    useragent = QWebEngineProfile.defaultProfile().httpUserAgent()
     match = re.search(r"""Chrome/([\d.]+)""", useragent)
     if match:
         chromeVersion = match.group(1)
--- a/WebBrowser/WebBrowserSingleApplication.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/WebBrowser/WebBrowserSingleApplication.py	Sat Dec 15 16:21:38 2018 +0100
@@ -115,8 +115,7 @@
 
 class WebBrowserSingleApplicationClient(SingleApplicationClient):
     """
-    Class implementing the single application client of the Translations
-    Previewer.
+    Class implementing the single application client of the web browser.
     """
     def __init__(self, name=""):
         """
--- a/WebBrowser/WebBrowserWindow.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/WebBrowser/WebBrowserWindow.py	Sat Dec 15 16:21:38 2018 +0100
@@ -129,15 +129,15 @@
         @type QWidget
         @param name name of this window
         @type str
-        @keyparam searchWord word to search for
+        @param searchWord word to search for
         @type str
-        @keyparam private flag indicating a private browsing window
+        @param private flag indicating a private browsing window
         @type bool
-        @keyparam qthelp flag indicating to enable the QtHelp support
+        @param qthelp flag indicating to enable the QtHelp support
         @type bool
-        @keyparam settingsDir directory to be used for the settings files
+        @param settingsDir directory to be used for the settings files
         @type str
-        @keyparam restoreSession flag indicating a restore session action
+        @param restoreSession flag indicating a restore session action
         @type bool
         @param single flag indicating to start in single application mode
         @type bool
@@ -2359,6 +2359,7 @@
         settingstb.setObjectName("SettingsToolBar")
         settingstb.setIconSize(UI.Config.ToolBarIconSize)
         settingstb.addAction(self.prefAct)
+        settingstb.addAction(self.shortcutsAct)
         settingstb.addAction(self.acceptedLanguagesAct)
         settingstb.addAction(self.cookiesAct)
         settingstb.addAction(self.flashCookiesAct)
@@ -3198,7 +3199,7 @@
         """
         from Preferences.ConfigurationDialog import ConfigurationDialog
         dlg = ConfigurationDialog(
-            self, 'Configuration', True, fromEric=self.__fromEric,
+            self, 'Configuration', True, fromEric=False,
             displayMode=ConfigurationDialog.WebBrowserMode)
         dlg.preferencesChanged.connect(self.preferencesChanged)
         dlg.masterPasswordChanged.connect(
@@ -3586,10 +3587,11 @@
         """
         Private slot to remove non-existing documentation from the help engine.
         """
-        for namespace in self.__helpEngine.registeredDocumentations():
-            docFile = self.__helpEngine.documentationFileName(namespace)
-            if not os.path.exists(docFile):
-                self.__helpEngine.unregisterDocumentation(namespace)
+        if WebBrowserWindow._useQtHelp:
+            for namespace in self.__helpEngine.registeredDocumentations():
+                docFile = self.__helpEngine.documentationFileName(namespace)
+                if not os.path.exists(docFile):
+                    self.__helpEngine.unregisterDocumentation(namespace)
         
     def __lookForNewDocumentation(self):
         """
--- a/changelog	Fri Dec 14 19:52:38 2018 +0100
+++ b/changelog	Sat Dec 15 16:21:38 2018 +0100
@@ -7,6 +7,10 @@
      if it has one defined
 - Project Resources Browser
   -- added support for some resource compiler options
+- Web Browser (old):
+  -- added single application mode
+  -- change logic inside eric to use a remote controlled web browser to show
+     help texts
 - Web Browser (NG):
   -- added single application mode
   -- change logic inside eric to use a remote controlled web browser to show
--- a/eric6.e4p	Fri Dec 14 19:52:38 2018 +0100
+++ b/eric6.e4p	Sat Dec 15 16:21:38 2018 +0100
@@ -307,6 +307,7 @@
     <Source>Helpviewer/HelpInspector.py</Source>
     <Source>Helpviewer/HelpLanguagesDialog.py</Source>
     <Source>Helpviewer/HelpSearchWidget.py</Source>
+    <Source>Helpviewer/HelpSingleApplication.py</Source>
     <Source>Helpviewer/HelpSnap.py</Source>
     <Source>Helpviewer/HelpTabBar.py</Source>
     <Source>Helpviewer/HelpTabWidget.py</Source>
@@ -1339,6 +1340,7 @@
     <Source>Tools/TrayStarter.py</Source>
     <Source>Tools/UIPreviewer.py</Source>
     <Source>Tools/__init__.py</Source>
+    <Source>Tools/webBrowserSupport.py</Source>
     <Source>UI/AuthenticationDialog.py</Source>
     <Source>UI/Browser.py</Source>
     <Source>UI/BrowserModel.py</Source>
--- a/eric6_browser.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/eric6_browser.py	Sat Dec 15 16:21:38 2018 +0100
@@ -104,8 +104,10 @@
     """
     Function to create the main widget.
     
-    @param argv list of commandline parameters (list of strings)
-    @return reference to the main widget (QWidget)
+    @param argv list of command line parameters
+    @type list of str
+    @return reference to the main widget
+    @rtype QWidget
     """
     from WebBrowser.WebBrowserWindow import WebBrowserWindow
     
--- a/eric6_configure.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/eric6_configure.py	Sat Dec 15 16:21:38 2018 +0100
@@ -37,16 +37,6 @@
                           settingsDir)
         sys.argv.remove(arg)
 
-from Globals import qVersionTuple
-if qVersionTuple() < (5, 6, 0):
-    WEBENGINE_AVAILABLE = False
-else:
-    try:
-        from PyQt5 import QtWebEngineWidgets    # __IGNORE_WARNING__
-        WEBENGINE_AVAILABLE = True
-    except ImportError:
-        WEBENGINE_AVAILABLE = False
-
 # make ThirdParty package available as a packages repository
 sys.path.insert(2, os.path.join(os.path.dirname(__file__),
                                 "ThirdParty", "Pygments"))
@@ -66,7 +56,7 @@
     @return reference to the main widget (QWidget)
     """
     from Preferences.ConfigurationDialog import ConfigurationWindow
-    w = ConfigurationWindow(webEngine=WEBENGINE_AVAILABLE)
+    w = ConfigurationWindow()
     w.show()
     w.showConfigurationPageByName("empty")
     return w
--- a/eric6_tray.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/eric6_tray.py	Sat Dec 15 16:21:38 2018 +0100
@@ -42,16 +42,6 @@
                           SettingsDir)
         sys.argv.remove(arg)
 
-from Globals import qVersionTuple
-if qVersionTuple() < (5, 6, 0):
-    WEBENGINE_AVAILABLE = False
-else:
-    try:
-        from PyQt5 import QtWebEngineWidgets    # __IGNORE_WARNING__
-        WEBENGINE_AVAILABLE = True
-    except ImportError:
-        WEBENGINE_AVAILABLE = False
-
 from Globals import AppInfo
 
 from Toolbox import Startup
@@ -65,7 +55,7 @@
     @return reference to the main widget (QWidget)
     """
     from Tools.TrayStarter import TrayStarter
-    return TrayStarter(PyQt4Option, SettingsDir, webEngine=WEBENGINE_AVAILABLE)
+    return TrayStarter(PyQt4Option, SettingsDir)
 
 
 def main():
--- a/eric6_webbrowser.py	Fri Dec 14 19:52:38 2018 +0100
+++ b/eric6_webbrowser.py	Sat Dec 15 16:21:38 2018 +0100
@@ -36,17 +36,18 @@
 try:
     from PyQt5 import QtWebKit      # __IGNORE_WARNING__
 except ImportError:
-    from PyQt5.QtCore import qVersion, QTimer
-    from PyQt5.QtWidgets import QApplication
-    from E5Gui import E5MessageBox
-    app = QApplication([])
-    QTimer.singleShot(0, lambda: E5MessageBox.critical(
-        None,
-        "eric6 Web Browser (QtWebKit based)",
-        "QtWebKit is needed to run this variant of the eric6 Web Browser."
-        " However, it seems to be missing. You are using Qt {0}, which"
-        " doesn't include this anymore.".format(qVersion())))
-    app.exec_()
+    if "--quiet" not in sys.argv:
+        from PyQt5.QtCore import qVersion, QTimer
+        from PyQt5.QtWidgets import QApplication
+        from E5Gui import E5MessageBox
+        app = QApplication([])
+        QTimer.singleShot(0, lambda: E5MessageBox.critical(
+            None,
+            "eric6 Web Browser (QtWebKit based)",
+            "QtWebKit is needed to run this variant of the eric6 Web Browser."
+            " However, it seems to be missing. You are using Qt {0}, which"
+            " doesn't include this anymore.".format(qVersion())))
+        app.exec_()
     sys.exit(100)
 
 for arg in sys.argv[:]:
@@ -73,23 +74,48 @@
 import Globals
 from Globals import AppInfo
 
+from E5Gui.E5Application import E5Application
+
 from Toolbox import Startup
 
+from Helpviewer.HelpSingleApplication import HelpSingleApplicationClient
+
 
 def createMainWidget(argv):
     """
     Function to create the main widget.
     
-    @param argv list of commandline parameters (list of strings)
-    @return reference to the main widget (QWidget)
+    @param argv list of command line parameters
+    @type list of str
+    @return reference to the main widget
+    @rtype QWidget
     """
     from Helpviewer.HelpWindow import HelpWindow
     
     searchWord = None
+    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 == "--qthelp":
+            qthelp = True
+            argv.remove(arg)
+        elif arg == "--quiet":
+            # only needed until we reach this point
+            argv.remove(arg)
+        elif arg == "--single":
+            single = True
+            argv.remove(arg)
         elif arg.startswith("--"):
             argv.remove(arg)
     
@@ -99,7 +125,8 @@
         home = ""
     
     helpWindow = HelpWindow(home, '.', None, 'help viewer',
-                            searchWord=searchWord)
+                            searchWord=searchWord, qthelp=qthelp,
+                            single=single, saname=name)
     return helpWindow
 
 
@@ -110,9 +137,12 @@
     options = [
         ("--config=configDir",
          "use the given directory as the one containing the config files"),
+        ("--qthelp", "start the browser with support for QtHelp"),
+        ("--quiet", "don't show any startup error messages"),
         ("--search=word", "search for the given word"),
         ("--settings=settingsDir",
          "use the given directory to store the settings files"),
+        ("--single", "start the browser as a single application"),
     ]
     appinfo = AppInfo.makeAppInfo(sys.argv,
                                   "eric6 Web Browser",
@@ -123,10 +153,26 @@
     if not Globals.checkBlacklistedVersions():
         sys.exit(100)
     
+    # set the library paths for plugins
+    Startup.setLibraryPaths()
+    
+    app = E5Application(sys.argv)
+    client = HelpSingleApplicationClient()
+    res = client.connect()
+    if res > 0:
+        if len(sys.argv) > 1:
+            client.processArgs(sys.argv[1:])
+        sys.exit(0)
+    elif res < 0:
+        print("eric6_webbrowser: {0}".format(client.errstr()))
+        # __IGNORE_WARNING_M801__
+        sys.exit(res)
+    
     res = Startup.simpleAppStartup(sys.argv,
                                    appinfo,
                                    createMainWidget,
-                                   installErrorHandler=True)
+                                   installErrorHandler=True,
+                                   app=app)
     sys.exit(res)
 
 if __name__ == '__main__':

eric ide

mercurial