1# -*- coding: utf-8 -*-
2
3# Copyright (c) 2002 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4#
5
6"""
7Module implementing the web browser main window.
8"""
9
10import os
11import shutil
12import sys
13import functools
14import contextlib
15
16from PyQt5.QtCore import (
17    pyqtSlot, pyqtSignal, Qt, QByteArray, QSize, QTimer, QUrl, QProcess,
18    QEvent, QFileInfo
19)
20from PyQt5.QtGui import QDesktopServices, QKeySequence, QFont, QFontMetrics
21from PyQt5.QtWidgets import (
22    QWidget, QVBoxLayout, QSizePolicy, QDockWidget, QComboBox, QLabel, QMenu,
23    QLineEdit, QApplication, QWhatsThis, QDialog, QHBoxLayout, QProgressBar,
24    QInputDialog, QAction
25)
26from PyQt5.QtWebEngineWidgets import (
27    QWebEngineSettings, QWebEnginePage, QWebEngineProfile, QWebEngineScript
28)
29try:
30    from PyQt5.QtHelp import QHelpEngine, QHelpEngineCore, QHelpSearchQuery
31    QTHELP_AVAILABLE = True
32except ImportError:
33    QTHELP_AVAILABLE = False
34
35from E5Gui.E5Action import E5Action
36from E5Gui import E5MessageBox, E5FileDialog, E5ErrorMessage
37from E5Gui.E5MainWindow import E5MainWindow
38from E5Gui.E5Application import e5App
39from E5Gui.E5ZoomWidget import E5ZoomWidget
40from E5Gui.E5OverrideCursor import E5OverrideCursor
41
42import Preferences
43from Preferences import Shortcuts
44
45import Utilities
46import Globals
47
48import UI.PixmapCache
49import UI.Config
50from UI.Info import Version
51from UI.NotificationWidget import NotificationTypes
52
53from .Tools import Scripts, WebBrowserTools, WebIconProvider
54
55from .ZoomManager import ZoomManager
56
57from .WebBrowserSingleApplication import WebBrowserSingleApplicationServer
58
59from eric6config import getConfig
60
61
62class WebBrowserWindow(E5MainWindow):
63    """
64    Class implementing the web browser main window.
65
66    @signal webBrowserWindowOpened(window) emitted after a new web browser
67        window was opened
68    @signal webBrowserWindowClosed(window) emitted after the window was
69        requested to close
70    @signal webBrowserOpened(browser) emitted after a new web browser tab was
71        created
72    @signal webBrowserClosed(browser) emitted after a web browser tab was
73        closed
74    """
75    webBrowserWindowClosed = pyqtSignal(E5MainWindow)
76    webBrowserWindowOpened = pyqtSignal(E5MainWindow)
77    webBrowserOpened = pyqtSignal(QWidget)
78    webBrowserClosed = pyqtSignal(QWidget)
79
80    BrowserWindows = []
81
82    _useQtHelp = QTHELP_AVAILABLE
83    _isPrivate = False
84
85    _webProfile = None
86    _networkManager = None
87    _cookieJar = None
88    _helpEngine = None
89    _bookmarksManager = None
90    _historyManager = None
91    _passwordManager = None
92    _adblockManager = None
93    _downloadManager = None
94    _feedsManager = None
95    _userAgentsManager = None
96    _syncManager = None
97    _speedDial = None
98    _personalInformationManager = None
99    _greaseMonkeyManager = None
100    _notification = None
101    _featurePermissionManager = None
102    _imageSearchEngine = None
103    _autoScroller = None
104    _tabManager = None
105    _sessionManager = None
106    _safeBrowsingManager = None
107    _protocolHandlerManager = None
108
109    _performingStartup = True
110    _performingShutdown = False
111    _lastActiveWindow = None
112
113    def __init__(self, home, path, parent, name,
114                 searchWord=None, private=False, qthelp=False, settingsDir="",
115                 restoreSession=False, single=False, saname=""):
116        """
117        Constructor
118
119        @param home the URL to be shown
120        @type str
121        @param path the path of the working dir (usually '.')
122        @type str
123        @param parent parent widget of this window
124        @type QWidget
125        @param name name of this window
126        @type str
127        @param searchWord word to search for
128        @type str
129        @param private flag indicating a private browsing window
130        @type bool
131        @param qthelp flag indicating to enable the QtHelp support
132        @type bool
133        @param settingsDir directory to be used for the settings files
134        @type str
135        @param restoreSession flag indicating a restore session action
136        @type bool
137        @param single flag indicating to start in single application mode
138        @type bool
139        @param saname name to be used for the single application server
140        @type str
141        """
142        self.__hideNavigationTimer = None
143
144        super().__init__(parent)
145        self.setObjectName(name)
146        if private:
147            self.setWindowTitle(self.tr("eric Web Browser (Private Mode)"))
148        else:
149            self.setWindowTitle(self.tr("eric Web Browser"))
150
151        self.__settingsDir = settingsDir
152        self.setWindowIcon(UI.PixmapCache.getIcon("ericWeb"))
153
154        self.__mHistory = []
155        self.__lastConfigurationPageName = ""
156
157        WebBrowserWindow._isPrivate = private
158
159        self.__shortcutsDialog = None
160
161        self.__eventMouseButtons = Qt.MouseButton.NoButton
162        self.__eventKeyboardModifiers = Qt.KeyboardModifier.NoModifier
163
164        WebBrowserWindow.setUseQtHelp(qthelp or bool(searchWord))
165
166        self.webProfile(private)
167        self.networkManager()
168
169        self.__htmlFullScreen = False
170        self.__windowStates = Qt.WindowState.WindowNoState
171        self.__isClosing = False
172
173        from .SearchWidget import SearchWidget
174        from .QtHelp.HelpTocWidget import HelpTocWidget
175        from .QtHelp.HelpIndexWidget import HelpIndexWidget
176        from .QtHelp.HelpSearchWidget import HelpSearchWidget
177        from .WebBrowserView import WebBrowserView
178        from .WebBrowserTabWidget import WebBrowserTabWidget
179        from .AdBlock.AdBlockIcon import AdBlockIcon
180        from .StatusBar.JavaScriptIcon import JavaScriptIcon
181        from .StatusBar.ImagesIcon import ImagesIcon
182        from .VirusTotal.VirusTotalApi import VirusTotalAPI
183        from .Navigation.NavigationBar import NavigationBar
184        from .Navigation.NavigationContainer import NavigationContainer
185        from .Bookmarks.BookmarksToolBar import BookmarksToolBar
186
187        self.setStyle(Preferences.getUI("Style"),
188                      Preferences.getUI("StyleSheet"))
189
190        # initialize some SSL stuff
191        from E5Network.E5SslUtilities import initSSL
192        initSSL()
193
194        if WebBrowserWindow._useQtHelp:
195            self.__helpEngine = QHelpEngine(
196                WebBrowserWindow.getQtHelpCollectionFileName(),
197                self)
198            self.__removeOldDocumentation()
199            self.__helpEngine.warning.connect(self.__warning)
200        else:
201            self.__helpEngine = None
202        self.__helpInstaller = None
203
204        self.__zoomWidget = E5ZoomWidget(
205            UI.PixmapCache.getPixmap("zoomOut"),
206            UI.PixmapCache.getPixmap("zoomIn"),
207            UI.PixmapCache.getPixmap("zoomReset"), self)
208        self.statusBar().addPermanentWidget(self.__zoomWidget)
209        self.__zoomWidget.setMapping(
210            WebBrowserView.ZoomLevels, WebBrowserView.ZoomLevelDefault)
211        self.__zoomWidget.valueChanged.connect(self.__zoomValueChanged)
212
213        self.__tabWidget = WebBrowserTabWidget(self)
214        self.__tabWidget.currentChanged[int].connect(self.__currentChanged)
215        self.__tabWidget.titleChanged.connect(self.__titleChanged)
216        self.__tabWidget.showMessage.connect(self.statusBar().showMessage)
217        self.__tabWidget.browserZoomValueChanged.connect(
218            self.__zoomWidget.setValue)
219        self.__tabWidget.browserClosed.connect(self.webBrowserClosed)
220        self.__tabWidget.browserOpened.connect(self.webBrowserOpened)
221
222        self.__searchWidget = SearchWidget(self, self)
223
224        self.__setIconDatabasePath()
225
226        bookmarksModel = self.bookmarksManager().bookmarksModel()
227        self.__bookmarksToolBar = BookmarksToolBar(self, bookmarksModel,
228                                                   self)
229        self.__bookmarksToolBar.setIconSize(UI.Config.ToolBarIconSize)
230        self.__bookmarksToolBar.openUrl.connect(self.openUrl)
231        self.__bookmarksToolBar.newTab.connect(self.openUrlNewTab)
232        self.__bookmarksToolBar.newWindow.connect(self.openUrlNewWindow)
233
234        self.__navigationBar = NavigationBar(self)
235
236        self.__navigationContainer = NavigationContainer(self)
237        self.__navigationContainer.addWidget(self.__navigationBar)
238        self.__navigationContainer.addWidget(self.__bookmarksToolBar)
239
240        centralWidget = QWidget()
241        layout = QVBoxLayout()
242        layout.setContentsMargins(1, 1, 1, 1)
243        layout.setSpacing(0)
244        layout.addWidget(self.__navigationContainer)
245        layout.addWidget(self.__tabWidget)
246        layout.addWidget(self.__searchWidget)
247        self.__tabWidget.setSizePolicy(
248            QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding)
249        centralWidget.setLayout(layout)
250        self.setCentralWidget(centralWidget)
251        self.__searchWidget.hide()
252
253        if WebBrowserWindow._useQtHelp:
254            # setup the TOC widget
255            self.__tocWindow = HelpTocWidget(self.__helpEngine)
256            self.__tocDock = QDockWidget(self.tr("Contents"), self)
257            self.__tocDock.setObjectName("TocWindow")
258            self.__tocDock.setWidget(self.__tocWindow)
259            self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea,
260                               self.__tocDock)
261
262            # setup the index widget
263            self.__indexWindow = HelpIndexWidget(self.__helpEngine)
264            self.__indexDock = QDockWidget(self.tr("Index"), self)
265            self.__indexDock.setObjectName("IndexWindow")
266            self.__indexDock.setWidget(self.__indexWindow)
267            self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea,
268                               self.__indexDock)
269
270            # setup the search widget
271            self.__searchWord = searchWord
272            self.__indexing = False
273            self.__indexingProgress = None
274            self.__searchEngine = self.__helpEngine.searchEngine()
275            self.__searchEngine.indexingStarted.connect(
276                self.__indexingStarted)
277            self.__searchEngine.indexingFinished.connect(
278                self.__indexingFinished)
279            self.__searchWindow = HelpSearchWidget(self.__searchEngine)
280            self.__searchDock = QDockWidget(self.tr("Search"), self)
281            self.__searchDock.setObjectName("SearchWindow")
282            self.__searchDock.setWidget(self.__searchWindow)
283            self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea,
284                               self.__searchDock)
285
286        # JavaScript Console window
287        from .WebBrowserJavaScriptConsole import WebBrowserJavaScriptConsole
288        self.__javascriptConsole = WebBrowserJavaScriptConsole(self)
289        self.__javascriptConsoleDock = QDockWidget(
290            self.tr("JavaScript Console"))
291        self.__javascriptConsoleDock.setObjectName("JavascriptConsole")
292        self.__javascriptConsoleDock.setAllowedAreas(
293            Qt.DockWidgetArea.BottomDockWidgetArea |
294            Qt.DockWidgetArea.TopDockWidgetArea)
295        self.__javascriptConsoleDock.setWidget(self.__javascriptConsole)
296        self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea,
297                           self.__javascriptConsoleDock)
298
299        g = (
300            Preferences.getGeometry("WebBrowserGeometry")
301            if Preferences.getWebBrowser("SaveGeometry") else
302            QByteArray()
303        )
304        if g.isEmpty():
305            s = QSize(800, 800)
306            self.resize(s)
307        else:
308            self.restoreGeometry(g)
309
310        WebBrowserWindow.BrowserWindows.append(self)
311
312        self.__initWebEngineSettings()
313
314        # initialize some of our class objects
315        self.passwordManager()
316        self.historyManager()
317        self.greaseMonkeyManager()
318        self.protocolHandlerManager()
319
320        # initialize the actions
321        self.__initActions()
322
323        # initialize the menus
324        self.__initMenus()
325        self.__initSuperMenu()
326        if Preferences.getWebBrowser("MenuBarVisible"):
327            self.__navigationBar.superMenuButton().hide()
328        else:
329            self.menuBar().hide()
330
331        # save references to toolbars in order to hide them
332        # when going full screen
333        self.__toolbars = {}
334        # initialize toolbars
335        if Preferences.getWebBrowser("ShowToolbars"):
336            self.__initToolbars()
337        self.__bookmarksToolBar.setVisible(
338            Preferences.getWebBrowser("BookmarksToolBarVisible"))
339
340        syncMgr = self.syncManager()
341        syncMgr.syncMessage.connect(self.statusBar().showMessage)
342        syncMgr.syncError.connect(self.statusBar().showMessage)
343
344        restoreSessionData = {}
345        if (
346            WebBrowserWindow._performingStartup and
347            not home and
348            not WebBrowserWindow.isPrivate()
349        ):
350            startupBehavior = Preferences.getWebBrowser("StartupBehavior")
351            if not private and startupBehavior in [3, 4]:
352                if startupBehavior == 3:
353                    # restore last session
354                    restoreSessionFile = (
355                        self.sessionManager().lastActiveSessionFile()
356                    )
357                elif startupBehavior == 4:
358                    # select session
359                    restoreSessionFile = self.sessionManager().selectSession()
360                sessionData = self.sessionManager().readSessionFromFile(
361                    restoreSessionFile)
362                if self.sessionManager().isValidSession(sessionData):
363                    restoreSessionData = sessionData
364                    restoreSession = True
365            else:
366                if Preferences.getWebBrowser("StartupBehavior") == 0:
367                    home = "about:blank"
368                elif Preferences.getWebBrowser("StartupBehavior") == 1:
369                    home = Preferences.getWebBrowser("HomePage")
370                elif Preferences.getWebBrowser("StartupBehavior") == 2:
371                    home = "eric:speeddial"
372
373        if not restoreSession:
374            self.__tabWidget.newBrowser(QUrl.fromUserInput(home))
375            self.__tabWidget.currentBrowser().setFocus()
376        WebBrowserWindow._performingStartup = False
377
378        self.__imagesIcon = ImagesIcon(self)
379        self.statusBar().addPermanentWidget(self.__imagesIcon)
380        self.__javaScriptIcon = JavaScriptIcon(self)
381        self.statusBar().addPermanentWidget(self.__javaScriptIcon)
382
383        self.__adBlockIcon = AdBlockIcon(self)
384        self.statusBar().addPermanentWidget(self.__adBlockIcon)
385        self.__adBlockIcon.setEnabled(
386            Preferences.getWebBrowser("AdBlockEnabled"))
387        self.__tabWidget.currentChanged[int].connect(
388            self.__adBlockIcon.currentChanged)
389        self.__tabWidget.sourceChanged.connect(
390            self.__adBlockIcon.sourceChanged)
391
392        self.__tabManagerIcon = self.tabManager().createStatusBarIcon()
393        self.statusBar().addPermanentWidget(self.__tabManagerIcon)
394
395        if not Preferences.getWebBrowser("StatusBarVisible"):
396            self.statusBar().hide()
397
398        if len(WebBrowserWindow.BrowserWindows):
399            QDesktopServices.setUrlHandler(
400                "http", WebBrowserWindow.BrowserWindows[0].urlHandler)
401            QDesktopServices.setUrlHandler(
402                "https", WebBrowserWindow.BrowserWindows[0].urlHandler)
403
404        # setup connections
405        self.__activating = False
406        if WebBrowserWindow._useQtHelp:
407            # TOC window
408            self.__tocWindow.escapePressed.connect(
409                self.__activateCurrentBrowser)
410            self.__tocWindow.openUrl.connect(self.openUrl)
411            self.__tocWindow.newTab.connect(self.openUrlNewTab)
412            self.__tocWindow.newBackgroundTab.connect(
413                self.openUrlNewBackgroundTab)
414            self.__tocWindow.newWindow.connect(self.openUrlNewWindow)
415
416            # index window
417            self.__indexWindow.escapePressed.connect(
418                self.__activateCurrentBrowser)
419            self.__indexWindow.openUrl.connect(self.openUrl)
420            self.__indexWindow.newTab.connect(self.openUrlNewTab)
421            self.__indexWindow.newBackgroundTab.connect(
422                self.openUrlNewBackgroundTab)
423            self.__indexWindow.newWindow.connect(self.openUrlNewWindow)
424
425            # search window
426            self.__searchWindow.escapePressed.connect(
427                self.__activateCurrentBrowser)
428            self.__searchWindow.openUrl.connect(self.openUrl)
429            self.__searchWindow.newTab.connect(self.openUrlNewTab)
430            self.__searchWindow.newBackgroundTab.connect(
431                self.openUrlNewBackgroundTab)
432            self.__searchWindow.newWindow.connect(self.openUrlNewWindow)
433
434        state = Preferences.getWebBrowser("WebBrowserState")
435        self.restoreState(state)
436
437        self.__initHelpDb()
438
439        self.__virusTotal = VirusTotalAPI(self)
440        self.__virusTotal.submitUrlError.connect(
441            self.__virusTotalSubmitUrlError)
442        self.__virusTotal.urlScanReport.connect(
443            self.__virusTotalUrlScanReport)
444        self.__virusTotal.fileScanReport.connect(
445            self.__virusTotalFileScanReport)
446
447        e5App().focusChanged.connect(self.__appFocusChanged)
448
449        self.__toolbarStates = self.saveState()
450
451        if single:
452            self.SAServer = WebBrowserSingleApplicationServer(saname)
453            self.SAServer.loadUrl.connect(self.__saLoadUrl)
454            self.SAServer.newTab.connect(self.__saNewTab)
455            self.SAServer.search.connect(self.__saSearchWord)
456            self.SAServer.shutdown.connect(self.shutdown)
457        else:
458            self.SAServer = None
459
460        self.__hideNavigationTimer = QTimer(self)
461        self.__hideNavigationTimer.setInterval(1000)
462        self.__hideNavigationTimer.setSingleShot(True)
463        self.__hideNavigationTimer.timeout.connect(self.__hideNavigation)
464
465        self.__forcedClose = False
466
467        if restoreSessionData and not WebBrowserWindow.isPrivate():
468            self.sessionManager().restoreSessionFromData(
469                self, restoreSessionData)
470
471        if not WebBrowserWindow.isPrivate():
472            self.sessionManager().activateTimer()
473
474        QTimer.singleShot(0, syncMgr.loadSettings)
475
476        if WebBrowserWindow._useQtHelp:
477            QTimer.singleShot(50, self.__lookForNewDocumentation)
478            if self.__searchWord is not None:
479                QTimer.singleShot(0, self.__searchForWord)
480
481    def __del__(self):
482        """
483        Special method called during object destruction.
484
485        Note: This empty variant seems to get rid of the Qt message
486        'Warning: QBasicTimer::start: QBasicTimer can only be used with
487        threads started with QThread'
488        """
489        pass
490
491    def tabWidget(self):
492        """
493        Public method to get a reference to the tab widget.
494
495        @return reference to the tab widget
496        @rtype WebBrowserTabWidget
497        """
498        return self.__tabWidget
499
500    def __setIconDatabasePath(self, enable=True):
501        """
502        Private method to set the favicons path.
503
504        @param enable flag indicating to enabled icon storage (boolean)
505        """
506        if enable:
507            iconDatabasePath = os.path.join(Utilities.getConfigDir(),
508                                            "web_browser", "favicons")
509            if not os.path.exists(iconDatabasePath):
510                os.makedirs(iconDatabasePath)
511        else:
512            iconDatabasePath = ""   # setting an empty path disables it
513
514        WebIconProvider.instance().setIconDatabasePath(iconDatabasePath)
515
516    def __initWebEngineSettings(self):
517        """
518        Private method to set the global web settings.
519        """
520        settings = self.webSettings()
521
522        settings.setFontFamily(
523            QWebEngineSettings.FontFamily.StandardFont,
524            Preferences.getWebBrowser("StandardFontFamily"))
525        settings.setFontFamily(
526            QWebEngineSettings.FontFamily.FixedFont,
527            Preferences.getWebBrowser("FixedFontFamily"))
528        settings.setFontFamily(
529            QWebEngineSettings.FontFamily.SerifFont,
530            Preferences.getWebBrowser("SerifFontFamily"))
531        settings.setFontFamily(
532            QWebEngineSettings.FontFamily.SansSerifFont,
533            Preferences.getWebBrowser("SansSerifFontFamily"))
534        settings.setFontFamily(
535            QWebEngineSettings.FontFamily.CursiveFont,
536            Preferences.getWebBrowser("CursiveFontFamily"))
537        settings.setFontFamily(
538            QWebEngineSettings.FontFamily.FantasyFont,
539            Preferences.getWebBrowser("FantasyFontFamily"))
540
541        settings.setFontSize(
542            QWebEngineSettings.FontSize.DefaultFontSize,
543            Preferences.getWebBrowser("DefaultFontSize"))
544        settings.setFontSize(
545            QWebEngineSettings.FontSize.DefaultFixedFontSize,
546            Preferences.getWebBrowser("DefaultFixedFontSize"))
547        settings.setFontSize(
548            QWebEngineSettings.FontSize.MinimumFontSize,
549            Preferences.getWebBrowser("MinimumFontSize"))
550        settings.setFontSize(
551            QWebEngineSettings.FontSize.MinimumLogicalFontSize,
552            Preferences.getWebBrowser("MinimumLogicalFontSize"))
553
554        styleSheet = Preferences.getWebBrowser("UserStyleSheet")
555        self.__setUserStyleSheet(styleSheet)
556
557        settings.setAttribute(
558            QWebEngineSettings.WebAttribute.AutoLoadImages,
559            Preferences.getWebBrowser("AutoLoadImages"))
560        settings.setAttribute(
561            QWebEngineSettings.WebAttribute.JavascriptEnabled,
562            Preferences.getWebBrowser("JavaScriptEnabled"))
563        # JavaScript is needed for the web browser functionality
564        settings.setAttribute(
565            QWebEngineSettings.WebAttribute.JavascriptCanOpenWindows,
566            Preferences.getWebBrowser("JavaScriptCanOpenWindows"))
567        settings.setAttribute(
568            QWebEngineSettings.WebAttribute.JavascriptCanAccessClipboard,
569            Preferences.getWebBrowser("JavaScriptCanAccessClipboard"))
570        settings.setAttribute(
571            QWebEngineSettings.WebAttribute.PluginsEnabled,
572            Preferences.getWebBrowser("PluginsEnabled"))
573
574        if self.isPrivate():
575            settings.setAttribute(
576                QWebEngineSettings.WebAttribute.LocalStorageEnabled, False)
577        else:
578            settings.setAttribute(
579                QWebEngineSettings.WebAttribute.LocalStorageEnabled,
580                Preferences.getWebBrowser("LocalStorageEnabled"))
581        settings.setDefaultTextEncoding(
582            Preferences.getWebBrowser("DefaultTextEncoding"))
583
584        settings.setAttribute(
585            QWebEngineSettings.WebAttribute.SpatialNavigationEnabled,
586            Preferences.getWebBrowser("SpatialNavigationEnabled"))
587        settings.setAttribute(
588            QWebEngineSettings.WebAttribute.LinksIncludedInFocusChain,
589            Preferences.getWebBrowser("LinksIncludedInFocusChain"))
590        settings.setAttribute(
591            QWebEngineSettings.WebAttribute.LocalContentCanAccessRemoteUrls,
592            Preferences.getWebBrowser("LocalContentCanAccessRemoteUrls"))
593        settings.setAttribute(
594            QWebEngineSettings.WebAttribute.LocalContentCanAccessFileUrls,
595            Preferences.getWebBrowser("LocalContentCanAccessFileUrls"))
596        settings.setAttribute(
597            QWebEngineSettings.WebAttribute.XSSAuditingEnabled,
598            Preferences.getWebBrowser("XSSAuditingEnabled"))
599        settings.setAttribute(
600            QWebEngineSettings.WebAttribute.ScrollAnimatorEnabled,
601            Preferences.getWebBrowser("ScrollAnimatorEnabled"))
602        settings.setAttribute(
603            QWebEngineSettings.WebAttribute.ErrorPageEnabled,
604            Preferences.getWebBrowser("ErrorPageEnabled"))
605        settings.setAttribute(
606            QWebEngineSettings.WebAttribute.FullScreenSupportEnabled,
607            Preferences.getWebBrowser("FullScreenSupportEnabled"))
608        settings.setAttribute(
609            QWebEngineSettings.WebAttribute.ScreenCaptureEnabled,
610            Preferences.getWebBrowser("ScreenCaptureEnabled"))
611        settings.setAttribute(
612            QWebEngineSettings.WebAttribute.WebGLEnabled,
613            Preferences.getWebBrowser("WebGLEnabled"))
614        settings.setAttribute(
615            QWebEngineSettings.WebAttribute.FocusOnNavigationEnabled,
616            Preferences.getWebBrowser("FocusOnNavigationEnabled"))
617        settings.setAttribute(
618            QWebEngineSettings.WebAttribute.PrintElementBackgrounds,
619            Preferences.getWebBrowser("PrintElementBackgrounds"))
620        settings.setAttribute(
621            QWebEngineSettings.WebAttribute.AllowRunningInsecureContent,
622            Preferences.getWebBrowser("AllowRunningInsecureContent"))
623        settings.setAttribute(
624            QWebEngineSettings.WebAttribute.AllowGeolocationOnInsecureOrigins,
625            Preferences.getWebBrowser("AllowGeolocationOnInsecureOrigins"))
626        settings.setAttribute(
627            QWebEngineSettings.WebAttribute
628            .AllowWindowActivationFromJavaScript,
629            Preferences.getWebBrowser(
630                "AllowWindowActivationFromJavaScript"))
631        settings.setAttribute(
632            QWebEngineSettings.WebAttribute.ShowScrollBars,
633            Preferences.getWebBrowser("ShowScrollBars"))
634        settings.setAttribute(
635            QWebEngineSettings.WebAttribute.PlaybackRequiresUserGesture,
636            Preferences.getWebBrowser(
637                "PlaybackRequiresUserGesture"))
638        settings.setAttribute(
639            QWebEngineSettings.WebAttribute.JavascriptCanPaste,
640            Preferences.getWebBrowser(
641                "JavaScriptCanPaste"))
642        settings.setAttribute(
643            QWebEngineSettings.WebAttribute.WebRTCPublicInterfacesOnly,
644            Preferences.getWebBrowser(
645                "WebRTCPublicInterfacesOnly"))
646        settings.setAttribute(
647            QWebEngineSettings.WebAttribute.DnsPrefetchEnabled,
648            Preferences.getWebBrowser(
649                "DnsPrefetchEnabled"))
650
651        with contextlib.suppress(AttributeError, KeyError):
652            # Qt 5.13
653            settings.setAttribute(
654                QWebEngineSettings.WebAttribute.PdfViewerEnabled,
655                Preferences.getWebBrowser(
656                    "PdfViewerEnabled"))
657
658    def __initActions(self):
659        """
660        Private method to define the user interface actions.
661        """
662        # list of all actions
663        self.__actions = []
664
665        self.newTabAct = E5Action(
666            self.tr('New Tab'),
667            UI.PixmapCache.getIcon("tabNew"),
668            self.tr('&New Tab'),
669            QKeySequence(self.tr("Ctrl+T", "File|New Tab")),
670            0, self, 'webbrowser_file_new_tab')
671        self.newTabAct.setStatusTip(self.tr('Open a new web browser tab'))
672        self.newTabAct.setWhatsThis(self.tr(
673            """<b>New Tab</b>"""
674            """<p>This opens a new web browser tab.</p>"""
675        ))
676        self.newTabAct.triggered.connect(self.newTab)
677        self.__actions.append(self.newTabAct)
678
679        self.newAct = E5Action(
680            self.tr('New Window'),
681            UI.PixmapCache.getIcon("newWindow"),
682            self.tr('New &Window'),
683            QKeySequence(self.tr("Ctrl+N", "File|New Window")),
684            0, self, 'webbrowser_file_new_window')
685        self.newAct.setStatusTip(self.tr('Open a new web browser window'))
686        self.newAct.setWhatsThis(self.tr(
687            """<b>New Window</b>"""
688            """<p>This opens a new web browser window in the current"""
689            """ privacy mode.</p>"""
690        ))
691        self.newAct.triggered.connect(self.newWindow)
692        self.__actions.append(self.newAct)
693
694        self.newPrivateAct = E5Action(
695            self.tr('New Private Window'),
696            UI.PixmapCache.getIcon("privateMode"),
697            self.tr('New &Private Window'),
698            QKeySequence(self.tr("Ctrl+Shift+P", "File|New Private Window")),
699            0, self, 'webbrowser_file_new_private_window')
700        self.newPrivateAct.setStatusTip(self.tr(
701            'Open a new private web browser window'))
702        self.newPrivateAct.setWhatsThis(self.tr(
703            """<b>New Private Window</b>"""
704            """<p>This opens a new private web browser window by starting"""
705            """ a new web browser instance in private mode.</p>"""
706        ))
707        self.newPrivateAct.triggered.connect(self.newPrivateWindow)
708        self.__actions.append(self.newPrivateAct)
709
710        self.openAct = E5Action(
711            self.tr('Open File'),
712            UI.PixmapCache.getIcon("open"),
713            self.tr('&Open File'),
714            QKeySequence(self.tr("Ctrl+O", "File|Open")),
715            0, self, 'webbrowser_file_open')
716        self.openAct.setStatusTip(self.tr('Open a file for display'))
717        self.openAct.setWhatsThis(self.tr(
718            """<b>Open File</b>"""
719            """<p>This opens a new file for display."""
720            """ It pops up a file selection dialog.</p>"""
721        ))
722        self.openAct.triggered.connect(self.__openFile)
723        self.__actions.append(self.openAct)
724
725        self.openTabAct = E5Action(
726            self.tr('Open File in New Tab'),
727            UI.PixmapCache.getIcon("openNewTab"),
728            self.tr('Open File in New &Tab'),
729            QKeySequence(self.tr("Shift+Ctrl+O", "File|Open in new tab")),
730            0, self, 'webbrowser_file_open_tab')
731        self.openTabAct.setStatusTip(
732            self.tr('Open a file for display in a new tab'))
733        self.openTabAct.setWhatsThis(self.tr(
734            """<b>Open File in New Tab</b>"""
735            """<p>This opens a new file for display in a new tab."""
736            """ It pops up a file selection dialog.</p>"""
737        ))
738        self.openTabAct.triggered.connect(self.__openFileNewTab)
739        self.__actions.append(self.openTabAct)
740
741        if hasattr(QWebEnginePage, "SavePage"):
742            self.saveAsAct = E5Action(
743                self.tr('Save As'),
744                UI.PixmapCache.getIcon("fileSaveAs"),
745                self.tr('&Save As...'),
746                QKeySequence(self.tr("Shift+Ctrl+S", "File|Save As")),
747                0, self, 'webbrowser_file_save_as')
748            self.saveAsAct.setStatusTip(
749                self.tr('Save the current page to disk'))
750            self.saveAsAct.setWhatsThis(self.tr(
751                """<b>Save As...</b>"""
752                """<p>Saves the current page to disk.</p>"""
753            ))
754            self.saveAsAct.triggered.connect(self.__savePageAs)
755            self.__actions.append(self.saveAsAct)
756        else:
757            self.saveAsAct = None
758
759        self.saveVisiblePageScreenAct = E5Action(
760            self.tr('Save Page Screen'),
761            UI.PixmapCache.getIcon("fileSavePixmap"),
762            self.tr('Save Page Screen...'),
763            0, 0, self, 'webbrowser_file_save_visible_page_screen')
764        self.saveVisiblePageScreenAct.setStatusTip(
765            self.tr('Save the visible part of the current page as a'
766                    ' screen shot'))
767        self.saveVisiblePageScreenAct.setWhatsThis(self.tr(
768            """<b>Save Page Screen...</b>"""
769            """<p>Saves the visible part of the current page as a"""
770            """ screen shot.</p>"""
771        ))
772        self.saveVisiblePageScreenAct.triggered.connect(
773            self.__saveVisiblePageScreen)
774        self.__actions.append(self.saveVisiblePageScreenAct)
775
776        bookmarksManager = self.bookmarksManager()
777        self.importBookmarksAct = E5Action(
778            self.tr('Import Bookmarks'),
779            self.tr('&Import Bookmarks...'),
780            0, 0, self, 'webbrowser_file_import_bookmarks')
781        self.importBookmarksAct.setStatusTip(
782            self.tr('Import bookmarks from other browsers'))
783        self.importBookmarksAct.setWhatsThis(self.tr(
784            """<b>Import Bookmarks</b>"""
785            """<p>Import bookmarks from other browsers.</p>"""
786        ))
787        self.importBookmarksAct.triggered.connect(
788            bookmarksManager.importBookmarks)
789        self.__actions.append(self.importBookmarksAct)
790
791        self.exportBookmarksAct = E5Action(
792            self.tr('Export Bookmarks'),
793            self.tr('&Export Bookmarks...'),
794            0, 0, self, 'webbrowser_file_export_bookmarks')
795        self.exportBookmarksAct.setStatusTip(
796            self.tr('Export the bookmarks into a file'))
797        self.exportBookmarksAct.setWhatsThis(self.tr(
798            """<b>Export Bookmarks</b>"""
799            """<p>Export the bookmarks into a file.</p>"""
800        ))
801        self.exportBookmarksAct.triggered.connect(
802            bookmarksManager.exportBookmarks)
803        self.__actions.append(self.exportBookmarksAct)
804
805        self.printAct = E5Action(
806            self.tr('Print'),
807            UI.PixmapCache.getIcon("print"),
808            self.tr('&Print'),
809            QKeySequence(self.tr("Ctrl+P", "File|Print")),
810            0, self, 'webbrowser_file_print')
811        self.printAct.setStatusTip(self.tr('Print the displayed help'))
812        self.printAct.setWhatsThis(self.tr(
813            """<b>Print</b>"""
814            """<p>Print the displayed help text.</p>"""
815        ))
816        self.printAct.triggered.connect(self.__tabWidget.printBrowser)
817        self.__actions.append(self.printAct)
818
819        self.printPdfAct = E5Action(
820            self.tr('Print as PDF'),
821            UI.PixmapCache.getIcon("printPdf"),
822            self.tr('Print as PDF'),
823            0, 0, self, 'webbrowser_file_print_pdf')
824        self.printPdfAct.setStatusTip(self.tr(
825            'Print the displayed help as PDF'))
826        self.printPdfAct.setWhatsThis(self.tr(
827            """<b>Print as PDF</b>"""
828            """<p>Print the displayed help text as a PDF file.</p>"""
829        ))
830        self.printPdfAct.triggered.connect(
831            self.__tabWidget.printBrowserPdf)
832        self.__actions.append(self.printPdfAct)
833
834        self.printPreviewAct = E5Action(
835            self.tr('Print Preview'),
836            UI.PixmapCache.getIcon("printPreview"),
837            self.tr('Print Preview'),
838            0, 0, self, 'webbrowser_file_print_preview')
839        self.printPreviewAct.setStatusTip(self.tr(
840            'Print preview of the displayed help'))
841        self.printPreviewAct.setWhatsThis(self.tr(
842            """<b>Print Preview</b>"""
843            """<p>Print preview of the displayed help text.</p>"""
844        ))
845        self.printPreviewAct.triggered.connect(
846            self.__tabWidget.printPreviewBrowser)
847        self.__actions.append(self.printPreviewAct)
848
849        self.sendPageLinkAct = E5Action(
850            self.tr('Send Page Link'),
851            UI.PixmapCache.getIcon("mailSend"),
852            self.tr('Send Page Link'),
853            0, 0, self, 'webbrowser_send_page_link')
854        self.sendPageLinkAct.setStatusTip(self.tr(
855            'Send the link of the current page via email'))
856        self.sendPageLinkAct.setWhatsThis(self.tr(
857            """<b>Send Page Link</b>"""
858            """<p>Send the link of the current page via email.</p>"""
859        ))
860        self.sendPageLinkAct.triggered.connect(self.__sendPageLink)
861        self.__actions.append(self.sendPageLinkAct)
862
863        self.closeAct = E5Action(
864            self.tr('Close'),
865            UI.PixmapCache.getIcon("close"),
866            self.tr('&Close'),
867            QKeySequence(self.tr("Ctrl+W", "File|Close")),
868            0, self, 'webbrowser_file_close')
869        self.closeAct.setStatusTip(self.tr(
870            'Close the current help window'))
871        self.closeAct.setWhatsThis(self.tr(
872            """<b>Close</b>"""
873            """<p>Closes the current web browser window.</p>"""
874        ))
875        self.closeAct.triggered.connect(self.__tabWidget.closeBrowser)
876        self.__actions.append(self.closeAct)
877
878        self.closeAllAct = E5Action(
879            self.tr('Close All'),
880            self.tr('Close &All'),
881            0, 0, self, 'webbrowser_file_close_all')
882        self.closeAllAct.setStatusTip(self.tr('Close all help windows'))
883        self.closeAllAct.setWhatsThis(self.tr(
884            """<b>Close All</b>"""
885            """<p>Closes all web browser windows except the first one.</p>"""
886        ))
887        self.closeAllAct.triggered.connect(
888            self.__tabWidget.closeAllBrowsers)
889        self.__actions.append(self.closeAllAct)
890
891        self.exitAct = E5Action(
892            self.tr('Quit'),
893            UI.PixmapCache.getIcon("exit"),
894            self.tr('&Quit'),
895            QKeySequence(self.tr("Ctrl+Q", "File|Quit")),
896            0, self, 'webbrowser_file_quit')
897        self.exitAct.setStatusTip(self.tr('Quit the eric Web Browser'))
898        self.exitAct.setWhatsThis(self.tr(
899            """<b>Quit</b>"""
900            """<p>Quit the eric Web Browser.</p>"""
901        ))
902        self.exitAct.triggered.connect(self.shutdown)
903        self.__actions.append(self.exitAct)
904
905        self.backAct = E5Action(
906            self.tr('Backward'),
907            UI.PixmapCache.getIcon("back"),
908            self.tr('&Backward'),
909            QKeySequence(self.tr("Alt+Left", "Go|Backward")),
910            0, self, 'webbrowser_go_backward')
911        self.backAct.setStatusTip(self.tr('Move one screen backward'))
912        self.backAct.setWhatsThis(self.tr(
913            """<b>Backward</b>"""
914            """<p>Moves one screen backward. If none is"""
915            """ available, this action is disabled.</p>"""
916        ))
917        self.backAct.triggered.connect(self.__backward)
918        self.__actions.append(self.backAct)
919
920        self.forwardAct = E5Action(
921            self.tr('Forward'),
922            UI.PixmapCache.getIcon("forward"),
923            self.tr('&Forward'),
924            QKeySequence(self.tr("Alt+Right", "Go|Forward")),
925            0, self, 'webbrowser_go_foreward')
926        self.forwardAct.setStatusTip(self.tr(
927            'Move one screen forward'))
928        self.forwardAct.setWhatsThis(self.tr(
929            """<b>Forward</b>"""
930            """<p>Moves one screen forward. If none is"""
931            """ available, this action is disabled.</p>"""
932        ))
933        self.forwardAct.triggered.connect(self.__forward)
934        self.__actions.append(self.forwardAct)
935
936        self.homeAct = E5Action(
937            self.tr('Home'),
938            UI.PixmapCache.getIcon("home"),
939            self.tr('&Home'),
940            QKeySequence(self.tr("Ctrl+Home", "Go|Home")),
941            0, self, 'webbrowser_go_home')
942        self.homeAct.setStatusTip(self.tr(
943            'Move to the initial screen'))
944        self.homeAct.setWhatsThis(self.tr(
945            """<b>Home</b>"""
946            """<p>Moves to the initial screen.</p>"""
947        ))
948        self.homeAct.triggered.connect(self.__home)
949        self.__actions.append(self.homeAct)
950
951        self.reloadAct = E5Action(
952            self.tr('Reload'),
953            UI.PixmapCache.getIcon("reload"),
954            self.tr('&Reload'),
955            QKeySequence(self.tr("Ctrl+R", "Go|Reload")),
956            QKeySequence(self.tr("F5", "Go|Reload")),
957            self, 'webbrowser_go_reload')
958        self.reloadAct.setStatusTip(self.tr(
959            'Reload the current screen'))
960        self.reloadAct.setWhatsThis(self.tr(
961            """<b>Reload</b>"""
962            """<p>Reloads the current screen.</p>"""
963        ))
964        self.reloadAct.triggered.connect(self.__reload)
965        self.__actions.append(self.reloadAct)
966
967        self.stopAct = E5Action(
968            self.tr('Stop'),
969            UI.PixmapCache.getIcon("stopLoading"),
970            self.tr('&Stop'),
971            QKeySequence(self.tr("Ctrl+.", "Go|Stop")),
972            QKeySequence(self.tr("Esc", "Go|Stop")),
973            self, 'webbrowser_go_stop')
974        self.stopAct.setStatusTip(self.tr('Stop loading'))
975        self.stopAct.setWhatsThis(self.tr(
976            """<b>Stop</b>"""
977            """<p>Stops loading of the current tab.</p>"""
978        ))
979        self.stopAct.triggered.connect(self.__stopLoading)
980        self.__actions.append(self.stopAct)
981
982        self.copyAct = E5Action(
983            self.tr('Copy'),
984            UI.PixmapCache.getIcon("editCopy"),
985            self.tr('&Copy'),
986            QKeySequence(self.tr("Ctrl+C", "Edit|Copy")),
987            0, self, 'webbrowser_edit_copy')
988        self.copyAct.setStatusTip(self.tr('Copy the selected text'))
989        self.copyAct.setWhatsThis(self.tr(
990            """<b>Copy</b>"""
991            """<p>Copy the selected text to the clipboard.</p>"""
992        ))
993        self.copyAct.triggered.connect(self.__copy)
994        self.__actions.append(self.copyAct)
995
996        self.cutAct = E5Action(
997            self.tr('Cut'),
998            UI.PixmapCache.getIcon("editCut"),
999            self.tr('Cu&t'),
1000            QKeySequence(self.tr("Ctrl+X", "Edit|Cut")),
1001            0, self, 'webbrowser_edit_cut')
1002        self.cutAct.setStatusTip(self.tr('Cut the selected text'))
1003        self.cutAct.setWhatsThis(self.tr(
1004            """<b>Cut</b>"""
1005            """<p>Cut the selected text to the clipboard.</p>"""
1006        ))
1007        self.cutAct.triggered.connect(self.__cut)
1008        self.__actions.append(self.cutAct)
1009
1010        self.pasteAct = E5Action(
1011            self.tr('Paste'),
1012            UI.PixmapCache.getIcon("editPaste"),
1013            self.tr('&Paste'),
1014            QKeySequence(self.tr("Ctrl+V", "Edit|Paste")),
1015            0, self, 'webbrowser_edit_paste')
1016        self.pasteAct.setStatusTip(self.tr('Paste text from the clipboard'))
1017        self.pasteAct.setWhatsThis(self.tr(
1018            """<b>Paste</b>"""
1019            """<p>Paste some text from the clipboard.</p>"""
1020        ))
1021        self.pasteAct.triggered.connect(self.__paste)
1022        self.__actions.append(self.pasteAct)
1023
1024        self.undoAct = E5Action(
1025            self.tr('Undo'),
1026            UI.PixmapCache.getIcon("editUndo"),
1027            self.tr('&Undo'),
1028            QKeySequence(self.tr("Ctrl+Z", "Edit|Undo")),
1029            0, self, 'webbrowser_edit_undo')
1030        self.undoAct.setStatusTip(self.tr('Undo the last edit action'))
1031        self.undoAct.setWhatsThis(self.tr(
1032            """<b>Undo</b>"""
1033            """<p>Undo the last edit action.</p>"""
1034        ))
1035        self.undoAct.triggered.connect(self.__undo)
1036        self.__actions.append(self.undoAct)
1037
1038        self.redoAct = E5Action(
1039            self.tr('Redo'),
1040            UI.PixmapCache.getIcon("editRedo"),
1041            self.tr('&Redo'),
1042            QKeySequence(self.tr("Ctrl+Shift+Z", "Edit|Redo")),
1043            0, self, 'webbrowser_edit_redo')
1044        self.redoAct.setStatusTip(self.tr('Redo the last edit action'))
1045        self.redoAct.setWhatsThis(self.tr(
1046            """<b>Redo</b>"""
1047            """<p>Redo the last edit action.</p>"""
1048        ))
1049        self.redoAct.triggered.connect(self.__redo)
1050        self.__actions.append(self.redoAct)
1051
1052        self.selectAllAct = E5Action(
1053            self.tr('Select All'),
1054            UI.PixmapCache.getIcon("editSelectAll"),
1055            self.tr('&Select All'),
1056            QKeySequence(self.tr("Ctrl+A", "Edit|Select All")),
1057            0, self, 'webbrowser_edit_select_all')
1058        self.selectAllAct.setStatusTip(self.tr('Select all text'))
1059        self.selectAllAct.setWhatsThis(self.tr(
1060            """<b>Select All</b>"""
1061            """<p>Select all text of the current browser.</p>"""
1062        ))
1063        self.selectAllAct.triggered.connect(self.__selectAll)
1064        self.__actions.append(self.selectAllAct)
1065
1066        self.unselectAct = E5Action(
1067            self.tr('Unselect'),
1068            self.tr('Unselect'),
1069            QKeySequence(self.tr("Alt+Ctrl+A", "Edit|Unselect")),
1070            0, self, 'webbrowser_edit_unselect')
1071        self.unselectAct.setStatusTip(self.tr('Clear current selection'))
1072        self.unselectAct.setWhatsThis(self.tr(
1073            """<b>Unselect</b>"""
1074            """<p>Clear the selection of the current browser.</p>"""
1075        ))
1076        self.unselectAct.triggered.connect(self.__unselect)
1077        self.__actions.append(self.unselectAct)
1078
1079        self.findAct = E5Action(
1080            self.tr('Find...'),
1081            UI.PixmapCache.getIcon("find"),
1082            self.tr('&Find...'),
1083            QKeySequence(self.tr("Ctrl+F", "Edit|Find")),
1084            0, self, 'webbrowser_edit_find')
1085        self.findAct.setStatusTip(self.tr('Find text in page'))
1086        self.findAct.setWhatsThis(self.tr(
1087            """<b>Find</b>"""
1088            """<p>Find text in the current page.</p>"""
1089        ))
1090        self.findAct.triggered.connect(self.__find)
1091        self.__actions.append(self.findAct)
1092
1093        self.findNextAct = E5Action(
1094            self.tr('Find next'),
1095            UI.PixmapCache.getIcon("findNext"),
1096            self.tr('Find &next'),
1097            QKeySequence(self.tr("F3", "Edit|Find next")),
1098            0, self, 'webbrowser_edit_find_next')
1099        self.findNextAct.setStatusTip(self.tr(
1100            'Find next occurrence of text in page'))
1101        self.findNextAct.setWhatsThis(self.tr(
1102            """<b>Find next</b>"""
1103            """<p>Find the next occurrence of text in the current page.</p>"""
1104        ))
1105        self.findNextAct.triggered.connect(self.__searchWidget.findNext)
1106        self.__actions.append(self.findNextAct)
1107
1108        self.findPrevAct = E5Action(
1109            self.tr('Find previous'),
1110            UI.PixmapCache.getIcon("findPrev"),
1111            self.tr('Find &previous'),
1112            QKeySequence(self.tr("Shift+F3", "Edit|Find previous")),
1113            0, self, 'webbrowser_edit_find_previous')
1114        self.findPrevAct.setStatusTip(
1115            self.tr('Find previous occurrence of text in page'))
1116        self.findPrevAct.setWhatsThis(self.tr(
1117            """<b>Find previous</b>"""
1118            """<p>Find the previous occurrence of text in the current"""
1119            """ page.</p>"""
1120        ))
1121        self.findPrevAct.triggered.connect(
1122            self.__searchWidget.findPrevious)
1123        self.__actions.append(self.findPrevAct)
1124
1125        self.bookmarksManageAct = E5Action(
1126            self.tr('Manage Bookmarks'),
1127            self.tr('&Manage Bookmarks...'),
1128            QKeySequence(self.tr("Ctrl+Shift+B", "Help|Manage bookmarks")),
1129            0, self, 'webbrowser_bookmarks_manage')
1130        self.bookmarksManageAct.setStatusTip(self.tr(
1131            'Open a dialog to manage the bookmarks.'))
1132        self.bookmarksManageAct.setWhatsThis(self.tr(
1133            """<b>Manage Bookmarks...</b>"""
1134            """<p>Open a dialog to manage the bookmarks.</p>"""
1135        ))
1136        self.bookmarksManageAct.triggered.connect(
1137            self.__showBookmarksDialog)
1138        self.__actions.append(self.bookmarksManageAct)
1139
1140        self.bookmarksAddAct = E5Action(
1141            self.tr('Add Bookmark'),
1142            UI.PixmapCache.getIcon("addBookmark"),
1143            self.tr('Add &Bookmark...'),
1144            QKeySequence(self.tr("Ctrl+D", "Help|Add bookmark")),
1145            0, self, 'webbrowser_bookmark_add')
1146        self.bookmarksAddAct.setIconVisibleInMenu(False)
1147        self.bookmarksAddAct.setStatusTip(self.tr(
1148            'Open a dialog to add a bookmark.'))
1149        self.bookmarksAddAct.setWhatsThis(self.tr(
1150            """<b>Add Bookmark</b>"""
1151            """<p>Open a dialog to add the current URL as a bookmark.</p>"""
1152        ))
1153        self.bookmarksAddAct.triggered.connect(self.__addBookmark)
1154        self.__actions.append(self.bookmarksAddAct)
1155
1156        self.bookmarksAddFolderAct = E5Action(
1157            self.tr('Add Folder'),
1158            self.tr('Add &Folder...'),
1159            0, 0, self, 'webbrowser_bookmark_show_all')
1160        self.bookmarksAddFolderAct.setStatusTip(self.tr(
1161            'Open a dialog to add a new bookmarks folder.'))
1162        self.bookmarksAddFolderAct.setWhatsThis(self.tr(
1163            """<b>Add Folder...</b>"""
1164            """<p>Open a dialog to add a new bookmarks folder.</p>"""
1165        ))
1166        self.bookmarksAddFolderAct.triggered.connect(
1167            self.__addBookmarkFolder)
1168        self.__actions.append(self.bookmarksAddFolderAct)
1169
1170        self.bookmarksAllTabsAct = E5Action(
1171            self.tr('Bookmark All Tabs'),
1172            self.tr('Bookmark All Tabs...'),
1173            0, 0, self, 'webbrowser_bookmark_all_tabs')
1174        self.bookmarksAllTabsAct.setStatusTip(self.tr(
1175            'Bookmark all open tabs.'))
1176        self.bookmarksAllTabsAct.setWhatsThis(self.tr(
1177            """<b>Bookmark All Tabs...</b>"""
1178            """<p>Open a dialog to add a new bookmarks folder for"""
1179            """ all open tabs.</p>"""
1180        ))
1181        self.bookmarksAllTabsAct.triggered.connect(self.bookmarkAll)
1182        self.__actions.append(self.bookmarksAllTabsAct)
1183
1184        self.whatsThisAct = E5Action(
1185            self.tr('What\'s This?'),
1186            UI.PixmapCache.getIcon("whatsThis"),
1187            self.tr('&What\'s This?'),
1188            QKeySequence(self.tr("Shift+F1", "Help|What's This?'")),
1189            0, self, 'webbrowser_help_whats_this')
1190        self.whatsThisAct.setStatusTip(self.tr('Context sensitive help'))
1191        self.whatsThisAct.setWhatsThis(self.tr(
1192            """<b>Display context sensitive help</b>"""
1193            """<p>In What's This? mode, the mouse cursor shows an arrow"""
1194            """ with a question mark, and you can click on the interface"""
1195            """ elements to get a short description of what they do and how"""
1196            """ to use them. In dialogs, this feature can be accessed using"""
1197            """ the context help button in the titlebar.</p>"""
1198        ))
1199        self.whatsThisAct.triggered.connect(self.__whatsThis)
1200        self.__actions.append(self.whatsThisAct)
1201
1202        self.aboutAct = E5Action(
1203            self.tr('About'),
1204            self.tr('&About'),
1205            0, 0, self, 'webbrowser_help_about')
1206        self.aboutAct.setStatusTip(self.tr(
1207            'Display information about this software'))
1208        self.aboutAct.setWhatsThis(self.tr(
1209            """<b>About</b>"""
1210            """<p>Display some information about this software.</p>"""
1211        ))
1212        self.aboutAct.triggered.connect(self.__about)
1213        self.__actions.append(self.aboutAct)
1214
1215        self.aboutQtAct = E5Action(
1216            self.tr('About Qt'),
1217            self.tr('About &Qt'),
1218            0, 0, self, 'webbrowser_help_about_qt')
1219        self.aboutQtAct.setStatusTip(
1220            self.tr('Display information about the Qt toolkit'))
1221        self.aboutQtAct.setWhatsThis(self.tr(
1222            """<b>About Qt</b>"""
1223            """<p>Display some information about the Qt toolkit.</p>"""
1224        ))
1225        self.aboutQtAct.triggered.connect(self.__aboutQt)
1226        self.__actions.append(self.aboutQtAct)
1227
1228        self.zoomInAct = E5Action(
1229            self.tr('Zoom in'),
1230            UI.PixmapCache.getIcon("zoomIn"),
1231            self.tr('Zoom &in'),
1232            QKeySequence(self.tr("Ctrl++", "View|Zoom in")),
1233            QKeySequence(self.tr("Zoom In", "View|Zoom in")),
1234            self, 'webbrowser_view_zoom_in')
1235        self.zoomInAct.setStatusTip(self.tr('Zoom in on the web page'))
1236        self.zoomInAct.setWhatsThis(self.tr(
1237            """<b>Zoom in</b>"""
1238            """<p>Zoom in on the web page."""
1239            """ This makes the web page bigger.</p>"""
1240        ))
1241        self.zoomInAct.triggered.connect(self.__zoomIn)
1242        self.__actions.append(self.zoomInAct)
1243
1244        self.zoomOutAct = E5Action(
1245            self.tr('Zoom out'),
1246            UI.PixmapCache.getIcon("zoomOut"),
1247            self.tr('Zoom &out'),
1248            QKeySequence(self.tr("Ctrl+-", "View|Zoom out")),
1249            QKeySequence(self.tr("Zoom Out", "View|Zoom out")),
1250            self, 'webbrowser_view_zoom_out')
1251        self.zoomOutAct.setStatusTip(self.tr('Zoom out on the web page'))
1252        self.zoomOutAct.setWhatsThis(self.tr(
1253            """<b>Zoom out</b>"""
1254            """<p>Zoom out on the web page."""
1255            """ This makes the web page smaller.</p>"""
1256        ))
1257        self.zoomOutAct.triggered.connect(self.__zoomOut)
1258        self.__actions.append(self.zoomOutAct)
1259
1260        self.zoomResetAct = E5Action(
1261            self.tr('Zoom reset'),
1262            UI.PixmapCache.getIcon("zoomReset"),
1263            self.tr('Zoom &reset'),
1264            QKeySequence(self.tr("Ctrl+0", "View|Zoom reset")),
1265            0, self, 'webbrowser_view_zoom_reset')
1266        self.zoomResetAct.setStatusTip(self.tr(
1267            'Reset the zoom of the web page'))
1268        self.zoomResetAct.setWhatsThis(self.tr(
1269            """<b>Zoom reset</b>"""
1270            """<p>Reset the zoom of the web page. """
1271            """This sets the zoom factor to 100%.</p>"""
1272        ))
1273        self.zoomResetAct.triggered.connect(self.__zoomReset)
1274        self.__actions.append(self.zoomResetAct)
1275
1276        self.pageSourceAct = E5Action(
1277            self.tr('Show page source'),
1278            self.tr('Show page source'),
1279            QKeySequence(self.tr('Ctrl+U')), 0,
1280            self, 'webbrowser_show_page_source')
1281        self.pageSourceAct.setStatusTip(self.tr(
1282            'Show the page source in an editor'))
1283        self.pageSourceAct.setWhatsThis(self.tr(
1284            """<b>Show page source</b>"""
1285            """<p>Show the page source in an editor.</p>"""
1286        ))
1287        self.pageSourceAct.triggered.connect(self.__showPageSource)
1288        self.__actions.append(self.pageSourceAct)
1289        self.addAction(self.pageSourceAct)
1290
1291        self.fullScreenAct = E5Action(
1292            self.tr('Full Screen'),
1293            UI.PixmapCache.getIcon("windowFullscreen"),
1294            self.tr('&Full Screen'),
1295            0, 0,
1296            self, 'webbrowser_view_full_screen')
1297        if Globals.isMacPlatform():
1298            self.fullScreenAct.setShortcut(
1299                QKeySequence(self.tr("Meta+Ctrl+F")))
1300        else:
1301            self.fullScreenAct.setShortcut(QKeySequence(self.tr('F11')))
1302        self.fullScreenAct.triggered.connect(self.toggleFullScreen)
1303        self.__actions.append(self.fullScreenAct)
1304        self.addAction(self.fullScreenAct)
1305
1306        self.nextTabAct = E5Action(
1307            self.tr('Show next tab'),
1308            self.tr('Show next tab'),
1309            QKeySequence(self.tr('Ctrl+Alt+Tab')), 0,
1310            self, 'webbrowser_view_next_tab')
1311        self.nextTabAct.triggered.connect(self.__nextTab)
1312        self.__actions.append(self.nextTabAct)
1313        self.addAction(self.nextTabAct)
1314
1315        self.prevTabAct = E5Action(
1316            self.tr('Show previous tab'),
1317            self.tr('Show previous tab'),
1318            QKeySequence(self.tr('Shift+Ctrl+Alt+Tab')), 0,
1319            self, 'webbrowser_view_previous_tab')
1320        self.prevTabAct.triggered.connect(self.__prevTab)
1321        self.__actions.append(self.prevTabAct)
1322        self.addAction(self.prevTabAct)
1323
1324        self.switchTabAct = E5Action(
1325            self.tr('Switch between tabs'),
1326            self.tr('Switch between tabs'),
1327            QKeySequence(self.tr('Ctrl+1')), 0,
1328            self, 'webbrowser_switch_tabs')
1329        self.switchTabAct.triggered.connect(self.__switchTab)
1330        self.__actions.append(self.switchTabAct)
1331        self.addAction(self.switchTabAct)
1332
1333        self.prefAct = E5Action(
1334            self.tr('Preferences'),
1335            UI.PixmapCache.getIcon("configure"),
1336            self.tr('&Preferences...'), 0, 0, self, 'webbrowser_preferences')
1337        self.prefAct.setStatusTip(self.tr(
1338            'Set the prefered configuration'))
1339        self.prefAct.setWhatsThis(self.tr(
1340            """<b>Preferences</b>"""
1341            """<p>Set the configuration items of the application"""
1342            """ with your prefered values.</p>"""
1343        ))
1344        self.prefAct.triggered.connect(self.__showPreferences)
1345        self.__actions.append(self.prefAct)
1346
1347        self.acceptedLanguagesAct = E5Action(
1348            self.tr('Languages'),
1349            UI.PixmapCache.getIcon("flag"),
1350            self.tr('&Languages...'), 0, 0,
1351            self, 'webbrowser_accepted_languages')
1352        self.acceptedLanguagesAct.setStatusTip(self.tr(
1353            'Configure the accepted languages for web pages'))
1354        self.acceptedLanguagesAct.setWhatsThis(self.tr(
1355            """<b>Languages</b>"""
1356            """<p>Configure the accepted languages for web pages.</p>"""
1357        ))
1358        self.acceptedLanguagesAct.triggered.connect(
1359            self.__showAcceptedLanguages)
1360        self.__actions.append(self.acceptedLanguagesAct)
1361
1362        self.cookiesAct = E5Action(
1363            self.tr('Cookies'),
1364            UI.PixmapCache.getIcon("cookie"),
1365            self.tr('C&ookies...'), 0, 0, self, 'webbrowser_cookies')
1366        self.cookiesAct.setStatusTip(self.tr(
1367            'Configure cookies handling'))
1368        self.cookiesAct.setWhatsThis(self.tr(
1369            """<b>Cookies</b>"""
1370            """<p>Configure cookies handling.</p>"""
1371        ))
1372        self.cookiesAct.triggered.connect(
1373            self.__showCookiesConfiguration)
1374        self.__actions.append(self.cookiesAct)
1375
1376        self.personalDataAct = E5Action(
1377            self.tr('Personal Information'),
1378            UI.PixmapCache.getIcon("pim"),
1379            self.tr('Personal Information...'),
1380            0, 0,
1381            self, 'webbrowser_personal_information')
1382        self.personalDataAct.setStatusTip(self.tr(
1383            'Configure personal information for completing form fields'))
1384        self.personalDataAct.setWhatsThis(self.tr(
1385            """<b>Personal Information...</b>"""
1386            """<p>Opens a dialog to configure the personal information"""
1387            """ used for completing form fields.</p>"""
1388        ))
1389        self.personalDataAct.triggered.connect(
1390            self.__showPersonalInformationDialog)
1391        self.__actions.append(self.personalDataAct)
1392
1393        self.greaseMonkeyAct = E5Action(
1394            self.tr('GreaseMonkey Scripts'),
1395            UI.PixmapCache.getIcon("greaseMonkey"),
1396            self.tr('GreaseMonkey Scripts...'),
1397            0, 0,
1398            self, 'webbrowser_greasemonkey')
1399        self.greaseMonkeyAct.setStatusTip(self.tr(
1400            'Configure the GreaseMonkey Scripts'))
1401        self.greaseMonkeyAct.setWhatsThis(self.tr(
1402            """<b>GreaseMonkey Scripts...</b>"""
1403            """<p>Opens a dialog to configure the available GreaseMonkey"""
1404            """ Scripts.</p>"""
1405        ))
1406        self.greaseMonkeyAct.triggered.connect(
1407            self.__showGreaseMonkeyConfigDialog)
1408        self.__actions.append(self.greaseMonkeyAct)
1409
1410        self.editMessageFilterAct = E5Action(
1411            self.tr('Edit Message Filters'),
1412            UI.PixmapCache.getIcon("warning"),
1413            self.tr('Edit Message Filters...'), 0, 0, self,
1414            'webbrowser_manage_message_filters')
1415        self.editMessageFilterAct.setStatusTip(self.tr(
1416            'Edit the message filters used to suppress unwanted messages'))
1417        self.editMessageFilterAct.setWhatsThis(self.tr(
1418            """<b>Edit Message Filters</b>"""
1419            """<p>Opens a dialog to edit the message filters used to"""
1420            """ suppress unwanted messages been shown in an error"""
1421            """ window.</p>"""
1422        ))
1423        self.editMessageFilterAct.triggered.connect(
1424            E5ErrorMessage.editMessageFilters)
1425        self.__actions.append(self.editMessageFilterAct)
1426
1427        self.featurePermissionAct = E5Action(
1428            self.tr('Edit HTML5 Feature Permissions'),
1429            UI.PixmapCache.getIcon("featurePermission"),
1430            self.tr('Edit HTML5 Feature Permissions...'), 0, 0, self,
1431            'webbrowser_edit_feature_permissions')
1432        self.featurePermissionAct.setStatusTip(self.tr(
1433            'Edit the remembered HTML5 feature permissions'))
1434        self.featurePermissionAct.setWhatsThis(self.tr(
1435            """<b>Edit HTML5 Feature Permissions</b>"""
1436            """<p>Opens a dialog to edit the remembered HTML5"""
1437            """ feature permissions.</p>"""
1438        ))
1439        self.featurePermissionAct.triggered.connect(
1440            self.__showFeaturePermissionDialog)
1441        self.__actions.append(self.featurePermissionAct)
1442
1443        if WebBrowserWindow._useQtHelp:
1444            self.syncTocAct = E5Action(
1445                self.tr('Sync with Table of Contents'),
1446                UI.PixmapCache.getIcon("syncToc"),
1447                self.tr('Sync with Table of Contents'),
1448                0, 0, self, 'webbrowser_sync_toc')
1449            self.syncTocAct.setStatusTip(self.tr(
1450                'Synchronizes the table of contents with current page'))
1451            self.syncTocAct.setWhatsThis(self.tr(
1452                """<b>Sync with Table of Contents</b>"""
1453                """<p>Synchronizes the table of contents with current"""
1454                """ page.</p>"""
1455            ))
1456            self.syncTocAct.triggered.connect(self.__syncTOC)
1457            self.__actions.append(self.syncTocAct)
1458
1459            self.showTocAct = E5Action(
1460                self.tr('Table of Contents'),
1461                self.tr('Table of Contents'),
1462                0, 0, self, 'webbrowser_show_toc')
1463            self.showTocAct.setStatusTip(self.tr(
1464                'Shows the table of contents window'))
1465            self.showTocAct.setWhatsThis(self.tr(
1466                """<b>Table of Contents</b>"""
1467                """<p>Shows the table of contents window.</p>"""
1468            ))
1469            self.showTocAct.triggered.connect(self.__showTocWindow)
1470            self.__actions.append(self.showTocAct)
1471
1472            self.showIndexAct = E5Action(
1473                self.tr('Index'),
1474                self.tr('Index'),
1475                0, 0, self, 'webbrowser_show_index')
1476            self.showIndexAct.setStatusTip(self.tr(
1477                'Shows the index window'))
1478            self.showIndexAct.setWhatsThis(self.tr(
1479                """<b>Index</b>"""
1480                """<p>Shows the index window.</p>"""
1481            ))
1482            self.showIndexAct.triggered.connect(self.__showIndexWindow)
1483            self.__actions.append(self.showIndexAct)
1484
1485            self.showSearchAct = E5Action(
1486                self.tr('Search'),
1487                self.tr('Search'),
1488                0, 0, self, 'webbrowser_show_search')
1489            self.showSearchAct.setStatusTip(self.tr(
1490                'Shows the search window'))
1491            self.showSearchAct.setWhatsThis(self.tr(
1492                """<b>Search</b>"""
1493                """<p>Shows the search window.</p>"""
1494            ))
1495            self.showSearchAct.triggered.connect(
1496                self.__showSearchWindow)
1497            self.__actions.append(self.showSearchAct)
1498
1499            self.manageQtHelpDocsAct = E5Action(
1500                self.tr('Manage QtHelp Documents'),
1501                self.tr('Manage QtHelp &Documents'),
1502                0, 0, self, 'webbrowser_qthelp_documents')
1503            self.manageQtHelpDocsAct.setStatusTip(self.tr(
1504                'Shows a dialog to manage the QtHelp documentation set'))
1505            self.manageQtHelpDocsAct.setWhatsThis(self.tr(
1506                """<b>Manage QtHelp Documents</b>"""
1507                """<p>Shows a dialog to manage the QtHelp documentation"""
1508                """ set.</p>"""
1509            ))
1510            self.manageQtHelpDocsAct.triggered.connect(
1511                self.__manageQtHelpDocumentation)
1512            self.__actions.append(self.manageQtHelpDocsAct)
1513
1514            self.reindexDocumentationAct = E5Action(
1515                self.tr('Reindex Documentation'),
1516                self.tr('&Reindex Documentation'),
1517                0, 0, self, 'webbrowser_qthelp_reindex')
1518            self.reindexDocumentationAct.setStatusTip(self.tr(
1519                'Reindexes the documentation set'))
1520            self.reindexDocumentationAct.setWhatsThis(self.tr(
1521                """<b>Reindex Documentation</b>"""
1522                """<p>Reindexes the documentation set.</p>"""
1523            ))
1524            self.reindexDocumentationAct.triggered.connect(
1525                self.__searchEngine.reindexDocumentation)
1526            self.__actions.append(self.reindexDocumentationAct)
1527
1528        self.clearPrivateDataAct = E5Action(
1529            self.tr('Clear private data'),
1530            UI.PixmapCache.getIcon("clearPrivateData"),
1531            self.tr('Clear private data'),
1532            0, 0,
1533            self, 'webbrowser_clear_private_data')
1534        self.clearPrivateDataAct.setStatusTip(self.tr(
1535            'Clear private data'))
1536        self.clearPrivateDataAct.setWhatsThis(self.tr(
1537            """<b>Clear private data</b>"""
1538            """<p>Clears the private data like browsing history, search"""
1539            """ history or the favicons database.</p>"""
1540        ))
1541        self.clearPrivateDataAct.triggered.connect(
1542            self.__clearPrivateData)
1543        self.__actions.append(self.clearPrivateDataAct)
1544
1545        self.clearIconsAct = E5Action(
1546            self.tr('Clear icons database'),
1547            self.tr('Clear &icons database'),
1548            0, 0,
1549            self, 'webbrowser_clear_icons_db')
1550        self.clearIconsAct.setStatusTip(self.tr(
1551            'Clear the database of favicons'))
1552        self.clearIconsAct.setWhatsThis(self.tr(
1553            """<b>Clear icons database</b>"""
1554            """<p>Clears the database of favicons of previously visited"""
1555            """ URLs.</p>"""
1556        ))
1557        self.clearIconsAct.triggered.connect(self.__clearIconsDatabase)
1558        self.__actions.append(self.clearIconsAct)
1559
1560        self.manageIconsAct = E5Action(
1561            self.tr('Manage saved Favicons'),
1562            UI.PixmapCache.getIcon("icons"),
1563            self.tr('Manage saved Favicons'),
1564            0, 0,
1565            self, 'webbrowser_manage_icons_db')
1566        self.manageIconsAct.setStatusTip(self.tr(
1567            'Show a dialog to manage the saved favicons'))
1568        self.manageIconsAct.setWhatsThis(self.tr(
1569            """<b>Manage saved Favicons</b>"""
1570            """<p>This shows a dialog to manage the saved favicons of"""
1571            """ previously visited URLs.</p>"""
1572        ))
1573        self.manageIconsAct.triggered.connect(self.__showWebIconsDialog)
1574        self.__actions.append(self.manageIconsAct)
1575
1576        self.searchEnginesAct = E5Action(
1577            self.tr('Configure Search Engines'),
1578            self.tr('Configure Search &Engines...'),
1579            0, 0,
1580            self, 'webbrowser_search_engines')
1581        self.searchEnginesAct.setStatusTip(self.tr(
1582            'Configure the available search engines'))
1583        self.searchEnginesAct.setWhatsThis(self.tr(
1584            """<b>Configure Search Engines...</b>"""
1585            """<p>Opens a dialog to configure the available search"""
1586            """ engines.</p>"""
1587        ))
1588        self.searchEnginesAct.triggered.connect(
1589            self.__showEnginesConfigurationDialog)
1590        self.__actions.append(self.searchEnginesAct)
1591
1592        self.passwordsAct = E5Action(
1593            self.tr('Manage Saved Passwords'),
1594            UI.PixmapCache.getIcon("passwords"),
1595            self.tr('Manage Saved Passwords...'),
1596            0, 0,
1597            self, 'webbrowser_manage_passwords')
1598        self.passwordsAct.setStatusTip(self.tr(
1599            'Manage the saved passwords'))
1600        self.passwordsAct.setWhatsThis(self.tr(
1601            """<b>Manage Saved Passwords...</b>"""
1602            """<p>Opens a dialog to manage the saved passwords.</p>"""
1603        ))
1604        self.passwordsAct.triggered.connect(self.__showPasswordsDialog)
1605        self.__actions.append(self.passwordsAct)
1606
1607        self.adblockAct = E5Action(
1608            self.tr('Ad Block'),
1609            UI.PixmapCache.getIcon("adBlockPlus"),
1610            self.tr('&Ad Block...'),
1611            0, 0,
1612            self, 'webbrowser_adblock')
1613        self.adblockAct.setStatusTip(self.tr(
1614            'Configure AdBlock subscriptions and rules'))
1615        self.adblockAct.setWhatsThis(self.tr(
1616            """<b>Ad Block...</b>"""
1617            """<p>Opens a dialog to configure AdBlock subscriptions and"""
1618            """ rules.</p>"""
1619        ))
1620        self.adblockAct.triggered.connect(self.__showAdBlockDialog)
1621        self.__actions.append(self.adblockAct)
1622
1623        self.certificateErrorsAct = E5Action(
1624            self.tr('Manage SSL Certificate Errors'),
1625            UI.PixmapCache.getIcon("certificates"),
1626            self.tr('Manage SSL Certificate Errors...'),
1627            0, 0,
1628            self, 'webbrowser_manage_certificate_errors')
1629        self.certificateErrorsAct.setStatusTip(self.tr(
1630            'Manage the accepted SSL certificate Errors'))
1631        self.certificateErrorsAct.setWhatsThis(self.tr(
1632            """<b>Manage SSL Certificate Errors...</b>"""
1633            """<p>Opens a dialog to manage the accepted SSL"""
1634            """ certificate errors.</p>"""
1635        ))
1636        self.certificateErrorsAct.triggered.connect(
1637            self.__showCertificateErrorsDialog)
1638        self.__actions.append(self.certificateErrorsAct)
1639
1640        self.safeBrowsingAct = E5Action(
1641            self.tr('Manage Safe Browsing'),
1642            UI.PixmapCache.getIcon("safeBrowsing"),
1643            self.tr('Manage Safe Browsing...'), 0, 0, self,
1644            'webbrowser_manage_safe_browsing')
1645        self.safeBrowsingAct.setStatusTip(self.tr(
1646            'Configure Safe Browsing and manage local cache'))
1647        self.safeBrowsingAct.setWhatsThis(self.tr(
1648            """<b>Manage Safe Browsing</b>"""
1649            """<p>This opens a dialog to configure Safe Browsing and"""
1650            """ to manage the local cache.</p>"""
1651        ))
1652        self.safeBrowsingAct.triggered.connect(
1653            self.__showSafeBrowsingDialog)
1654        self.__actions.append(self.safeBrowsingAct)
1655
1656        self.showDownloadManagerAct = E5Action(
1657            self.tr('Downloads'),
1658            self.tr('Downloads'),
1659            0, 0, self, 'webbrowser_show_downloads')
1660        self.showDownloadManagerAct.setStatusTip(self.tr(
1661            'Shows the downloads window'))
1662        self.showDownloadManagerAct.setWhatsThis(self.tr(
1663            """<b>Downloads</b>"""
1664            """<p>Shows the downloads window.</p>"""
1665        ))
1666        self.showDownloadManagerAct.triggered.connect(
1667            self.__showDownloadsWindow)
1668        self.__actions.append(self.showDownloadManagerAct)
1669
1670        self.feedsManagerAct = E5Action(
1671            self.tr('RSS Feeds Dialog'),
1672            UI.PixmapCache.getIcon("rss22"),
1673            self.tr('&RSS Feeds Dialog...'),
1674            QKeySequence(self.tr("Ctrl+Shift+F", "Help|RSS Feeds Dialog")),
1675            0, self, 'webbrowser_rss_feeds')
1676        self.feedsManagerAct.setStatusTip(self.tr(
1677            'Open a dialog showing the configured RSS feeds.'))
1678        self.feedsManagerAct.setWhatsThis(self.tr(
1679            """<b>RSS Feeds Dialog...</b>"""
1680            """<p>Open a dialog to show the configured RSS feeds."""
1681            """ It can be used to mange the feeds and to show their"""
1682            """ contents.</p>"""
1683        ))
1684        self.feedsManagerAct.triggered.connect(self.__showFeedsManager)
1685        self.__actions.append(self.feedsManagerAct)
1686
1687        self.siteInfoAct = E5Action(
1688            self.tr('Siteinfo Dialog'),
1689            UI.PixmapCache.getIcon("helpAbout"),
1690            self.tr('&Siteinfo Dialog...'),
1691            QKeySequence(self.tr("Ctrl+Shift+I", "Help|Siteinfo Dialog")),
1692            0, self, 'webbrowser_siteinfo')
1693        self.siteInfoAct.setStatusTip(self.tr(
1694            'Open a dialog showing some information about the current site.'))
1695        self.siteInfoAct.setWhatsThis(self.tr(
1696            """<b>Siteinfo Dialog...</b>"""
1697            """<p>Opens a dialog showing some information about the current"""
1698            """ site.</p>"""
1699        ))
1700        self.siteInfoAct.triggered.connect(self.__showSiteinfoDialog)
1701        self.__actions.append(self.siteInfoAct)
1702
1703        self.userAgentManagerAct = E5Action(
1704            self.tr('Manage User Agent Settings'),
1705            self.tr('Manage &User Agent Settings'),
1706            0, 0, self, 'webbrowser_user_agent_settings')
1707        self.userAgentManagerAct.setStatusTip(self.tr(
1708            'Shows a dialog to manage the User Agent settings'))
1709        self.userAgentManagerAct.setWhatsThis(self.tr(
1710            """<b>Manage User Agent Settings</b>"""
1711            """<p>Shows a dialog to manage the User Agent settings.</p>"""
1712        ))
1713        self.userAgentManagerAct.triggered.connect(
1714            self.__showUserAgentsDialog)
1715        self.__actions.append(self.userAgentManagerAct)
1716
1717        self.synchronizationAct = E5Action(
1718            self.tr('Synchronize data'),
1719            UI.PixmapCache.getIcon("sync"),
1720            self.tr('&Synchronize Data...'),
1721            0, 0, self, 'webbrowser_synchronize_data')
1722        self.synchronizationAct.setStatusTip(self.tr(
1723            'Shows a dialog to synchronize data via the network'))
1724        self.synchronizationAct.setWhatsThis(self.tr(
1725            """<b>Synchronize Data...</b>"""
1726            """<p>This shows a dialog to synchronize data via the"""
1727            """ network.</p>"""
1728        ))
1729        self.synchronizationAct.triggered.connect(
1730            self.__showSyncDialog)
1731        self.__actions.append(self.synchronizationAct)
1732
1733        self.zoomValuesAct = E5Action(
1734            self.tr('Manage Saved Zoom Values'),
1735            UI.PixmapCache.getIcon("zoomReset"),
1736            self.tr('Manage Saved Zoom Values...'),
1737            0, 0,
1738            self, 'webbrowser_manage_zoom_values')
1739        self.zoomValuesAct.setStatusTip(self.tr(
1740            'Manage the saved zoom values'))
1741        self.zoomValuesAct.setWhatsThis(self.tr(
1742            """<b>Manage Saved Zoom Values...</b>"""
1743            """<p>Opens a dialog to manage the saved zoom values.</p>"""
1744        ))
1745        self.zoomValuesAct.triggered.connect(self.__showZoomValuesDialog)
1746        self.__actions.append(self.zoomValuesAct)
1747
1748        self.showJavaScriptConsoleAct = E5Action(
1749            self.tr('JavaScript Console'),
1750            self.tr('JavaScript Console'),
1751            0, 0, self, 'webbrowser_show_javascript_console')
1752        self.showJavaScriptConsoleAct.setStatusTip(self.tr(
1753            'Toggle the JavaScript console window'))
1754        self.showJavaScriptConsoleAct.setWhatsThis(self.tr(
1755            """<b>JavaScript Console</b>"""
1756            """<p>This toggles the JavaScript console window.</p>"""
1757        ))
1758        self.showJavaScriptConsoleAct.triggered.connect(
1759            self.__toggleJavaScriptConsole)
1760        self.__actions.append(self.showJavaScriptConsoleAct)
1761
1762        self.showTabManagerAct = E5Action(
1763            self.tr('Tab Manager'),
1764            self.tr('Tab Manager'),
1765            0, 0, self, 'webbrowser_show_tab_manager')
1766        self.showTabManagerAct.setStatusTip(self.tr(
1767            'Shows the tab manager window'))
1768        self.showTabManagerAct.setWhatsThis(self.tr(
1769            """<b>Tab Manager</b>"""
1770            """<p>Shows the tab manager window.</p>"""
1771        ))
1772        self.showTabManagerAct.triggered.connect(
1773            lambda: self.__showTabManager(self.showTabManagerAct))
1774        self.__actions.append(self.showTabManagerAct)
1775
1776        self.showSessionsManagerAct = E5Action(
1777            self.tr('Session Manager'),
1778            self.tr('Session Manager...'),
1779            0, 0, self, 'webbrowser_show_session_manager')
1780        self.showSessionsManagerAct.setStatusTip(self.tr(
1781            'Shows the session manager window'))
1782        self.showSessionsManagerAct.setWhatsThis(self.tr(
1783            """<b>Session Manager</b>"""
1784            """<p>Shows the session manager window.</p>"""
1785        ))
1786        self.showSessionsManagerAct.triggered.connect(
1787            self.__showSessionManagerDialog)
1788        self.__actions.append(self.showSessionsManagerAct)
1789
1790        self.virustotalScanCurrentAct = E5Action(
1791            self.tr("Scan current site"),
1792            UI.PixmapCache.getIcon("virustotal"),
1793            self.tr("Scan current site"),
1794            0, 0,
1795            self, 'webbrowser_virustotal_scan_site')
1796        self.virustotalScanCurrentAct.triggered.connect(
1797            self.__virusTotalScanCurrentSite)
1798        self.__actions.append(self.virustotalScanCurrentAct)
1799
1800        self.virustotalIpReportAct = E5Action(
1801            self.tr("IP Address Report"),
1802            UI.PixmapCache.getIcon("virustotal"),
1803            self.tr("IP Address Report"),
1804            0, 0,
1805            self, 'webbrowser_virustotal_ip_report')
1806        self.virustotalIpReportAct.triggered.connect(
1807            self.__virusTotalIpAddressReport)
1808        self.__actions.append(self.virustotalIpReportAct)
1809
1810        self.virustotalDomainReportAct = E5Action(
1811            self.tr("Domain Report"),
1812            UI.PixmapCache.getIcon("virustotal"),
1813            self.tr("Domain Report"),
1814            0, 0,
1815            self, 'webbrowser_virustotal_domain_report')
1816        self.virustotalDomainReportAct.triggered.connect(
1817            self.__virusTotalDomainReport)
1818        self.__actions.append(self.virustotalDomainReportAct)
1819
1820        if (
1821            not Preferences.getWebBrowser("VirusTotalEnabled") or
1822            Preferences.getWebBrowser("VirusTotalServiceKey") == ""
1823        ):
1824            self.virustotalScanCurrentAct.setEnabled(False)
1825            self.virustotalIpReportAct.setEnabled(False)
1826            self.virustotalDomainReportAct.setEnabled(False)
1827
1828        self.shortcutsAct = E5Action(
1829            self.tr('Keyboard Shortcuts'),
1830            UI.PixmapCache.getIcon("configureShortcuts"),
1831            self.tr('Keyboard &Shortcuts...'),
1832            0, 0,
1833            self, 'webbrowser_keyboard_shortcuts')
1834        self.shortcutsAct.setStatusTip(self.tr(
1835            'Set the keyboard shortcuts'))
1836        self.shortcutsAct.setWhatsThis(self.tr(
1837            """<b>Keyboard Shortcuts</b>"""
1838            """<p>Set the keyboard shortcuts of the application"""
1839            """ with your prefered values.</p>"""
1840        ))
1841        self.shortcutsAct.triggered.connect(self.__configShortcuts)
1842        self.__actions.append(self.shortcutsAct)
1843
1844        self.exportShortcutsAct = E5Action(
1845            self.tr('Export Keyboard Shortcuts'),
1846            UI.PixmapCache.getIcon("exportShortcuts"),
1847            self.tr('&Export Keyboard Shortcuts...'),
1848            0, 0, self, 'export_keyboard_shortcuts')
1849        self.exportShortcutsAct.setStatusTip(self.tr(
1850            'Export the keyboard shortcuts'))
1851        self.exportShortcutsAct.setWhatsThis(self.tr(
1852            """<b>Export Keyboard Shortcuts</b>"""
1853            """<p>Export the keyboard shortcuts of the application.</p>"""
1854        ))
1855        self.exportShortcutsAct.triggered.connect(self.__exportShortcuts)
1856        self.__actions.append(self.exportShortcutsAct)
1857
1858        self.importShortcutsAct = E5Action(
1859            self.tr('Import Keyboard Shortcuts'),
1860            UI.PixmapCache.getIcon("importShortcuts"),
1861            self.tr('&Import Keyboard Shortcuts...'),
1862            0, 0, self, 'import_keyboard_shortcuts')
1863        self.importShortcutsAct.setStatusTip(self.tr(
1864            'Import the keyboard shortcuts'))
1865        self.importShortcutsAct.setWhatsThis(self.tr(
1866            """<b>Import Keyboard Shortcuts</b>"""
1867            """<p>Import the keyboard shortcuts of the application.</p>"""
1868        ))
1869        self.importShortcutsAct.triggered.connect(self.__importShortcuts)
1870        self.__actions.append(self.importShortcutsAct)
1871
1872        self.showProtocolHandlerManagerAct = E5Action(
1873            self.tr('Protocol Handler Manager'),
1874            self.tr('Protocol Handler Manager...'),
1875            0, 0, self, 'webbrowser_show_protocol_handler_manager')
1876        self.showProtocolHandlerManagerAct.setStatusTip(self.tr(
1877            'Shows the protocol handler manager window'))
1878        self.showProtocolHandlerManagerAct.setWhatsThis(self.tr(
1879            """<b>Protocol Handler Manager</b>"""
1880            """<p>Shows the protocol handler manager window.</p>"""
1881        ))
1882        self.showProtocolHandlerManagerAct.triggered.connect(
1883            self.__showProtocolHandlerManagerDialog)
1884        self.__actions.append(self.showProtocolHandlerManagerAct)
1885
1886        self.backAct.setEnabled(False)
1887        self.forwardAct.setEnabled(False)
1888
1889        # now read the keyboard shortcuts for the actions
1890        Shortcuts.readShortcuts(helpViewer=self)
1891
1892    def getActions(self):
1893        """
1894        Public method to get a list of all actions.
1895
1896        @return list of all actions (list of E5Action)
1897        """
1898        return self.__actions[:]
1899
1900    def getActionsCategory(self):
1901        """
1902        Public method to get the category of the defined actions.
1903
1904        @return category of the actions
1905        @rtype str
1906        """
1907        return "WebBrowser"
1908
1909    def __initMenus(self):
1910        """
1911        Private method to create the menus.
1912        """
1913        mb = self.menuBar()
1914
1915        menu = mb.addMenu(self.tr('&File'))
1916        menu.addAction(self.newTabAct)
1917        menu.addAction(self.newAct)
1918        menu.addAction(self.newPrivateAct)
1919        menu.addAction(self.openAct)
1920        menu.addAction(self.openTabAct)
1921        menu.addSeparator()
1922        if not self.isPrivate():
1923            sessionsMenu = menu.addMenu(self.tr("Sessions"))
1924            sessionsMenu.aboutToShow.connect(
1925                lambda: self.sessionManager().aboutToShowSessionsMenu(
1926                    sessionsMenu))
1927            menu.addAction(self.showSessionsManagerAct)
1928            menu.addSeparator()
1929        if self.saveAsAct is not None:
1930            menu.addAction(self.saveAsAct)
1931        menu.addAction(self.saveVisiblePageScreenAct)
1932        menu.addSeparator()
1933        if self.printPreviewAct:
1934            menu.addAction(self.printPreviewAct)
1935        if self.printAct:
1936            menu.addAction(self.printAct)
1937        if self.printPdfAct:
1938            menu.addAction(self.printPdfAct)
1939        menu.addAction(self.sendPageLinkAct)
1940        menu.addSeparator()
1941        menu.addAction(self.closeAct)
1942        menu.addAction(self.closeAllAct)
1943        menu.addSeparator()
1944        menu.addAction(self.exitAct)
1945        self.addActions(menu.actions())
1946
1947        menu = mb.addMenu(self.tr('&Edit'))
1948        menu.addAction(self.undoAct)
1949        menu.addAction(self.redoAct)
1950        menu.addSeparator()
1951        menu.addAction(self.copyAct)
1952        menu.addAction(self.cutAct)
1953        menu.addAction(self.pasteAct)
1954        menu.addSeparator()
1955        menu.addAction(self.selectAllAct)
1956        menu.addAction(self.unselectAct)
1957        menu.addSeparator()
1958        menu.addAction(self.findAct)
1959        menu.addAction(self.findNextAct)
1960        menu.addAction(self.findPrevAct)
1961        self.addActions(menu.actions())
1962
1963        menu = mb.addMenu(self.tr('&View'))
1964        menu.addAction(self.stopAct)
1965        menu.addAction(self.reloadAct)
1966        if WebBrowserWindow._useQtHelp:
1967            menu.addSeparator()
1968            menu.addAction(self.syncTocAct)
1969        menu.addSeparator()
1970        menu.addAction(self.zoomInAct)
1971        menu.addAction(self.zoomResetAct)
1972        menu.addAction(self.zoomOutAct)
1973        menu.addSeparator()
1974        self.__textEncodingMenu = menu.addMenu(
1975            self.tr("Text Encoding"))
1976        self.__textEncodingMenu.aboutToShow.connect(
1977            self.__aboutToShowTextEncodingMenu)
1978        self.__textEncodingMenu.triggered.connect(self.__setTextEncoding)
1979        menu.addSeparator()
1980        menu.addAction(self.pageSourceAct)
1981        menu.addAction(self.fullScreenAct)
1982        self.addActions(menu.actions())
1983
1984        from .History.HistoryMenu import HistoryMenu
1985        self.historyMenu = HistoryMenu(self, self.__tabWidget)
1986        self.historyMenu.setTitle(self.tr('H&istory'))
1987        self.historyMenu.openUrl.connect(self.openUrl)
1988        self.historyMenu.newTab.connect(self.openUrlNewTab)
1989        self.historyMenu.newBackgroundTab.connect(self.openUrlNewBackgroundTab)
1990        self.historyMenu.newWindow.connect(self.openUrlNewWindow)
1991        self.historyMenu.newPrivateWindow.connect(self.openUrlNewPrivateWindow)
1992        mb.addMenu(self.historyMenu)
1993
1994        historyActions = []
1995        historyActions.append(self.backAct)
1996        historyActions.append(self.forwardAct)
1997        historyActions.append(self.homeAct)
1998        self.historyMenu.setInitialActions(historyActions)
1999        self.addActions(historyActions)
2000
2001        from .Bookmarks.BookmarksMenu import BookmarksMenuBarMenu
2002        self.bookmarksMenu = BookmarksMenuBarMenu(self)
2003        self.bookmarksMenu.setTitle(self.tr('&Bookmarks'))
2004        self.bookmarksMenu.openUrl.connect(self.openUrl)
2005        self.bookmarksMenu.newTab.connect(self.openUrlNewTab)
2006        self.bookmarksMenu.newWindow.connect(self.openUrlNewWindow)
2007        mb.addMenu(self.bookmarksMenu)
2008
2009        bookmarksActions = []
2010        bookmarksActions.append(self.bookmarksManageAct)
2011        bookmarksActions.append(self.bookmarksAddAct)
2012        bookmarksActions.append(self.bookmarksAllTabsAct)
2013        bookmarksActions.append(self.bookmarksAddFolderAct)
2014        bookmarksActions.append("--SEPARATOR--")
2015        bookmarksActions.append(self.importBookmarksAct)
2016        bookmarksActions.append(self.exportBookmarksAct)
2017        self.bookmarksMenu.setInitialActions(bookmarksActions)
2018
2019        menu = mb.addMenu(self.tr('&Settings'))
2020        menu.addAction(self.prefAct)
2021        menu.addSeparator()
2022        menu.addAction(self.shortcutsAct)
2023        menu.addAction(self.exportShortcutsAct)
2024        menu.addAction(self.importShortcutsAct)
2025        menu.addSeparator()
2026        menu.addAction(self.acceptedLanguagesAct)
2027        menu.addAction(self.cookiesAct)
2028        menu.addAction(self.personalDataAct)
2029        menu.addAction(self.greaseMonkeyAct)
2030        menu.addAction(self.featurePermissionAct)
2031        menu.addSeparator()
2032        menu.addAction(self.editMessageFilterAct)
2033        menu.addSeparator()
2034        menu.addAction(self.searchEnginesAct)
2035        menu.addSeparator()
2036        menu.addAction(self.passwordsAct)
2037        menu.addAction(self.certificateErrorsAct)
2038        menu.addSeparator()
2039        menu.addAction(self.zoomValuesAct)
2040        menu.addAction(self.manageIconsAct)
2041        menu.addSeparator()
2042        menu.addAction(self.adblockAct)
2043        menu.addSeparator()
2044        menu.addAction(self.safeBrowsingAct)
2045        menu.addSeparator()
2046        self.__settingsMenu = menu
2047        self.__settingsMenu.aboutToShow.connect(
2048            self.__aboutToShowSettingsMenu)
2049
2050        from .UserAgent.UserAgentMenu import UserAgentMenu
2051        self.__userAgentMenu = UserAgentMenu(self.tr("Global User Agent"))
2052        menu.addMenu(self.__userAgentMenu)
2053        menu.addAction(self.userAgentManagerAct)
2054        menu.addSeparator()
2055
2056        if WebBrowserWindow._useQtHelp:
2057            menu.addAction(self.manageQtHelpDocsAct)
2058            menu.addAction(self.reindexDocumentationAct)
2059            menu.addSeparator()
2060        menu.addAction(self.clearPrivateDataAct)
2061        menu.addAction(self.clearIconsAct)
2062
2063        menu = mb.addMenu(self.tr("&Tools"))
2064        menu.addAction(self.feedsManagerAct)
2065        menu.addAction(self.siteInfoAct)
2066        menu.addSeparator()
2067        menu.addAction(self.synchronizationAct)
2068        menu.addSeparator()
2069        vtMenu = menu.addMenu(UI.PixmapCache.getIcon("virustotal"),
2070                              self.tr("&VirusTotal"))
2071        vtMenu.addAction(self.virustotalScanCurrentAct)
2072        vtMenu.addAction(self.virustotalIpReportAct)
2073        vtMenu.addAction(self.virustotalDomainReportAct)
2074
2075        menu = mb.addMenu(self.tr("&Windows"))
2076        menu.addAction(self.showDownloadManagerAct)
2077        menu.addAction(self.showJavaScriptConsoleAct)
2078        menu.addAction(self.showTabManagerAct)
2079        menu.addAction(self.showProtocolHandlerManagerAct)
2080        if WebBrowserWindow._useQtHelp:
2081            menu.addSection(self.tr("QtHelp"))
2082            menu.addAction(self.showTocAct)
2083            menu.addAction(self.showIndexAct)
2084            menu.addAction(self.showSearchAct)
2085        menu.addSeparator()
2086        self.__toolbarsMenu = menu.addMenu(self.tr("&Toolbars"))
2087        self.__toolbarsMenu.aboutToShow.connect(self.__showToolbarsMenu)
2088        self.__toolbarsMenu.triggered.connect(self.__TBMenuTriggered)
2089
2090        mb.addSeparator()
2091
2092        menu = mb.addMenu(self.tr('&Help'))
2093        menu.addAction(self.aboutAct)
2094        menu.addAction(self.aboutQtAct)
2095        menu.addSeparator()
2096        menu.addAction(self.whatsThisAct)
2097        self.addActions(menu.actions())
2098
2099    def __initSuperMenu(self):
2100        """
2101        Private method to create the super menu and attach it to the super
2102        menu button.
2103        """
2104        self.__superMenu = QMenu(self)
2105
2106        self.__superMenu.addAction(self.newTabAct)
2107        self.__superMenu.addAction(self.newAct)
2108        self.__superMenu.addAction(self.newPrivateAct)
2109        self.__superMenu.addAction(self.openAct)
2110        self.__superMenu.addAction(self.openTabAct)
2111        self.__superMenu.addSeparator()
2112
2113        if not self.isPrivate():
2114            sessionsMenu = self.__superMenu.addMenu(self.tr("Sessions"))
2115            sessionsMenu.aboutToShow.connect(
2116                lambda: self.sessionManager().aboutToShowSessionsMenu(
2117                    sessionsMenu))
2118            self.__superMenu.addAction(self.showSessionsManagerAct)
2119            self.__superMenu.addSeparator()
2120
2121        menu = self.__superMenu.addMenu(self.tr("Save"))
2122        if self.saveAsAct:
2123            menu.addAction(self.saveAsAct)
2124        menu.addAction(self.saveVisiblePageScreenAct)
2125
2126        if self.printPreviewAct or self.printAct or self.printPdfAct:
2127            menu = self.__superMenu.addMenu(self.tr("Print"))
2128            if self.printPreviewAct:
2129                menu.addAction(self.printPreviewAct)
2130            if self.printAct:
2131                menu.addAction(self.printAct)
2132            if self.printPdfAct:
2133                menu.addAction(self.printPdfAct)
2134
2135        self.__superMenu.addAction(self.sendPageLinkAct)
2136        self.__superMenu.addSeparator()
2137        self.__superMenu.addAction(self.selectAllAct)
2138        self.__superMenu.addAction(self.findAct)
2139        self.__superMenu.addSeparator()
2140        act = self.__superMenu.addAction(UI.PixmapCache.getIcon("history"),
2141                                         self.tr("Show All History..."))
2142        act.triggered.connect(self.historyMenu.showHistoryDialog)
2143        self.__superMenu.addAction(self.bookmarksManageAct)
2144        self.__superMenu.addSeparator()
2145        self.__superMenu.addAction(self.prefAct)
2146
2147        menu = self.__superMenu.addMenu(self.tr('Settings'))
2148        menu.addAction(self.shortcutsAct)
2149        menu.addAction(self.exportShortcutsAct)
2150        menu.addAction(self.importShortcutsAct)
2151        menu.addSeparator()
2152        menu.addAction(self.acceptedLanguagesAct)
2153        menu.addAction(self.cookiesAct)
2154        menu.addAction(self.personalDataAct)
2155        menu.addAction(self.greaseMonkeyAct)
2156        menu.addAction(self.featurePermissionAct)
2157        menu.addSeparator()
2158        menu.addAction(self.editMessageFilterAct)
2159        menu.addSeparator()
2160        menu.addAction(self.searchEnginesAct)
2161        menu.addSeparator()
2162        menu.addAction(self.passwordsAct)
2163        menu.addAction(self.certificateErrorsAct)
2164        menu.addSeparator()
2165        menu.addAction(self.zoomValuesAct)
2166        menu.addAction(self.manageIconsAct)
2167        menu.addSeparator()
2168        menu.addAction(self.adblockAct)
2169        menu.addSeparator()
2170        menu.addAction(self.safeBrowsingAct)
2171        menu.addSeparator()
2172        menu.addMenu(self.__userAgentMenu)
2173        menu.addAction(self.userAgentManagerAct)
2174        menu.addSeparator()
2175        if WebBrowserWindow._useQtHelp:
2176            menu.addAction(self.manageQtHelpDocsAct)
2177            menu.addAction(self.reindexDocumentationAct)
2178            menu.addSeparator()
2179        menu.addAction(self.clearPrivateDataAct)
2180        menu.addAction(self.clearIconsAct)
2181        menu.aboutToShow.connect(
2182            self.__aboutToShowSettingsMenu)
2183
2184        self.__superMenu.addSeparator()
2185
2186        menu = self.__superMenu.addMenu(self.tr('&View'))
2187        menu.addMenu(self.__toolbarsMenu)
2188        windowsMenu = menu.addMenu(self.tr("&Windows"))
2189        windowsMenu.addAction(self.showDownloadManagerAct)
2190        windowsMenu.addAction(self.showJavaScriptConsoleAct)
2191        windowsMenu.addAction(self.showTabManagerAct)
2192        windowsMenu.addAction(self.showProtocolHandlerManagerAct)
2193        if WebBrowserWindow._useQtHelp:
2194            windowsMenu.addSection(self.tr("QtHelp"))
2195            windowsMenu.addAction(self.showTocAct)
2196            windowsMenu.addAction(self.showIndexAct)
2197            windowsMenu.addAction(self.showSearchAct)
2198        menu.addSeparator()
2199        menu.addAction(self.stopAct)
2200        menu.addAction(self.reloadAct)
2201        if WebBrowserWindow._useQtHelp:
2202            menu.addSeparator()
2203            menu.addAction(self.syncTocAct)
2204        menu.addSeparator()
2205        menu.addAction(self.zoomInAct)
2206        menu.addAction(self.zoomResetAct)
2207        menu.addAction(self.zoomOutAct)
2208        menu.addSeparator()
2209        menu.addMenu(self.__textEncodingMenu)
2210        menu.addSeparator()
2211        menu.addAction(self.pageSourceAct)
2212        menu.addAction(self.fullScreenAct)
2213
2214        self.__superMenu.addMenu(self.historyMenu)
2215        self.__superMenu.addMenu(self.bookmarksMenu)
2216
2217        menu = self.__superMenu.addMenu(self.tr("&Tools"))
2218        menu.addAction(self.feedsManagerAct)
2219        menu.addAction(self.siteInfoAct)
2220        menu.addSeparator()
2221        menu.addAction(self.synchronizationAct)
2222        menu.addSeparator()
2223        vtMenu = menu.addMenu(UI.PixmapCache.getIcon("virustotal"),
2224                              self.tr("&VirusTotal"))
2225        vtMenu.addAction(self.virustotalScanCurrentAct)
2226        vtMenu.addAction(self.virustotalIpReportAct)
2227        vtMenu.addAction(self.virustotalDomainReportAct)
2228
2229        self.__superMenu.addSeparator()
2230        self.__superMenu.addAction(self.aboutAct)
2231        self.__superMenu.addAction(self.aboutQtAct)
2232        self.__superMenu.addSeparator()
2233        self.__superMenu.addAction(self.exitAct)
2234
2235        self.__navigationBar.superMenuButton().setMenu(self.__superMenu)
2236
2237    def __initToolbars(self):
2238        """
2239        Private method to create the toolbars.
2240        """
2241        filetb = self.addToolBar(self.tr("File"))
2242        filetb.setObjectName("FileToolBar")
2243        filetb.setIconSize(UI.Config.ToolBarIconSize)
2244        filetb.addAction(self.newTabAct)
2245        filetb.addAction(self.newAct)
2246        filetb.addAction(self.newPrivateAct)
2247        filetb.addAction(self.openAct)
2248        filetb.addAction(self.openTabAct)
2249        filetb.addSeparator()
2250        if self.saveAsAct is not None:
2251            filetb.addAction(self.saveAsAct)
2252        filetb.addAction(self.saveVisiblePageScreenAct)
2253        filetb.addSeparator()
2254        if self.printPreviewAct:
2255            filetb.addAction(self.printPreviewAct)
2256        if self.printAct:
2257            filetb.addAction(self.printAct)
2258        if self.printPdfAct:
2259            filetb.addAction(self.printPdfAct)
2260        if self.printPreviewAct or self.printAct or self.printPdfAct:
2261            filetb.addSeparator()
2262        filetb.addAction(self.closeAct)
2263        filetb.addAction(self.exitAct)
2264        self.__toolbars["file"] = (filetb.windowTitle(), filetb)
2265
2266        edittb = self.addToolBar(self.tr("Edit"))
2267        edittb.setObjectName("EditToolBar")
2268        edittb.setIconSize(UI.Config.ToolBarIconSize)
2269        edittb.addAction(self.undoAct)
2270        edittb.addAction(self.redoAct)
2271        edittb.addSeparator()
2272        edittb.addAction(self.copyAct)
2273        edittb.addAction(self.cutAct)
2274        edittb.addAction(self.pasteAct)
2275        edittb.addSeparator()
2276        edittb.addAction(self.selectAllAct)
2277        self.__toolbars["edit"] = (edittb.windowTitle(), edittb)
2278
2279        viewtb = self.addToolBar(self.tr("View"))
2280        viewtb.setObjectName("ViewToolBar")
2281        viewtb.setIconSize(UI.Config.ToolBarIconSize)
2282        viewtb.addAction(self.zoomInAct)
2283        viewtb.addAction(self.zoomResetAct)
2284        viewtb.addAction(self.zoomOutAct)
2285        viewtb.addSeparator()
2286        viewtb.addAction(self.fullScreenAct)
2287        self.__toolbars["view"] = (viewtb.windowTitle(), viewtb)
2288
2289        findtb = self.addToolBar(self.tr("Find"))
2290        findtb.setObjectName("FindToolBar")
2291        findtb.setIconSize(UI.Config.ToolBarIconSize)
2292        findtb.addAction(self.findAct)
2293        findtb.addAction(self.findNextAct)
2294        findtb.addAction(self.findPrevAct)
2295        self.__toolbars["find"] = (findtb.windowTitle(), findtb)
2296
2297        if WebBrowserWindow._useQtHelp:
2298            filtertb = self.addToolBar(self.tr("Filter"))
2299            filtertb.setObjectName("FilterToolBar")
2300            self.filterCombo = QComboBox()
2301            try:
2302                comboWidth = QFontMetrics(QFont()).horizontalAdvance(
2303                    "ComboBoxWithEnoughWidth")
2304            except AttributeError:
2305                comboWidth = QFontMetrics(QFont()).width(
2306                    "ComboBoxWithEnoughWidth")
2307            self.filterCombo.setMinimumWidth(comboWidth)
2308            filtertb.addWidget(QLabel(self.tr("Filtered by: ")))
2309            filtertb.addWidget(self.filterCombo)
2310            self.__helpEngine.setupFinished.connect(self.__setupFilterCombo)
2311            self.filterCombo.activated[int].connect(
2312                self.__filterQtHelpDocumentation)
2313            self.__setupFilterCombo()
2314            self.__toolbars["filter"] = (filtertb.windowTitle(), filtertb)
2315
2316        settingstb = self.addToolBar(self.tr("Settings"))
2317        settingstb.setObjectName("SettingsToolBar")
2318        settingstb.setIconSize(UI.Config.ToolBarIconSize)
2319        settingstb.addAction(self.prefAct)
2320        settingstb.addAction(self.shortcutsAct)
2321        settingstb.addAction(self.acceptedLanguagesAct)
2322        settingstb.addAction(self.cookiesAct)
2323        settingstb.addAction(self.personalDataAct)
2324        settingstb.addAction(self.greaseMonkeyAct)
2325        settingstb.addAction(self.featurePermissionAct)
2326        self.__toolbars["settings"] = (settingstb.windowTitle(), settingstb)
2327
2328        toolstb = self.addToolBar(self.tr("Tools"))
2329        toolstb.setObjectName("ToolsToolBar")
2330        toolstb.setIconSize(UI.Config.ToolBarIconSize)
2331        toolstb.addAction(self.feedsManagerAct)
2332        toolstb.addAction(self.siteInfoAct)
2333        toolstb.addSeparator()
2334        toolstb.addAction(self.synchronizationAct)
2335        self.__toolbars["tools"] = (toolstb.windowTitle(), toolstb)
2336
2337        helptb = self.addToolBar(self.tr("Help"))
2338        helptb.setObjectName("HelpToolBar")
2339        helptb.setIconSize(UI.Config.ToolBarIconSize)
2340        helptb.addAction(self.whatsThisAct)
2341        self.__toolbars["help"] = (helptb.windowTitle(), helptb)
2342
2343        self.addToolBarBreak()
2344        vttb = self.addToolBar(self.tr("VirusTotal"))
2345        vttb.setObjectName("VirusTotalToolBar")
2346        vttb.setIconSize(UI.Config.ToolBarIconSize)
2347        vttb.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
2348        vttb.addAction(self.virustotalScanCurrentAct)
2349        vttb.addAction(self.virustotalIpReportAct)
2350        vttb.addAction(self.virustotalDomainReportAct)
2351        self.__toolbars["virustotal"] = (vttb.windowTitle(), vttb)
2352
2353    def __nextTab(self):
2354        """
2355        Private slot used to show the next tab.
2356        """
2357        fwidget = QApplication.focusWidget()
2358        while fwidget and not hasattr(fwidget, 'nextTab'):
2359            fwidget = fwidget.parent()
2360        if fwidget:
2361            fwidget.nextTab()
2362
2363    def __prevTab(self):
2364        """
2365        Private slot used to show the previous tab.
2366        """
2367        fwidget = QApplication.focusWidget()
2368        while fwidget and not hasattr(fwidget, 'prevTab'):
2369            fwidget = fwidget.parent()
2370        if fwidget:
2371            fwidget.prevTab()
2372
2373    def __switchTab(self):
2374        """
2375        Private slot used to switch between the current and the previous
2376        current tab.
2377        """
2378        fwidget = QApplication.focusWidget()
2379        while fwidget and not hasattr(fwidget, 'switchTab'):
2380            fwidget = fwidget.parent()
2381        if fwidget:
2382            fwidget.switchTab()
2383
2384    def __whatsThis(self):
2385        """
2386        Private slot called in to enter Whats This mode.
2387        """
2388        QWhatsThis.enterWhatsThisMode()
2389
2390    def __titleChanged(self, browser, title):
2391        """
2392        Private slot called to handle a change of a browser's title.
2393
2394        @param browser reference to the browser (WebBrowserView)
2395        @param title new title (string)
2396        """
2397        self.historyManager().updateHistoryEntry(
2398            browser.url().toString(), title)
2399
2400    @pyqtSlot()
2401    def newTab(self, link=None, addNextTo=None, background=False):
2402        """
2403        Public slot called to open a new web browser tab.
2404
2405        @param link file to be displayed in the new window (string or QUrl)
2406        @param addNextTo reference to the browser to open the tab after
2407            (WebBrowserView)
2408        @param background flag indicating to open the tab in the
2409            background (bool)
2410        @return reference to the new browser
2411        @rtype WebBrowserView
2412        """
2413        if addNextTo:
2414            return self.__tabWidget.newBrowserAfter(
2415                addNextTo, link, background=background)
2416        else:
2417            return self.__tabWidget.newBrowser(link, background=background)
2418
2419    @pyqtSlot()
2420    def newWindow(self, link=None, restoreSession=False):
2421        """
2422        Public slot called to open a new web browser window.
2423
2424        @param link URL to be displayed in the new window
2425        @type str or QUrl
2426        @param restoreSession flag indicating a restore session action
2427        @type bool
2428        @return reference to the new window
2429        @rtype WebBrowserWindow
2430        """
2431        if link is None:
2432            linkName = ""
2433        elif isinstance(link, QUrl):
2434            linkName = link.toString()
2435        else:
2436            linkName = link
2437        h = WebBrowserWindow(linkName, ".", self.parent(), "webbrowser",
2438                             private=self.isPrivate(),
2439                             restoreSession=restoreSession)
2440        h.show()
2441
2442        self.webBrowserWindowOpened.emit(h)
2443
2444        return h
2445
2446    @pyqtSlot()
2447    def newPrivateWindow(self, link=None):
2448        """
2449        Public slot called to open a new private web browser window.
2450
2451        @param link URL to be displayed in the new window
2452        @type str or QUrl
2453        """
2454        if link is None:
2455            linkName = ""
2456        elif isinstance(link, QUrl):
2457            linkName = link.toString()
2458        else:
2459            linkName = link
2460
2461        applPath = os.path.join(getConfig("ericDir"), "eric6_browser.py")
2462        args = []
2463        args.append(applPath)
2464        args.append("--config={0}".format(Utilities.getConfigDir()))
2465        if self.__settingsDir:
2466            args.append("--settings={0}".format(self.__settingsDir))
2467        args.append("--private")
2468        if linkName:
2469            args.append(linkName)
2470
2471        if (
2472            not os.path.isfile(applPath) or
2473            not QProcess.startDetached(sys.executable, args)
2474        ):
2475            E5MessageBox.critical(
2476                self,
2477                self.tr('New Private Window'),
2478                self.tr(
2479                    '<p>Could not start the process.<br>'
2480                    'Ensure that it is available as <b>{0}</b>.</p>'
2481                ).format(applPath),
2482                self.tr('OK'))
2483
2484    def __openFile(self):
2485        """
2486        Private slot called to open a file.
2487        """
2488        fn = E5FileDialog.getOpenFileName(
2489            self,
2490            self.tr("Open File"),
2491            "",
2492            self.tr("HTML Files (*.html *.htm *.mhtml *.mht);;"
2493                    "PDF Files (*.pdf);;"
2494                    "CHM Files (*.chm);;"
2495                    "All Files (*)"
2496                    ))
2497        if fn:
2498            if Utilities.isWindowsPlatform():
2499                url = "file:///" + Utilities.fromNativeSeparators(fn)
2500            else:
2501                url = "file://" + fn
2502            self.currentBrowser().setSource(QUrl(url))
2503
2504    def __openFileNewTab(self):
2505        """
2506        Private slot called to open a file in a new tab.
2507        """
2508        fn = E5FileDialog.getOpenFileName(
2509            self,
2510            self.tr("Open File"),
2511            "",
2512            self.tr("HTML Files (*.html *.htm *.mhtml *.mht);;"
2513                    "PDF Files (*.pdf);;"
2514                    "CHM Files (*.chm);;"
2515                    "All Files (*)"
2516                    ))
2517        if fn:
2518            if Utilities.isWindowsPlatform():
2519                url = "file:///" + Utilities.fromNativeSeparators(fn)
2520            else:
2521                url = "file://" + fn
2522            self.newTab(url)
2523
2524    def __savePageAs(self):
2525        """
2526        Private slot to save the current page.
2527        """
2528        browser = self.currentBrowser()
2529        if browser is not None:
2530            browser.saveAs()
2531
2532    @pyqtSlot()
2533    def __saveVisiblePageScreen(self):
2534        """
2535        Private slot to save the visible part of the current page as a screen
2536        shot.
2537        """
2538        from .PageScreenDialog import PageScreenDialog
2539        self.__pageScreen = PageScreenDialog(self.currentBrowser())
2540        self.__pageScreen.show()
2541
2542    def __about(self):
2543        """
2544        Private slot to show the about information.
2545        """
2546        chromeVersion, webengineVersion = (
2547            WebBrowserTools.getWebEngineVersions()
2548        )
2549        E5MessageBox.about(
2550            self,
2551            self.tr("eric Web Browser"),
2552            self.tr(
2553                """<b>eric Web Browser - {0}</b>"""
2554                """<p>The eric Web Browser is a combined help file and HTML"""
2555                """ browser. It is part of the eric development"""
2556                """ toolset.</p>"""
2557                """<p>It is based on QtWebEngine {1} and Chrome {2}.</p>"""
2558            ).format(Version, webengineVersion, chromeVersion))
2559
2560    def __aboutQt(self):
2561        """
2562        Private slot to show info about Qt.
2563        """
2564        E5MessageBox.aboutQt(self, self.tr("eric Web Browser"))
2565
2566    def setBackwardAvailable(self, b):
2567        """
2568        Public slot called when backward references are available.
2569
2570        @param b flag indicating availability of the backwards action (boolean)
2571        """
2572        self.backAct.setEnabled(b)
2573        self.__navigationBar.backButton().setEnabled(b)
2574
2575    def setForwardAvailable(self, b):
2576        """
2577        Public slot called when forward references are available.
2578
2579        @param b flag indicating the availability of the forwards action
2580            (boolean)
2581        """
2582        self.forwardAct.setEnabled(b)
2583        self.__navigationBar.forwardButton().setEnabled(b)
2584
2585    def setLoadingActions(self, b):
2586        """
2587        Public slot to set the loading dependent actions.
2588
2589        @param b flag indicating the loading state to consider (boolean)
2590        """
2591        self.reloadAct.setEnabled(not b)
2592        self.stopAct.setEnabled(b)
2593
2594        self.__navigationBar.reloadStopButton().setLoading(b)
2595
2596    def __addBookmark(self):
2597        """
2598        Private slot called to add the displayed file to the bookmarks.
2599        """
2600        from .WebBrowserPage import WebBrowserPage
2601
2602        view = self.currentBrowser()
2603        view.addBookmark()
2604        urlStr = bytes(view.url().toEncoded()).decode()
2605        title = view.title()
2606
2607        script = Scripts.getAllMetaAttributes()
2608        view.page().runJavaScript(
2609            script,
2610            WebBrowserPage.SafeJsWorld,
2611            lambda res: self.__addBookmarkCallback(urlStr, title, res))
2612
2613    def __addBookmarkCallback(self, url, title, res):
2614        """
2615        Private callback method of __addBookmark().
2616
2617        @param url URL for the bookmark
2618        @type str
2619        @param title title for the bookmark
2620        @type str
2621        @param res result of the JavaScript
2622        @type list
2623        """
2624        description = ""
2625        for meta in res:
2626            if meta["name"] == "description":
2627                description = meta["content"]
2628
2629        from .Bookmarks.AddBookmarkDialog import AddBookmarkDialog
2630        dlg = AddBookmarkDialog()
2631        dlg.setUrl(url)
2632        dlg.setTitle(title)
2633        dlg.setDescription(description)
2634        menu = self.bookmarksManager().menu()
2635        idx = self.bookmarksManager().bookmarksModel().nodeIndex(menu)
2636        dlg.setCurrentIndex(idx)
2637        dlg.exec()
2638
2639    def __addBookmarkFolder(self):
2640        """
2641        Private slot to add a new bookmarks folder.
2642        """
2643        from .Bookmarks.AddBookmarkDialog import AddBookmarkDialog
2644        dlg = AddBookmarkDialog()
2645        menu = self.bookmarksManager().menu()
2646        idx = self.bookmarksManager().bookmarksModel().nodeIndex(menu)
2647        dlg.setCurrentIndex(idx)
2648        dlg.setFolder(True)
2649        dlg.exec()
2650
2651    def __showBookmarksDialog(self):
2652        """
2653        Private slot to show the bookmarks dialog.
2654        """
2655        from .Bookmarks.BookmarksDialog import BookmarksDialog
2656        self.__bookmarksDialog = BookmarksDialog(self)
2657        self.__bookmarksDialog.openUrl.connect(self.openUrl)
2658        self.__bookmarksDialog.newTab.connect(self.openUrlNewTab)
2659        self.__bookmarksDialog.newBackgroundTab.connect(
2660            self.openUrlNewBackgroundTab)
2661        self.__bookmarksDialog.show()
2662
2663    def bookmarkAll(self):
2664        """
2665        Public slot to bookmark all open tabs.
2666        """
2667        from .WebBrowserPage import WebBrowserPage
2668        from .Bookmarks.AddBookmarkDialog import AddBookmarkDialog
2669
2670        dlg = AddBookmarkDialog()
2671        dlg.setFolder(True)
2672        dlg.setTitle(self.tr("Saved Tabs"))
2673        dlg.exec()
2674
2675        folder = dlg.addedNode()
2676        if folder is None:
2677            return
2678
2679        for view in self.__tabWidget.browsers():
2680            urlStr = bytes(view.url().toEncoded()).decode()
2681            title = view.title()
2682
2683            script = Scripts.getAllMetaAttributes()
2684            view.page().runJavaScript(
2685                script,
2686                WebBrowserPage.SafeJsWorld,
2687                functools.partial(self.__bookmarkAllCallback,
2688                                  folder, urlStr, title))
2689
2690    def __bookmarkAllCallback(self, folder, url, title, res):
2691        """
2692        Private callback method of __addBookmark().
2693
2694        @param folder reference to the bookmarks folder
2695        @type BookmarkNode
2696        @param url URL for the bookmark
2697        @type str
2698        @param title title for the bookmark
2699        @type str
2700        @param res result of the JavaScript
2701        @type list
2702        """
2703        description = ""
2704        for meta in res:
2705            if meta["name"] == "description":
2706                description = meta["content"]
2707
2708        from .Bookmarks.BookmarkNode import BookmarkNode
2709        bookmark = BookmarkNode(BookmarkNode.Bookmark)
2710        bookmark.url = url
2711        bookmark.title = title
2712        bookmark.desc = description
2713
2714        self.bookmarksManager().addBookmark(folder, bookmark)
2715
2716    def __find(self):
2717        """
2718        Private slot to handle the find action.
2719
2720        It opens the search dialog in order to perform the various
2721        search actions and to collect the various search info.
2722        """
2723        self.__searchWidget.showFind()
2724
2725    def forceClose(self):
2726        """
2727        Public method to force closing the window.
2728        """
2729        self.__forcedClose = True
2730        self.close()
2731
2732    def closeEvent(self, e):
2733        """
2734        Protected event handler for the close event.
2735
2736        @param e the close event (QCloseEvent)
2737            <br />This event is simply accepted after the history has been
2738            saved and all window references have been deleted.
2739        """
2740        res = self.__shutdownWindow()
2741
2742        if res:
2743            e.accept()
2744            self.webBrowserWindowClosed.emit(self)
2745        else:
2746            e.ignore()
2747
2748    def isClosing(self):
2749        """
2750        Public method to test, if the window is closing.
2751
2752        @return flag indicating that the window is closing
2753        @rtype bool
2754        """
2755        return self.__isClosing
2756
2757    def __shutdownWindow(self):
2758        """
2759        Private method to shut down a web browser window.
2760
2761        @return flag indicating successful shutdown (boolean)
2762        """
2763        if (
2764            not WebBrowserWindow._performingShutdown and
2765            not self.__forcedClose and
2766            not self.__tabWidget.shallShutDown()
2767        ):
2768            return False
2769
2770        self.__isClosing = True
2771
2772        if (
2773            not WebBrowserWindow._performingShutdown and
2774            len(WebBrowserWindow.BrowserWindows) == 1 and
2775            not WebBrowserWindow.isPrivate()
2776        ):
2777            # shut down the session manager in case the last window is
2778            # about to be closed
2779            self.sessionManager().shutdown()
2780
2781        self.__bookmarksToolBar.setModel(None)
2782
2783        self.__virusTotal.close()
2784
2785        self.__navigationBar.searchEdit().openSearchManager().close()
2786
2787        if WebBrowserWindow._useQtHelp:
2788            self.__searchEngine.cancelIndexing()
2789            self.__searchEngine.cancelSearching()
2790
2791            if self.__helpInstaller:
2792                self.__helpInstaller.stop()
2793
2794        self.__navigationBar.searchEdit().saveSearches()
2795
2796        self.__tabWidget.closeAllBrowsers(shutdown=True)
2797
2798        state = self.saveState()
2799        Preferences.setWebBrowser("WebBrowserState", state)
2800
2801        if Preferences.getWebBrowser("SaveGeometry"):
2802            if not self.isFullScreen():
2803                Preferences.setGeometry("WebBrowserGeometry",
2804                                        self.saveGeometry())
2805        else:
2806            Preferences.setGeometry("WebBrowserGeometry", QByteArray())
2807
2808        with contextlib.suppress(ValueError):
2809            browserIndex = WebBrowserWindow.BrowserWindows.index(self)
2810            if len(WebBrowserWindow.BrowserWindows) and browserIndex == 0:
2811                if len(WebBrowserWindow.BrowserWindows) > 1:
2812                    # first window will be deleted
2813                    QDesktopServices.setUrlHandler(
2814                        "http",
2815                        WebBrowserWindow.BrowserWindows[1].urlHandler)
2816                    QDesktopServices.setUrlHandler(
2817                        "https",
2818                        WebBrowserWindow.BrowserWindows[1].urlHandler)
2819                else:
2820                    QDesktopServices.unsetUrlHandler("http")
2821                    QDesktopServices.unsetUrlHandler("https")
2822            if len(WebBrowserWindow.BrowserWindows) > 0:
2823                del WebBrowserWindow.BrowserWindows[browserIndex]
2824
2825        Preferences.syncPreferences()
2826        if (
2827            not WebBrowserWindow._performingShutdown and
2828            len(WebBrowserWindow.BrowserWindows) == 0
2829        ):
2830            # shut down the browser in case the last window was
2831            # simply closed
2832            self.shutdown()
2833
2834        return True
2835
2836    def __shallShutDown(self):
2837        """
2838        Private method to check, if the application should be shut down.
2839
2840        @return flag indicating a shut down
2841        @rtype bool
2842        """
2843        if Preferences.getWebBrowser("WarnOnMultipleClose"):
2844            windowCount = len(WebBrowserWindow.BrowserWindows)
2845            tabCount = 0
2846            for browser in WebBrowserWindow.BrowserWindows:
2847                tabCount += browser.tabWidget().count()
2848
2849            if windowCount > 1 or tabCount > 1:
2850                mb = E5MessageBox.E5MessageBox(
2851                    E5MessageBox.Information,
2852                    self.tr("Are you sure you want to close the web browser?"),
2853                    self.tr("""Are you sure you want to close the web"""
2854                            """ browser?\n"""
2855                            """You have {0} windows with {1} tabs open.""")
2856                    .format(windowCount, tabCount),
2857                    modal=True,
2858                    parent=self)
2859                quitButton = mb.addButton(
2860                    self.tr("&Quit"), E5MessageBox.AcceptRole)
2861                quitButton.setIcon(UI.PixmapCache.getIcon("exit"))
2862                mb.addButton(E5MessageBox.Cancel)
2863                mb.exec()
2864                return mb.clickedButton() == quitButton
2865
2866        return True
2867
2868    def shutdown(self):
2869        """
2870        Public method to shut down the web browser.
2871
2872        @return flag indicating successful shutdown (boolean)
2873        """
2874        if not self.__shallShutDown():
2875            return False
2876
2877        if (
2878            WebBrowserWindow._downloadManager is not None and
2879            not self.downloadManager().allowQuit()
2880        ):
2881            return False
2882
2883        WebBrowserWindow._performingShutdown = True
2884
2885        if not WebBrowserWindow.isPrivate():
2886            self.sessionManager().shutdown()
2887
2888        if WebBrowserWindow._downloadManager is not None:
2889            self.downloadManager().shutdown()
2890
2891        self.cookieJar().close()
2892
2893        self.bookmarksManager().close()
2894
2895        self.historyManager().close()
2896
2897        self.passwordManager().close()
2898
2899        self.adBlockManager().close()
2900
2901        self.userAgentsManager().close()
2902
2903        self.speedDial().close()
2904
2905        self.syncManager().close()
2906
2907        ZoomManager.instance().close()
2908
2909        WebIconProvider.instance().close()
2910
2911        if len(WebBrowserWindow.BrowserWindows) == 1:
2912            # it is the last window
2913            self.tabManager().close()
2914
2915        self.networkManager().shutdown()
2916
2917        if WebBrowserWindow._safeBrowsingManager:
2918            self.safeBrowsingManager().close()
2919
2920        for browser in WebBrowserWindow.BrowserWindows:
2921            if browser != self:
2922                browser.close()
2923        self.close()
2924
2925        return True
2926
2927    def __backward(self):
2928        """
2929        Private slot called to handle the backward action.
2930        """
2931        self.currentBrowser().backward()
2932
2933    def __forward(self):
2934        """
2935        Private slot called to handle the forward action.
2936        """
2937        self.currentBrowser().forward()
2938
2939    def __home(self):
2940        """
2941        Private slot called to handle the home action.
2942        """
2943        self.currentBrowser().home()
2944
2945    def __reload(self):
2946        """
2947        Private slot called to handle the reload action.
2948        """
2949        self.currentBrowser().reloadBypassingCache()
2950
2951    def __stopLoading(self):
2952        """
2953        Private slot called to handle loading of the current page.
2954        """
2955        self.currentBrowser().stop()
2956
2957    def __zoomValueChanged(self, value):
2958        """
2959        Private slot to handle value changes of the zoom widget.
2960
2961        @param value zoom value (integer)
2962        """
2963        self.currentBrowser().setZoomValue(value)
2964
2965    def __zoomIn(self):
2966        """
2967        Private slot called to handle the zoom in action.
2968        """
2969        self.currentBrowser().zoomIn()
2970        self.__zoomWidget.setValue(self.currentBrowser().zoomValue())
2971
2972    def __zoomOut(self):
2973        """
2974        Private slot called to handle the zoom out action.
2975        """
2976        self.currentBrowser().zoomOut()
2977        self.__zoomWidget.setValue(self.currentBrowser().zoomValue())
2978
2979    def __zoomReset(self):
2980        """
2981        Private slot called to handle the zoom reset action.
2982        """
2983        self.currentBrowser().zoomReset()
2984        self.__zoomWidget.setValue(self.currentBrowser().zoomValue())
2985
2986    def toggleFullScreen(self):
2987        """
2988        Public slot called to toggle the full screen mode.
2989        """
2990        if self.__htmlFullScreen:
2991            self.currentBrowser().triggerPageAction(
2992                QWebEnginePage.WebAction.ExitFullScreen)
2993            return
2994
2995        if self.isFullScreen():
2996            # switch back to normal
2997            self.showNormal()
2998        else:
2999            # switch to full screen
3000            self.showFullScreen()
3001
3002    def enterHtmlFullScreen(self):
3003        """
3004        Public method to switch to full screen initiated by the
3005        HTML page.
3006        """
3007        self.showFullScreen()
3008        self.__htmlFullScreen = True
3009
3010    def isFullScreenNavigationVisible(self):
3011        """
3012        Public method to check, if full screen navigation is active.
3013
3014        @return flag indicating visibility of the navigation container in full
3015            screen mode
3016        @rtype bool
3017        """
3018        return self.isFullScreen() and self.__navigationContainer.isVisible()
3019
3020    def showFullScreenNavigation(self):
3021        """
3022        Public slot to show full screen navigation.
3023        """
3024        if self.__htmlFullScreen:
3025            return
3026
3027        if self.__hideNavigationTimer.isActive():
3028            self.__hideNavigationTimer.stop()
3029
3030        self.__navigationContainer.show()
3031        self.__tabWidget.tabBar().show()
3032
3033    def hideFullScreenNavigation(self):
3034        """
3035        Public slot to hide full screen navigation.
3036        """
3037        if not self.__hideNavigationTimer.isActive():
3038            self.__hideNavigationTimer.start()
3039
3040    def __hideNavigation(self):
3041        """
3042        Private slot to hide full screen navigation by timer.
3043        """
3044        browser = self.currentBrowser()
3045        mouseInBrowser = browser and browser.underMouse()
3046
3047        if self.isFullScreen() and mouseInBrowser:
3048            self.__navigationContainer.hide()
3049            self.__tabWidget.tabBar().hide()
3050
3051    def __copy(self):
3052        """
3053        Private slot called to handle the copy action.
3054        """
3055        self.currentBrowser().copy()
3056
3057    def __cut(self):
3058        """
3059        Private slot called to handle the cut action.
3060        """
3061        self.currentBrowser().cut()
3062
3063    def __paste(self):
3064        """
3065        Private slot called to handle the paste action.
3066        """
3067        self.currentBrowser().paste()
3068
3069    def __undo(self):
3070        """
3071        Private slot to handle the undo action.
3072        """
3073        self.currentBrowser().undo()
3074
3075    def __redo(self):
3076        """
3077        Private slot to handle the redo action.
3078        """
3079        self.currentBrowser().redo()
3080
3081    def __selectAll(self):
3082        """
3083        Private slot to handle the select all action.
3084        """
3085        self.currentBrowser().selectAll()
3086
3087    def __unselect(self):
3088        """
3089        Private slot to clear the selection of the current browser.
3090        """
3091        self.currentBrowser().unselect()
3092
3093    @classmethod
3094    def isPrivate(cls):
3095        """
3096        Class method to check the private browsing mode.
3097
3098        @return flag indicating private browsing mode
3099        @rtype bool
3100        """
3101        return cls._isPrivate
3102
3103    def closeCurrentBrowser(self):
3104        """
3105        Public method to close the current web browser.
3106        """
3107        self.__tabWidget.closeBrowser()
3108
3109    def closeBrowser(self, browser):
3110        """
3111        Public method to close the given browser.
3112
3113        @param browser reference to the web browser view to be closed
3114        @type WebBrowserView
3115        """
3116        self.__tabWidget.closeBrowserView(browser)
3117
3118    def currentBrowser(self):
3119        """
3120        Public method to get a reference to the current web browser.
3121
3122        @return reference to the current help browser (WebBrowserView)
3123        """
3124        return self.__tabWidget.currentBrowser()
3125
3126    def browserAt(self, index):
3127        """
3128        Public method to get a reference to the web browser with the given
3129        index.
3130
3131        @param index index of the browser to get (integer)
3132        @return reference to the indexed web browser (WebBrowserView)
3133        """
3134        return self.__tabWidget.browserAt(index)
3135
3136    def browsers(self):
3137        """
3138        Public method to get a list of references to all web browsers.
3139
3140        @return list of references to web browsers (list of WebBrowserView)
3141        """
3142        return self.__tabWidget.browsers()
3143
3144    def __currentChanged(self, index):
3145        """
3146        Private slot to handle the currentChanged signal.
3147
3148        @param index index of the current tab (integer)
3149        """
3150        if index > -1:
3151            cb = self.currentBrowser()
3152            if cb is not None:
3153                self.setForwardAvailable(cb.isForwardAvailable())
3154                self.setBackwardAvailable(cb.isBackwardAvailable())
3155                self.setLoadingActions(cb.isLoading())
3156
3157                # set value of zoom widget
3158                self.__zoomWidget.setValue(cb.zoomValue())
3159
3160    def __showPreferences(self):
3161        """
3162        Private slot to set the preferences.
3163        """
3164        from Preferences.ConfigurationDialog import (
3165            ConfigurationDialog, ConfigurationMode
3166        )
3167        dlg = ConfigurationDialog(
3168            self, 'Configuration', True, fromEric=False,
3169            displayMode=ConfigurationMode.WEBBROWSERMODE)
3170        dlg.preferencesChanged.connect(self.preferencesChanged)
3171        dlg.masterPasswordChanged.connect(
3172            lambda old, new: self.masterPasswordChanged(old, new, local=True))
3173        dlg.show()
3174        if self.__lastConfigurationPageName:
3175            dlg.showConfigurationPageByName(self.__lastConfigurationPageName)
3176        else:
3177            dlg.showConfigurationPageByName("empty")
3178        dlg.exec()
3179        QApplication.processEvents()
3180        if dlg.result() == QDialog.DialogCode.Accepted:
3181            dlg.setPreferences()
3182            Preferences.syncPreferences()
3183            self.preferencesChanged()
3184        self.__lastConfigurationPageName = dlg.getConfigurationPageName()
3185
3186    def preferencesChanged(self):
3187        """
3188        Public slot to handle a change of preferences.
3189        """
3190        self.setStyle(Preferences.getUI("Style"),
3191                      Preferences.getUI("StyleSheet"))
3192
3193        self.__initWebEngineSettings()
3194
3195        self.networkManager().preferencesChanged()
3196
3197        self.historyManager().preferencesChanged()
3198
3199        self.__tabWidget.preferencesChanged()
3200
3201        self.__navigationBar.searchEdit().preferencesChanged()
3202
3203        self.autoScroller().preferencesChanged()
3204
3205        profile = self.webProfile()
3206        if not self.isPrivate():
3207            if Preferences.getWebBrowser("DiskCacheEnabled"):
3208                profile.setHttpCacheType(
3209                    QWebEngineProfile.HttpCacheType.DiskHttpCache)
3210                profile.setHttpCacheMaximumSize(
3211                    Preferences.getWebBrowser("DiskCacheSize") * 1024 * 1024)
3212            else:
3213                profile.setHttpCacheType(
3214                    QWebEngineProfile.HttpCacheType.MemoryHttpCache)
3215                profile.setHttpCacheMaximumSize(0)
3216
3217        with contextlib.suppress(AttributeError):
3218            profile.setSpellCheckEnabled(
3219                Preferences.getWebBrowser("SpellCheckEnabled"))
3220            profile.setSpellCheckLanguages(
3221                Preferences.getWebBrowser("SpellCheckLanguages"))
3222
3223        self.__virusTotal.preferencesChanged()
3224        if (
3225            not Preferences.getWebBrowser("VirusTotalEnabled") or
3226            Preferences.getWebBrowser("VirusTotalServiceKey") == ""
3227        ):
3228            self.virustotalScanCurrentAct.setEnabled(False)
3229            self.virustotalIpReportAct.setEnabled(False)
3230            self.virustotalDomainReportAct.setEnabled(False)
3231        else:
3232            self.virustotalScanCurrentAct.setEnabled(True)
3233            self.virustotalIpReportAct.setEnabled(True)
3234            self.virustotalDomainReportAct.setEnabled(True)
3235
3236        self.__javaScriptIcon.preferencesChanged()
3237
3238        if not WebBrowserWindow.isPrivate():
3239            self.sessionManager().preferencesChanged()
3240
3241    def masterPasswordChanged(self, oldPassword, newPassword, local=False):
3242        """
3243        Public slot to handle the change of the master password.
3244
3245        @param oldPassword current master password
3246        @type str
3247        @param newPassword new master password
3248        @type str
3249        @param local flag indicating being called from the local configuration
3250            dialog
3251        @type bool
3252        """
3253        self.passwordManager().masterPasswordChanged(oldPassword, newPassword)
3254        if local:
3255            # we were called from our local configuration dialog
3256            Preferences.convertPasswords(oldPassword, newPassword)
3257            Utilities.crypto.changeRememberedMaster(newPassword)
3258
3259    def __showAcceptedLanguages(self):
3260        """
3261        Private slot to configure the accepted languages for web pages.
3262        """
3263        from .WebBrowserLanguagesDialog import WebBrowserLanguagesDialog
3264        dlg = WebBrowserLanguagesDialog(self)
3265        dlg.exec()
3266        self.networkManager().languagesChanged()
3267
3268    def __showCookiesConfiguration(self):
3269        """
3270        Private slot to configure the cookies handling.
3271        """
3272        from .CookieJar.CookiesConfigurationDialog import (
3273            CookiesConfigurationDialog
3274        )
3275        dlg = CookiesConfigurationDialog(self)
3276        dlg.exec()
3277
3278    @classmethod
3279    def setUseQtHelp(cls, use):
3280        """
3281        Class method to set the QtHelp usage.
3282
3283        @param use flag indicating usage (boolean)
3284        """
3285        if use:
3286            cls._useQtHelp = use and QTHELP_AVAILABLE
3287        else:
3288            cls._useQtHelp = False
3289
3290    @classmethod
3291    def helpEngine(cls):
3292        """
3293        Class method to get a reference to the help engine.
3294
3295        @return reference to the help engine (QHelpEngine)
3296        """
3297        if cls._useQtHelp:
3298            if cls._helpEngine is None:
3299                cls._helpEngine = QHelpEngine(
3300                    WebBrowserWindow.getQtHelpCollectionFileName())
3301            return cls._helpEngine
3302        else:
3303            return None
3304
3305    @classmethod
3306    def getQtHelpCollectionFileName(cls):
3307        """
3308        Class method to determine the name of the QtHelp collection file.
3309
3310        @return path of the QtHelp collection file
3311        @rtype str
3312        """
3313        qthelpDir = os.path.join(Utilities.getConfigDir(), "qthelp")
3314        if not os.path.exists(qthelpDir):
3315            os.makedirs(qthelpDir)
3316        return os.path.join(qthelpDir, "eric6help.qhc")
3317
3318    @classmethod
3319    def networkManager(cls):
3320        """
3321        Class method to get a reference to the network manager object.
3322
3323        @return reference to the network access manager (NetworkManager)
3324        """
3325        if cls._networkManager is None:
3326            from .Network.NetworkManager import NetworkManager
3327            cls._networkManager = NetworkManager(cls.helpEngine())
3328
3329        return cls._networkManager
3330
3331    @classmethod
3332    def cookieJar(cls):
3333        """
3334        Class method to get a reference to the cookie jar.
3335
3336        @return reference to the cookie jar (CookieJar)
3337        """
3338        if cls._cookieJar is None:
3339            from .CookieJar.CookieJar import CookieJar
3340            cls._cookieJar = CookieJar()
3341
3342        return cls._cookieJar
3343
3344    def __clearIconsDatabase(self):
3345        """
3346        Private slot to clear the favicons databse.
3347        """
3348        WebIconProvider.instance().clear()
3349
3350    def __showWebIconsDialog(self):
3351        """
3352        Private slot to show a dialog to manage the favicons database.
3353        """
3354        WebIconProvider.instance().showWebIconDialog()
3355
3356    @pyqtSlot(QUrl)
3357    def urlHandler(self, url):
3358        """
3359        Public slot used as desktop URL handler.
3360
3361        @param url URL to be handled
3362        @type QUrl
3363        """
3364        self.__linkActivated(url)
3365
3366    @pyqtSlot(QUrl)
3367    def __linkActivated(self, url):
3368        """
3369        Private slot to handle the selection of a link.
3370
3371        @param url URL to be shown
3372        @type QUrl
3373        """
3374        if not self.__activating:
3375            self.__activating = True
3376            cb = self.currentBrowser()
3377            if cb is None:
3378                self.newTab(url)
3379            else:
3380                cb.setUrl(url)
3381            self.__activating = False
3382
3383    def __activateCurrentBrowser(self):
3384        """
3385        Private slot to activate the current browser.
3386        """
3387        self.currentBrowser().setFocus()
3388
3389    def __syncTOC(self):
3390        """
3391        Private slot to synchronize the TOC with the currently shown page.
3392        """
3393        if WebBrowserWindow._useQtHelp:
3394            with E5OverrideCursor():
3395                url = self.currentBrowser().source()
3396                self.__showTocWindow()
3397                if not self.__tocWindow.syncToContent(url):
3398                    self.statusBar().showMessage(
3399                        self.tr("Could not find an associated content."), 5000)
3400
3401    def __showTocWindow(self):
3402        """
3403        Private method to show the table of contents window.
3404        """
3405        if WebBrowserWindow._useQtHelp:
3406            self.__activateDock(self.__tocWindow)
3407
3408    def __showIndexWindow(self):
3409        """
3410        Private method to show the index window.
3411        """
3412        if WebBrowserWindow._useQtHelp:
3413            self.__activateDock(self.__indexWindow)
3414
3415    def __showSearchWindow(self):
3416        """
3417        Private method to show the search window.
3418        """
3419        if WebBrowserWindow._useQtHelp:
3420            self.__activateDock(self.__searchWindow)
3421
3422    def __activateDock(self, widget):
3423        """
3424        Private method to activate the dock widget of the given widget.
3425
3426        @param widget reference to the widget to be activated (QWidget)
3427        """
3428        widget.parent().show()
3429        widget.parent().raise_()
3430        widget.setFocus()
3431
3432    def __setupFilterCombo(self):
3433        """
3434        Private slot to setup the filter combo box.
3435        """
3436        if WebBrowserWindow._useQtHelp:
3437            curFilter = self.filterCombo.currentText()
3438            if not curFilter:
3439                curFilter = self.__helpEngine.currentFilter()
3440            self.filterCombo.clear()
3441            self.filterCombo.addItems(self.__helpEngine.customFilters())
3442            idx = self.filterCombo.findText(curFilter)
3443            if idx < 0:
3444                idx = 0
3445            self.filterCombo.setCurrentIndex(idx)
3446
3447    def __filterQtHelpDocumentation(self, index):
3448        """
3449        Private slot to filter the QtHelp documentation.
3450
3451        @param index index of the selected entry
3452        @type int
3453        """
3454        customFilter = self.filterCombo.itemText(index)
3455        if self.__helpEngine:
3456            self.__helpEngine.setCurrentFilter(customFilter)
3457
3458    def __manageQtHelpDocumentation(self):
3459        """
3460        Private slot to manage the QtHelp documentation database.
3461        """
3462        if WebBrowserWindow._useQtHelp:
3463            from .QtHelp.QtHelpDocumentationDialog import (
3464                QtHelpDocumentationDialog
3465            )
3466            dlg = QtHelpDocumentationDialog(self.__helpEngine, self)
3467            dlg.exec()
3468            if dlg.hasDocumentationChanges():
3469                for i in sorted(dlg.getTabsToClose(), reverse=True):
3470                    self.__tabWidget.closeBrowserAt(i)
3471                self.__searchEngine.reindexDocumentation()
3472
3473    def getSourceFileList(self):
3474        """
3475        Public method to get a list of all opened source files.
3476
3477        @return dictionary with tab id as key and host/namespace as value
3478        """
3479        return self.__tabWidget.getSourceFileList()
3480
3481    def __indexingStarted(self):
3482        """
3483        Private slot to handle the start of the indexing process.
3484        """
3485        if WebBrowserWindow._useQtHelp:
3486            self.__indexing = True
3487            if self.__indexingProgress is None:
3488                self.__indexingProgress = QWidget()
3489                layout = QHBoxLayout(self.__indexingProgress)
3490                layout.setContentsMargins(0, 0, 0, 0)
3491                sizePolicy = QSizePolicy(QSizePolicy.Policy.Preferred,
3492                                         QSizePolicy.Policy.Maximum)
3493
3494                label = QLabel(self.tr("Updating search index"))
3495                label.setSizePolicy(sizePolicy)
3496                layout.addWidget(label)
3497
3498                progressBar = QProgressBar()
3499                progressBar.setRange(0, 0)
3500                progressBar.setTextVisible(False)
3501                progressBar.setFixedHeight(16)
3502                progressBar.setSizePolicy(sizePolicy)
3503                layout.addWidget(progressBar)
3504
3505                self.statusBar().insertPermanentWidget(
3506                    0, self.__indexingProgress)
3507
3508    def __indexingFinished(self):
3509        """
3510        Private slot to handle the start of the indexing process.
3511        """
3512        if WebBrowserWindow._useQtHelp:
3513            self.statusBar().removeWidget(self.__indexingProgress)
3514            self.__indexingProgress = None
3515            self.__indexing = False
3516            if self.__searchWord is not None:
3517                self.__searchForWord()
3518
3519    def __searchForWord(self):
3520        """
3521        Private slot to search for a word.
3522        """
3523        if (
3524            WebBrowserWindow._useQtHelp and
3525            not self.__indexing and
3526            self.__searchWord is not None
3527        ):
3528            self.__searchDock.show()
3529            self.__searchDock.raise_()
3530            query = QHelpSearchQuery(QHelpSearchQuery.FieldName.DEFAULT,
3531                                     [self.__searchWord])
3532            self.__searchEngine.search([query])
3533            self.__searchWord = None
3534
3535    def search(self, word):
3536        """
3537        Public method to search for a word.
3538
3539        @param word word to search for (string)
3540        """
3541        if WebBrowserWindow._useQtHelp:
3542            self.__searchWord = word
3543            self.__searchForWord()
3544
3545    def __removeOldDocumentation(self):
3546        """
3547        Private slot to remove non-existing documentation from the help engine.
3548        """
3549        if WebBrowserWindow._useQtHelp:
3550            for namespace in self.__helpEngine.registeredDocumentations():
3551                docFile = self.__helpEngine.documentationFileName(namespace)
3552                if not os.path.exists(docFile):
3553                    self.__helpEngine.unregisterDocumentation(namespace)
3554
3555    def __lookForNewDocumentation(self):
3556        """
3557        Private slot to look for new documentation to be loaded into the
3558        help database.
3559        """
3560        if WebBrowserWindow._useQtHelp:
3561            from .QtHelp.HelpDocsInstaller import HelpDocsInstaller
3562            self.__helpInstaller = HelpDocsInstaller(
3563                self.__helpEngine.collectionFile())
3564            self.__helpInstaller.errorMessage.connect(
3565                self.__showInstallationError)
3566            self.__helpInstaller.docsInstalled.connect(self.__docsInstalled)
3567
3568            self.statusBar().showMessage(
3569                self.tr("Looking for Documentation..."))
3570            self.__helpInstaller.installDocs()
3571
3572    def __showInstallationError(self, message):
3573        """
3574        Private slot to show installation errors.
3575
3576        @param message message to be shown (string)
3577        """
3578        E5MessageBox.warning(
3579            self,
3580            self.tr("eric Web Browser"),
3581            message)
3582
3583    def __docsInstalled(self, installed):
3584        """
3585        Private slot handling the end of documentation installation.
3586
3587        @param installed flag indicating that documents were installed
3588            (boolean)
3589        """
3590        if WebBrowserWindow._useQtHelp:
3591            self.statusBar().clearMessage()
3592
3593    def __initHelpDb(self):
3594        """
3595        Private slot to initialize the documentation database.
3596        """
3597        if WebBrowserWindow._useQtHelp:
3598            unfiltered = self.tr("Unfiltered")
3599            if unfiltered not in self.__helpEngine.customFilters():
3600                hc = QHelpEngineCore(self.__helpEngine.collectionFile())
3601                hc.addCustomFilter(unfiltered, [])
3602                hc = None
3603                del hc
3604
3605                self.__helpEngine.blockSignals(True)
3606                self.__helpEngine.setCurrentFilter(unfiltered)
3607                self.__helpEngine.blockSignals(False)
3608
3609    def __warning(self, msg):
3610        """
3611        Private slot handling warnings from the help engine.
3612
3613        @param msg message sent by the help  engine (string)
3614        """
3615        E5MessageBox.warning(
3616            self,
3617            self.tr("Help Engine"), msg)
3618
3619    def __aboutToShowSettingsMenu(self):
3620        """
3621        Private slot to show the Settings menu.
3622        """
3623        self.editMessageFilterAct.setEnabled(
3624            E5ErrorMessage.messageHandlerInstalled())
3625
3626    def __clearPrivateData(self):
3627        """
3628        Private slot to clear the private data.
3629        """
3630        from .WebBrowserClearPrivateDataDialog import (
3631            WebBrowserClearPrivateDataDialog
3632        )
3633        dlg = WebBrowserClearPrivateDataDialog(self)
3634        if dlg.exec() == QDialog.DialogCode.Accepted:
3635            # browsing history, search history, favicons, disk cache, cookies,
3636            # passwords, web databases, downloads, zoom values, SSL error
3637            # exceptions, history period
3638            (history, searches, favicons, cache, cookies,
3639             passwords, databases, downloads, zoomValues,
3640             sslExceptions, historyPeriod) = dlg.getData()
3641            if history:
3642                self.historyManager().clear(historyPeriod)
3643                self.__tabWidget.clearClosedTabsList()
3644                self.webProfile().clearAllVisitedLinks()
3645            if searches:
3646                self.__navigationBar.searchEdit().clear()
3647            if downloads:
3648                self.downloadManager().cleanup()
3649                self.downloadManager().hide()
3650            if favicons:
3651                self.__clearIconsDatabase()
3652            if cache:
3653                try:
3654                    self.webProfile().clearHttpCache()
3655                except AttributeError:
3656                    cachePath = self.webProfile().cachePath()
3657                    if cachePath:
3658                        shutil.rmtree(cachePath)
3659            if cookies:
3660                self.cookieJar().clear()
3661                self.webProfile().cookieStore().deleteAllCookies()
3662            if passwords:
3663                self.passwordManager().clear()
3664            if zoomValues:
3665                ZoomManager.instance().clear()
3666            if sslExceptions:
3667                self.networkManager().clearSslExceptions()
3668
3669    def __showEnginesConfigurationDialog(self):
3670        """
3671        Private slot to show the search engines configuration dialog.
3672        """
3673        from .OpenSearch.OpenSearchDialog import OpenSearchDialog
3674
3675        dlg = OpenSearchDialog(self)
3676        dlg.exec()
3677
3678    def searchEnginesAction(self):
3679        """
3680        Public method to get a reference to the search engines configuration
3681        action.
3682
3683        @return reference to the search engines configuration action (QAction)
3684        """
3685        return self.searchEnginesAct
3686
3687    def __showPasswordsDialog(self):
3688        """
3689        Private slot to show the passwords management dialog.
3690        """
3691        from .Passwords.PasswordsDialog import PasswordsDialog
3692
3693        dlg = PasswordsDialog(self)
3694        dlg.exec()
3695
3696    def __showCertificateErrorsDialog(self):
3697        """
3698        Private slot to show the certificate errors management dialog.
3699        """
3700        self.networkManager().showSslErrorExceptionsDialog()
3701
3702    def __showAdBlockDialog(self):
3703        """
3704        Private slot to show the AdBlock configuration dialog.
3705        """
3706        self.adBlockManager().showDialog()
3707
3708    def __showPersonalInformationDialog(self):
3709        """
3710        Private slot to show the Personal Information configuration dialog.
3711        """
3712        self.personalInformationManager().showConfigurationDialog()
3713
3714    def __showGreaseMonkeyConfigDialog(self):
3715        """
3716        Private slot to show the GreaseMonkey scripts configuration dialog.
3717        """
3718        self.greaseMonkeyManager().showConfigurationDialog()
3719
3720    def __showFeaturePermissionDialog(self):
3721        """
3722        Private slot to show the feature permission dialog.
3723        """
3724        self.featurePermissionManager().showFeaturePermissionsDialog()
3725
3726    def __showZoomValuesDialog(self):
3727        """
3728        Private slot to show the zoom values management dialog.
3729        """
3730        from .ZoomManager.ZoomValuesDialog import ZoomValuesDialog
3731
3732        dlg = ZoomValuesDialog(self)
3733        dlg.exec()
3734
3735    def __showDownloadsWindow(self):
3736        """
3737        Private slot to show the downloads dialog.
3738        """
3739        self.downloadManager().show()
3740
3741    def __showPageSource(self):
3742        """
3743        Private slot to show the source of the current page in an editor.
3744        """
3745        self.currentBrowser().page().toHtml(self.__showPageSourceCallback)
3746
3747    def __showPageSourceCallback(self, src):
3748        """
3749        Private method to show the source of the current page in an editor.
3750
3751        @param src source of the web page
3752        @type str
3753        """
3754        from QScintilla.MiniEditor import MiniEditor
3755        editor = MiniEditor(parent=self)
3756        editor.setText(src, "Html")
3757        editor.setLanguage("dummy.html")
3758        editor.show()
3759
3760    def __toggleJavaScriptConsole(self):
3761        """
3762        Private slot to toggle the JavaScript console.
3763        """
3764        if self.__javascriptConsoleDock.isVisible():
3765            self.__javascriptConsoleDock.hide()
3766        else:
3767            self.__javascriptConsoleDock.show()
3768
3769    def javascriptConsole(self):
3770        """
3771        Public method to get a reference to the JavaScript console widget.
3772
3773        @return reference to the JavaScript console
3774        @rtype WebBrowserJavaScriptConsole
3775        """
3776        return self.__javascriptConsole
3777
3778    @classmethod
3779    def icon(cls, url):
3780        """
3781        Class method to get the icon for an URL.
3782
3783        @param url URL to get icon for (QUrl)
3784        @return icon for the URL (QIcon)
3785        """
3786        return WebIconProvider.instance().iconForUrl(url)
3787
3788    @classmethod
3789    def bookmarksManager(cls):
3790        """
3791        Class method to get a reference to the bookmarks manager.
3792
3793        @return reference to the bookmarks manager (BookmarksManager)
3794        """
3795        if cls._bookmarksManager is None:
3796            from .Bookmarks.BookmarksManager import BookmarksManager
3797            cls._bookmarksManager = BookmarksManager()
3798
3799        return cls._bookmarksManager
3800
3801    def openUrl(self, url, title=None):
3802        """
3803        Public slot to load a URL in the current tab.
3804
3805        @param url URL to be opened (QUrl)
3806        @param title title of the bookmark (string)
3807        """
3808        self.__linkActivated(url)
3809
3810    def openUrlNewTab(self, url, title=None):
3811        """
3812        Public slot to load a URL in a new tab.
3813
3814        @param url URL to be opened (QUrl)
3815        @param title title of the bookmark (string)
3816        """
3817        self.newTab(url)
3818
3819    def openUrlNewBackgroundTab(self, url, title=None):
3820        """
3821        Public slot to load a URL in a new background tab.
3822
3823        @param url URL to be opened (QUrl)
3824        @param title title of the bookmark (string)
3825        """
3826        self.newTab(url, background=True)
3827
3828    def openUrlNewWindow(self, url, title=None):
3829        """
3830        Public slot to load a URL in a new window.
3831
3832        @param url URL to be opened (QUrl)
3833        @param title title of the bookmark (string)
3834        """
3835        self.newWindow(url)
3836
3837    def openUrlNewPrivateWindow(self, url, title=None):
3838        """
3839        Public slot to load a URL in a new private window.
3840
3841        @param url URL to be opened (QUrl)
3842        @param title title of the bookmark (string)
3843        """
3844        self.newPrivateWindow(url)
3845
3846    def __sendPageLink(self):
3847        """
3848        Private slot to send the link of the current page via email.
3849        """
3850        url = self.currentBrowser().url()
3851        if not url.isEmpty():
3852            urlStr = url.toString()
3853            QDesktopServices.openUrl(QUrl("mailto:?body=" + urlStr))
3854
3855    @classmethod
3856    def historyManager(cls):
3857        """
3858        Class method to get a reference to the history manager.
3859
3860        @return reference to the history manager (HistoryManager)
3861        """
3862        if cls._historyManager is None:
3863            from .History.HistoryManager import HistoryManager
3864            cls._historyManager = HistoryManager()
3865
3866        return cls._historyManager
3867
3868    @classmethod
3869    def passwordManager(cls):
3870        """
3871        Class method to get a reference to the password manager.
3872
3873        @return reference to the password manager (PasswordManager)
3874        """
3875        if cls._passwordManager is None:
3876            from .Passwords.PasswordManager import PasswordManager
3877            cls._passwordManager = PasswordManager()
3878
3879        return cls._passwordManager
3880
3881    @classmethod
3882    def adBlockManager(cls):
3883        """
3884        Class method to get a reference to the AdBlock manager.
3885
3886        @return reference to the AdBlock manager (AdBlockManager)
3887        """
3888        if cls._adblockManager is None:
3889            from .AdBlock.AdBlockManager import AdBlockManager
3890            cls._adblockManager = AdBlockManager()
3891
3892        return cls._adblockManager
3893
3894    def adBlockIcon(self):
3895        """
3896        Public method to get a reference to the AdBlock icon.
3897
3898        @return reference to the AdBlock icon (AdBlockIcon)
3899        """
3900        return self.__adBlockIcon
3901
3902    @classmethod
3903    def downloadManager(cls):
3904        """
3905        Class method to get a reference to the download manager.
3906
3907        @return reference to the download manager (DownloadManager)
3908        """
3909        if cls._downloadManager is None:
3910            from .Download.DownloadManager import DownloadManager
3911            cls._downloadManager = DownloadManager()
3912
3913        return cls._downloadManager
3914
3915    @classmethod
3916    def personalInformationManager(cls):
3917        """
3918        Class method to get a reference to the personal information manager.
3919
3920        @return reference to the personal information manager
3921            (PersonalInformationManager)
3922        """
3923        if cls._personalInformationManager is None:
3924            from .PersonalInformationManager import PersonalInformationManager
3925            cls._personalInformationManager = (
3926                PersonalInformationManager.PersonalInformationManager()
3927            )
3928
3929        return cls._personalInformationManager
3930
3931    @classmethod
3932    def greaseMonkeyManager(cls):
3933        """
3934        Class method to get a reference to the GreaseMonkey manager.
3935
3936        @return reference to the GreaseMonkey manager (GreaseMonkeyManager)
3937        """
3938        if cls._greaseMonkeyManager is None:
3939            from .GreaseMonkey.GreaseMonkeyManager import GreaseMonkeyManager
3940            cls._greaseMonkeyManager = GreaseMonkeyManager()
3941
3942        return cls._greaseMonkeyManager
3943
3944    @classmethod
3945    def featurePermissionManager(cls):
3946        """
3947        Class method to get a reference to the feature permission manager.
3948
3949        @return reference to the feature permission manager
3950        @rtype FeaturePermissionManager
3951        """
3952        if cls._featurePermissionManager is None:
3953            from .FeaturePermissions.FeaturePermissionManager import (
3954                FeaturePermissionManager
3955            )
3956            cls._featurePermissionManager = FeaturePermissionManager()
3957
3958        return cls._featurePermissionManager
3959
3960    @classmethod
3961    def imageSearchEngine(cls):
3962        """
3963        Class method to get a reference to the image search engine.
3964
3965        @return reference to the image finder object
3966        @rtype ImageSearchEngine
3967        """
3968        if cls._imageSearchEngine is None:
3969            from .ImageSearch.ImageSearchEngine import (
3970                ImageSearchEngine
3971            )
3972            cls._imageSearchEngine = ImageSearchEngine()
3973
3974        return cls._imageSearchEngine
3975
3976    @classmethod
3977    def autoScroller(cls):
3978        """
3979        Class method to get a reference to the auto scroller.
3980
3981        @return reference to the auto scroller object
3982        @rtype AutoScroller
3983        """
3984        if cls._autoScroller is None:
3985            from .AutoScroll.AutoScroller import AutoScroller
3986            cls._autoScroller = AutoScroller()
3987
3988        return cls._autoScroller
3989
3990    @classmethod
3991    def tabManager(cls):
3992        """
3993        Class method to get a reference to the tab manager widget.
3994
3995        @return reference to the tab manager widget
3996        @rtype TabManagerWidget
3997        """
3998        if cls._tabManager is None:
3999            from .TabManager.TabManagerWidget import TabManagerWidget
4000            cls._tabManager = TabManagerWidget(cls.mainWindow())
4001
4002            # do the connections
4003            for window in cls.mainWindows():
4004                cls._tabManager.mainWindowCreated(window, False)
4005
4006            cls._tabManager.delayedRefreshTree()
4007
4008        return cls._tabManager
4009
4010    def __showTabManager(self, act):
4011        """
4012        Private method to show the tab manager window.
4013
4014        @param act reference to the act that triggered
4015        @type QAction
4016        """
4017        self.tabManager().raiseTabManager(act)
4018
4019    @classmethod
4020    def mainWindow(cls):
4021        """
4022        Class method to get a reference to the main window.
4023
4024        @return reference to the main window (WebBrowserWindow)
4025        """
4026        if cls.BrowserWindows:
4027            return cls.BrowserWindows[0]
4028        else:
4029            return None
4030
4031    @classmethod
4032    def mainWindows(cls):
4033        """
4034        Class method to get references to all main windows.
4035
4036        @return references to all main window (list of WebBrowserWindow)
4037        """
4038        return cls.BrowserWindows
4039
4040    @pyqtSlot()
4041    def __appFocusChanged(self):
4042        """
4043        Private slot to handle a change of the focus.
4044        """
4045        focusWindow = e5App().activeWindow()
4046        if isinstance(focusWindow, WebBrowserWindow):
4047            WebBrowserWindow._lastActiveWindow = focusWindow
4048
4049    @classmethod
4050    def getWindow(cls):
4051        """
4052        Class method to get a reference to the most recent active
4053        web browser window.
4054
4055        @return reference to most recent web browser window
4056        @rtype WebBrowserWindow
4057        """
4058        if cls._lastActiveWindow:
4059            return cls._lastActiveWindow
4060
4061        return cls.mainWindow()
4062
4063    def openSearchManager(self):
4064        """
4065        Public method to get a reference to the opensearch manager object.
4066
4067        @return reference to the opensearch manager object (OpenSearchManager)
4068        """
4069        return self.__navigationBar.searchEdit().openSearchManager()
4070
4071    def __createTextEncodingAction(self, codec, defaultCodec, parentMenu,
4072                                   name=None):
4073        """
4074        Private method to create an action for the text encoding menu.
4075
4076        @param codec name of the codec to create an action for
4077        @type str
4078        @param defaultCodec name of the default codec
4079        @type str
4080        @param parentMenu reference to the parent menu
4081        @type QMenu
4082        @param name name for the action
4083        @type str
4084        """
4085        act = QAction(name, parentMenu) if name else QAction(codec, parentMenu)
4086        act.setData(codec)
4087        act.setCheckable(True)
4088        if defaultCodec == codec:
4089            act.setChecked(True)
4090
4091        parentMenu.addAction(act)
4092
4093    def __createTextEncodingSubmenu(self, title, codecNames, parentMenu):
4094        """
4095        Private method to create a text encoding sub menu.
4096
4097        @param title title of the menu
4098        @type str
4099        @param codecNames list of codec names for the menu
4100        @type list of str
4101        @param parentMenu reference to the parent menu
4102        @type QMenu
4103        """
4104        if codecNames:
4105            defaultCodec = self.webSettings().defaultTextEncoding().lower()
4106
4107            menu = QMenu(title, parentMenu)
4108            for codec in codecNames:
4109                self.__createTextEncodingAction(codec, defaultCodec, menu)
4110
4111            parentMenu.addMenu(menu)
4112
4113    def __aboutToShowTextEncodingMenu(self):
4114        """
4115        Private slot to populate the text encoding menu.
4116        """
4117        self.__textEncodingMenu.clear()
4118
4119        defaultTextEncoding = self.webSettings().defaultTextEncoding().lower()
4120        currentCodec = (
4121            defaultTextEncoding
4122            if defaultTextEncoding in Utilities.supportedCodecs else
4123            ""
4124        )
4125
4126        isoCodecs = []
4127        winCodecs = []
4128        uniCodecs = []
4129        cpCodecs = []
4130        macCodecs = []
4131        otherCodecs = []
4132
4133        for codec in sorted(Utilities.supportedCodecs):
4134            if codec.startswith(("iso-", "latin")):
4135                isoCodecs.append(codec)
4136            elif codec.startswith(("windows-")):
4137                winCodecs.append(codec)
4138            elif codec.startswith("utf-"):
4139                uniCodecs.append(codec)
4140            elif codec.startswith("cp"):
4141                cpCodecs.append(codec)
4142            elif codec.startswith("mac-"):
4143                macCodecs.append(codec)
4144            else:
4145                otherCodecs.append(codec)
4146
4147        self.__createTextEncodingAction(
4148            "", currentCodec, self.__textEncodingMenu, name=self.tr("System"))
4149        self.__textEncodingMenu.addSeparator()
4150        self.__createTextEncodingSubmenu(self.tr("ISO"), isoCodecs,
4151                                         self.__textEncodingMenu)
4152        self.__createTextEncodingSubmenu(self.tr("Unicode"), uniCodecs,
4153                                         self.__textEncodingMenu)
4154        self.__createTextEncodingSubmenu(self.tr("Windows"), winCodecs,
4155                                         self.__textEncodingMenu)
4156        self.__createTextEncodingSubmenu(self.tr("IBM"), cpCodecs,
4157                                         self.__textEncodingMenu)
4158        self.__createTextEncodingSubmenu(self.tr("Apple"), macCodecs,
4159                                         self.__textEncodingMenu)
4160        self.__createTextEncodingSubmenu(self.tr("Other"), otherCodecs,
4161                                         self.__textEncodingMenu)
4162
4163    def __setTextEncoding(self, act):
4164        """
4165        Private slot to set the selected text encoding as the default for
4166        this session.
4167
4168        @param act reference to the selected action (QAction)
4169        """
4170        codec = act.data()
4171        if codec == "":
4172            self.webSettings().setDefaultTextEncoding("")
4173        else:
4174            self.webSettings().setDefaultTextEncoding(codec)
4175
4176    def __populateToolbarsMenu(self, menu):
4177        """
4178        Private method to populate the toolbars menu.
4179
4180        @param menu reference to the menu to be populated
4181        @type QMenu
4182        """
4183        menu.clear()
4184
4185        act = menu.addAction(self.tr("Menu Bar"))
4186        act.setCheckable(True)
4187        act.setChecked(not self.menuBar().isHidden())
4188        act.setData("menubar")
4189
4190        act = menu.addAction(self.tr("Bookmarks"))
4191        act.setCheckable(True)
4192        act.setChecked(not self.__bookmarksToolBar.isHidden())
4193        act.setData("bookmarks")
4194
4195        act = menu.addAction(self.tr("Status Bar"))
4196        act.setCheckable(True)
4197        act.setChecked(not self.statusBar().isHidden())
4198        act.setData("statusbar")
4199
4200        if Preferences.getWebBrowser("ShowToolbars"):
4201            menu.addSeparator()
4202            for name, (text, tb) in sorted(self.__toolbars.items(),
4203                                           key=lambda t: t[1][0]):
4204                act = menu.addAction(text)
4205                act.setCheckable(True)
4206                act.setChecked(not tb.isHidden())
4207                act.setData(name)
4208            menu.addSeparator()
4209            act = menu.addAction(self.tr("&Show all"))
4210            act.setData("__SHOW__")
4211            act = menu.addAction(self.tr("&Hide all"))
4212            act.setData("__HIDE__")
4213
4214    def createPopupMenu(self):
4215        """
4216        Public method to create the toolbars menu for Qt.
4217
4218        @return toolbars menu
4219        @rtype QMenu
4220        """
4221        menu = QMenu(self)
4222        menu.triggered.connect(self.__TBMenuTriggered)
4223
4224        self.__populateToolbarsMenu(menu)
4225
4226        return menu
4227
4228    def __showToolbarsMenu(self):
4229        """
4230        Private slot to display the Toolbars menu.
4231        """
4232        self.__populateToolbarsMenu(self.__toolbarsMenu)
4233
4234    def __TBMenuTriggered(self, act):
4235        """
4236        Private method to handle the toggle of a toolbar via the Window->
4237        Toolbars submenu or the toolbars popup menu.
4238
4239        @param act reference to the action that was triggered
4240        @type QAction
4241        """
4242        name = act.data()
4243        if name:
4244            if name == "bookmarks":
4245                # special handling of bookmarks toolbar
4246                self.__setBookmarksToolbarVisibility(act.isChecked())
4247
4248            elif name == "menubar":
4249                # special treatment of the menu bar
4250                self.__setMenuBarVisibility(act.isChecked())
4251
4252            elif name == "statusbar":
4253                # special treatment of the status bar
4254                self.__setStatusBarVisible(act.isChecked())
4255
4256            elif name == "__SHOW__":
4257                for _text, tb in list(self.__toolbars.values()):
4258                    tb.show()
4259
4260            elif name == "__HIDE__":
4261                for _text, tb in list(self.__toolbars.values()):
4262                    tb.hide()
4263
4264            else:
4265                tb = self.__toolbars[name][1]
4266                if act.isChecked():
4267                    tb.show()
4268                else:
4269                    tb.hide()
4270
4271    def __setBookmarksToolbarVisibility(self, visible):
4272        """
4273        Private method to set the visibility of the bookmarks toolbar.
4274
4275        @param visible flag indicating the toolbar visibility
4276        @type bool
4277        """
4278        if visible:
4279            self.__bookmarksToolBar.show()
4280        else:
4281            self.__bookmarksToolBar.hide()
4282
4283        # save state for next invokation
4284        Preferences.setWebBrowser("BookmarksToolBarVisible", visible)
4285
4286    def __setMenuBarVisibility(self, visible):
4287        """
4288        Private method to set the visibility of the menu bar.
4289
4290        @param visible flag indicating the menu bar visibility
4291        @type bool
4292        """
4293        if visible:
4294            self.menuBar().show()
4295            self.__navigationBar.superMenuButton().hide()
4296        else:
4297            self.menuBar().hide()
4298            self.__navigationBar.superMenuButton().show()
4299
4300        Preferences.setWebBrowser("MenuBarVisible", visible)
4301
4302    def __setStatusBarVisible(self, visible):
4303        """
4304        Private method to set the visibility of the status bar.
4305
4306        @param visible flag indicating the status bar visibility
4307        @type bool
4308        """
4309        self.statusBar().setVisible(visible)
4310
4311        Preferences.setWebBrowser("StatusBarVisible", visible)
4312
4313    def eventMouseButtons(self):
4314        """
4315        Public method to get the last recorded mouse buttons.
4316
4317        @return mouse buttons (Qt.MouseButtons)
4318        """
4319        return self.__eventMouseButtons
4320
4321    def eventKeyboardModifiers(self):
4322        """
4323        Public method to get the last recorded keyboard modifiers.
4324
4325        @return keyboard modifiers (Qt.KeyboardModifiers)
4326        """
4327        return self.__eventKeyboardModifiers
4328
4329    def setEventMouseButtons(self, buttons):
4330        """
4331        Public method to record mouse buttons.
4332
4333        @param buttons mouse buttons to record (Qt.MouseButtons)
4334        """
4335        self.__eventMouseButtons = buttons
4336
4337    def setEventKeyboardModifiers(self, modifiers):
4338        """
4339        Public method to record keyboard modifiers.
4340
4341        @param modifiers keyboard modifiers to record (Qt.KeyboardModifiers)
4342        """
4343        self.__eventKeyboardModifiers = modifiers
4344
4345    def mousePressEvent(self, evt):
4346        """
4347        Protected method called by a mouse press event.
4348
4349        @param evt reference to the mouse event (QMouseEvent)
4350        """
4351        if evt.button() == Qt.MouseButton.XButton1:
4352            self.currentBrowser().triggerPageAction(
4353                QWebEnginePage.WebAction.Back)
4354        elif evt.button() == Qt.MouseButton.XButton2:
4355            self.currentBrowser().triggerPageAction(
4356                QWebEnginePage.WebAction.Forward)
4357        else:
4358            super().mousePressEvent(evt)
4359
4360    @classmethod
4361    def feedsManager(cls):
4362        """
4363        Class method to get a reference to the RSS feeds manager.
4364
4365        @return reference to the RSS feeds manager (FeedsManager)
4366        """
4367        if cls._feedsManager is None:
4368            from .Feeds.FeedsManager import FeedsManager
4369            cls._feedsManager = FeedsManager()
4370
4371        return cls._feedsManager
4372
4373    def __showFeedsManager(self):
4374        """
4375        Private slot to show the feeds manager dialog.
4376        """
4377        feedsManager = self.feedsManager()
4378        feedsManager.openUrl.connect(self.openUrl)
4379        feedsManager.newTab.connect(self.openUrlNewTab)
4380        feedsManager.newBackgroundTab.connect(self.openUrlNewBackgroundTab)
4381        feedsManager.newWindow.connect(self.openUrlNewWindow)
4382        feedsManager.newPrivateWindow.connect(self.openUrlNewPrivateWindow)
4383        feedsManager.rejected.connect(
4384            lambda: self.__feedsManagerClosed(feedsManager))
4385        feedsManager.show()
4386
4387    def __feedsManagerClosed(self, feedsManager):
4388        """
4389        Private slot to handle closing the feeds manager dialog.
4390
4391        @param feedsManager reference to the feeds manager object
4392        @type FeedsManager
4393        """
4394        feedsManager.openUrl.disconnect(self.openUrl)
4395        feedsManager.newTab.disconnect(self.openUrlNewTab)
4396        feedsManager.newBackgroundTab.disconnect(self.openUrlNewBackgroundTab)
4397        feedsManager.newWindow.disconnect(self.openUrlNewWindow)
4398        feedsManager.newPrivateWindow.disconnect(self.openUrlNewPrivateWindow)
4399        feedsManager.rejected.disconnect()
4400
4401    def __showSiteinfoDialog(self):
4402        """
4403        Private slot to show the site info dialog.
4404        """
4405        from .SiteInfo.SiteInfoDialog import SiteInfoDialog
4406        self.__siteinfoDialog = SiteInfoDialog(self.currentBrowser(), self)
4407        self.__siteinfoDialog.show()
4408
4409    @classmethod
4410    def userAgentsManager(cls):
4411        """
4412        Class method to get a reference to the user agents manager.
4413
4414        @return reference to the user agents manager (UserAgentManager)
4415        """
4416        if cls._userAgentsManager is None:
4417            from .UserAgent.UserAgentManager import UserAgentManager
4418            cls._userAgentsManager = UserAgentManager()
4419
4420        return cls._userAgentsManager
4421
4422    def __showUserAgentsDialog(self):
4423        """
4424        Private slot to show the user agents management dialog.
4425        """
4426        from .UserAgent.UserAgentsDialog import UserAgentsDialog
4427
4428        dlg = UserAgentsDialog(self)
4429        dlg.exec()
4430
4431    @classmethod
4432    def syncManager(cls):
4433        """
4434        Class method to get a reference to the data synchronization manager.
4435
4436        @return reference to the data synchronization manager (SyncManager)
4437        """
4438        if cls._syncManager is None:
4439            from .Sync.SyncManager import SyncManager
4440            cls._syncManager = SyncManager()
4441
4442        return cls._syncManager
4443
4444    def __showSyncDialog(self):
4445        """
4446        Private slot to show the synchronization dialog.
4447        """
4448        self.syncManager().showSyncDialog()
4449
4450    @classmethod
4451    def speedDial(cls):
4452        """
4453        Class method to get a reference to the speed dial.
4454
4455        @return reference to the speed dial (SpeedDial)
4456        """
4457        if cls._speedDial is None:
4458            from .SpeedDial.SpeedDial import SpeedDial
4459            cls._speedDial = SpeedDial()
4460
4461        return cls._speedDial
4462
4463    def keyPressEvent(self, evt):
4464        """
4465        Protected method to handle key presses.
4466
4467        @param evt reference to the key press event (QKeyEvent)
4468        """
4469        number = -1
4470        key = evt.key()
4471
4472        if key == Qt.Key.Key_1:
4473            number = 1
4474        elif key == Qt.Key.Key_2:
4475            number = 2
4476        elif key == Qt.Key.Key_3:
4477            number = 3
4478        elif key == Qt.Key.Key_4:
4479            number = 4
4480        elif key == Qt.Key.Key_5:
4481            number = 5
4482        elif key == Qt.Key.Key_6:
4483            number = 6
4484        elif key == Qt.Key.Key_7:
4485            number = 7
4486        elif key == Qt.Key.Key_8:
4487            number = 8
4488        elif key == Qt.Key.Key_9:
4489            number = 9
4490        elif key == Qt.Key.Key_0:
4491            number = 10
4492
4493        if number != -1:
4494            if evt.modifiers() == Qt.KeyboardModifiers(
4495                Qt.KeyboardModifier.AltModifier
4496            ):
4497                if number == 10:
4498                    number = self.__tabWidget.count()
4499                self.__tabWidget.setCurrentIndex(number - 1)
4500                return
4501
4502            if evt.modifiers() == Qt.KeyboardModifiers(
4503                Qt.KeyboardModifier.MetaModifier
4504            ):
4505                url = self.speedDial().urlForShortcut(number - 1)
4506                if url.isValid():
4507                    self.__linkActivated(url)
4508                    return
4509
4510        super().keyPressEvent(evt)
4511
4512    def event(self, evt):
4513        """
4514        Public method handling events.
4515
4516        @param evt reference to the event
4517        @type QEvent
4518        @return flag indicating a handled event
4519        @rtype bool
4520        """
4521        if evt.type() == QEvent.Type.WindowStateChange:
4522            if (
4523                not bool(evt.oldState() & Qt.WindowState.WindowFullScreen) and
4524                bool(self.windowState() & Qt.WindowState.WindowFullScreen)
4525            ):
4526                # enter full screen mode
4527                self.__windowStates = evt.oldState()
4528                self.__toolbarStates = self.saveState()
4529                self.menuBar().hide()
4530                self.statusBar().hide()
4531                self.__searchWidget.hide()
4532                self.__tabWidget.tabBar().hide()
4533                if Preferences.getWebBrowser("ShowToolbars"):
4534                    for _title, toolbar in self.__toolbars.values():
4535                        if toolbar is not self.__bookmarksToolBar:
4536                            toolbar.hide()
4537                self.__navigationBar.exitFullScreenButton().setVisible(True)
4538                self.__navigationContainer.hide()
4539
4540            elif (
4541                bool(evt.oldState() & Qt.WindowState.WindowFullScreen) and
4542                not bool(self.windowState() & Qt.WindowState.WindowFullScreen)
4543            ):
4544                # leave full screen mode
4545                self.setWindowState(self.__windowStates)
4546                self.__htmlFullScreen = False
4547                if Preferences.getWebBrowser("MenuBarVisible"):
4548                    self.menuBar().show()
4549                if Preferences.getWebBrowser("StatusBarVisible"):
4550                    self.statusBar().show()
4551                self.restoreState(self.__toolbarStates)
4552                self.__tabWidget.tabBar().show()
4553                self.__navigationBar.exitFullScreenButton().setVisible(False)
4554                self.__navigationContainer.show()
4555
4556            if self.__hideNavigationTimer:
4557                self.__hideNavigationTimer.stop()
4558
4559        return super().event(evt)
4560
4561    ###########################################################################
4562    ## Interface to VirusTotal below                                         ##
4563    ###########################################################################
4564
4565    def __virusTotalScanCurrentSite(self):
4566        """
4567        Private slot to ask VirusTotal for a scan of the URL of the current
4568        browser.
4569        """
4570        cb = self.currentBrowser()
4571        if cb is not None:
4572            url = cb.url()
4573            if url.scheme() in ["http", "https", "ftp"]:
4574                self.requestVirusTotalScan(url)
4575
4576    def requestVirusTotalScan(self, url):
4577        """
4578        Public method to submit a request to scan an URL by VirusTotal.
4579
4580        @param url URL to be scanned (QUrl)
4581        """
4582        self.__virusTotal.submitUrl(url)
4583
4584    def __virusTotalSubmitUrlError(self, msg):
4585        """
4586        Private slot to handle an URL scan submission error.
4587
4588        @param msg error message (str)
4589        """
4590        E5MessageBox.critical(
4591            self,
4592            self.tr("VirusTotal Scan"),
4593            self.tr("""<p>The VirusTotal scan could not be"""
4594                    """ scheduled.<p>\n<p>Reason: {0}</p>""").format(msg))
4595
4596    def __virusTotalUrlScanReport(self, url):
4597        """
4598        Private slot to initiate the display of the URL scan report page.
4599
4600        @param url URL of the URL scan report page (string)
4601        """
4602        self.newTab(url)
4603
4604    def __virusTotalFileScanReport(self, url):
4605        """
4606        Private slot to initiate the display of the file scan report page.
4607
4608        @param url URL of the file scan report page (string)
4609        """
4610        self.newTab(url)
4611
4612    def __virusTotalIpAddressReport(self):
4613        """
4614        Private slot to retrieve an IP address report.
4615        """
4616        ip, ok = QInputDialog.getText(
4617            self,
4618            self.tr("IP Address Report"),
4619            self.tr("Enter a valid IPv4 address in dotted quad notation:"),
4620            QLineEdit.EchoMode.Normal)
4621        if ok and ip:
4622            if ip.count(".") == 3:
4623                self.__virusTotal.getIpAddressReport(ip)
4624            else:
4625                E5MessageBox.information(
4626                    self,
4627                    self.tr("IP Address Report"),
4628                    self.tr("""The given IP address is not in dotted quad"""
4629                            """ notation."""))
4630
4631    def __virusTotalDomainReport(self):
4632        """
4633        Private slot to retrieve a domain report.
4634        """
4635        domain, ok = QInputDialog.getText(
4636            self,
4637            self.tr("Domain Report"),
4638            self.tr("Enter a valid domain name:"),
4639            QLineEdit.EchoMode.Normal)
4640        if ok and domain:
4641            self.__virusTotal.getDomainReport(domain)
4642
4643    ###########################################################################
4644    ## Style sheet handling below                                            ##
4645    ###########################################################################
4646
4647    def reloadUserStyleSheet(self):
4648        """
4649        Public method to reload the user style sheet.
4650        """
4651        styleSheet = Preferences.getWebBrowser("UserStyleSheet")
4652        self.__setUserStyleSheet(styleSheet)
4653
4654    def __setUserStyleSheet(self, styleSheetFile):
4655        """
4656        Private method to set a user style sheet.
4657
4658        @param styleSheetFile name of the user style sheet file (string)
4659        """
4660        name = "_eric_userstylesheet"
4661        userStyle = ""
4662
4663        userStyle += (
4664            WebBrowserTools.readAllFileContents(styleSheetFile)
4665            .replace("\n", "")
4666        )
4667
4668        oldScript = self.webProfile().scripts().findScript(name)
4669        if not oldScript.isNull():
4670            self.webProfile().scripts().remove(oldScript)
4671
4672        if userStyle:
4673            from .WebBrowserPage import WebBrowserPage
4674
4675            script = QWebEngineScript()
4676            script.setName(name)
4677            script.setInjectionPoint(
4678                QWebEngineScript.InjectionPoint.DocumentCreation)
4679            script.setWorldId(WebBrowserPage.SafeJsWorld)
4680            script.setRunsOnSubFrames(True)
4681            script.setSourceCode(Scripts.setStyleSheet(userStyle))
4682            self.webProfile().scripts().insert(script)
4683
4684    ##########################################
4685    ## Support for desktop notifications below
4686    ##########################################
4687
4688    @classmethod
4689    def showNotification(cls, icon, heading, text,
4690                         kind=NotificationTypes.INFORMATION, timeout=None):
4691        """
4692        Class method to show a desktop notification.
4693
4694        @param icon icon to be shown in the notification
4695        @type QPixmap
4696        @param heading heading of the notification
4697        @type str
4698        @param text text of the notification
4699        @type str
4700        @param kind kind of notification to be shown
4701        @type NotificationTypes
4702        @param timeout time in seconds the notification should be shown
4703            (None = use configured timeout, 0 = indefinitely)
4704        @type int
4705        """
4706        if cls._notification is None:
4707            from UI.NotificationWidget import NotificationWidget
4708            cls._notification = NotificationWidget()
4709
4710        if timeout is None:
4711            timeout = Preferences.getUI("NotificationTimeout")
4712        cls._notification.showNotification(
4713            icon, heading, text, kind=kind, timeout=timeout)
4714
4715    ######################################
4716    ## Support for global status bar below
4717    ######################################
4718
4719    @classmethod
4720    def globalStatusBar(cls):
4721        """
4722        Class method to get a reference to a global status bar.
4723
4724        The global status bar is the status bar of the main window. If
4725        no such window exists and the web browser was called from the eric IDE,
4726        the status bar of the IDE is returned.
4727
4728        @return reference to the global status bar
4729        @rtype QStatusBar
4730        """
4731        if cls.BrowserWindows:
4732            return cls.BrowserWindows[0].statusBar()
4733        else:
4734            return None
4735
4736    ###################################
4737    ## Support for download files below
4738    ###################################
4739
4740    @classmethod
4741    def downloadRequested(cls, download):
4742        """
4743        Class method to handle a download request.
4744
4745        @param download reference to the download data
4746        @type QWebEngineDownloadItem
4747        """
4748        cls.downloadManager().download(download)
4749
4750    ########################################
4751    ## Support for web engine profiles below
4752    ########################################
4753
4754    @classmethod
4755    def webProfile(cls, private=False):
4756        """
4757        Class method handling the web engine profile.
4758
4759        @param private flag indicating the privacy mode
4760        @type bool
4761        @return reference to the web profile object
4762        @rtype QWebEngineProfile
4763        """
4764        if cls._webProfile is None:
4765            if private:
4766                cls._webProfile = QWebEngineProfile()
4767            else:
4768                cls._webProfile = QWebEngineProfile.defaultProfile()
4769            cls._webProfile.downloadRequested.connect(
4770                cls.downloadRequested)
4771
4772            # add the default user agent string
4773            userAgent = cls._webProfile.httpUserAgent()
4774            cls._webProfile.defaultUserAgent = userAgent
4775
4776            if not private:
4777                if Preferences.getWebBrowser("DiskCacheEnabled"):
4778                    cls._webProfile.setHttpCacheType(
4779                        QWebEngineProfile.HttpCacheType.DiskHttpCache)
4780                    cls._webProfile.setHttpCacheMaximumSize(
4781                        Preferences.getWebBrowser("DiskCacheSize") *
4782                        1024 * 1024)
4783                    cls._webProfile.setCachePath(os.path.join(
4784                        Utilities.getConfigDir(), "web_browser"))
4785                else:
4786                    cls._webProfile.setHttpCacheType(
4787                        QWebEngineProfile.HttpCacheType.MemoryHttpCache)
4788                    cls._webProfile.setHttpCacheMaximumSize(0)
4789                cls._webProfile.setPersistentStoragePath(os.path.join(
4790                    Utilities.getConfigDir(), "web_browser",
4791                    "persistentstorage"))
4792                cls._webProfile.setPersistentCookiesPolicy(
4793                    QWebEngineProfile.PersistentCookiesPolicy
4794                    .AllowPersistentCookies)
4795
4796            with contextlib.suppress(AttributeError):
4797                cls._webProfile.setSpellCheckEnabled(
4798                    Preferences.getWebBrowser("SpellCheckEnabled"))
4799                cls._webProfile.setSpellCheckLanguages(
4800                    Preferences.getWebBrowser("SpellCheckLanguages"))
4801
4802            # Setup QWebChannel user scripts
4803            from .WebBrowserPage import WebBrowserPage
4804
4805            # WebChannel for SafeJsWorld
4806            script = QWebEngineScript()
4807            script.setName("_eric_webchannel")
4808            script.setInjectionPoint(
4809                QWebEngineScript.InjectionPoint.DocumentCreation)
4810            script.setWorldId(WebBrowserPage.SafeJsWorld)
4811            script.setRunsOnSubFrames(True)
4812            script.setSourceCode(Scripts.setupWebChannel(script.worldId()))
4813            cls._webProfile.scripts().insert(script)
4814
4815            # WebChannel for UnsafeJsWorld
4816            script2 = QWebEngineScript()
4817            script2.setName("_eric_webchannel2")
4818            script2.setInjectionPoint(
4819                QWebEngineScript.InjectionPoint.DocumentCreation)
4820            script2.setWorldId(WebBrowserPage.UnsafeJsWorld)
4821            script2.setRunsOnSubFrames(True)
4822            script2.setSourceCode(Scripts.setupWebChannel(script2.worldId()))
4823            cls._webProfile.scripts().insert(script2)
4824
4825            # document.window object addons
4826            script3 = QWebEngineScript()
4827            script3.setName("_eric_window_object")
4828            script3.setInjectionPoint(
4829                QWebEngineScript.InjectionPoint.DocumentCreation)
4830            script3.setWorldId(WebBrowserPage.UnsafeJsWorld)
4831            script3.setRunsOnSubFrames(True)
4832            script3.setSourceCode(Scripts.setupWindowObject())
4833            cls._webProfile.scripts().insert(script3)
4834
4835        return cls._webProfile
4836
4837    @classmethod
4838    def webSettings(cls):
4839        """
4840        Class method to get the web settings of the current profile.
4841
4842        @return web settings of the current profile
4843        @rtype QWebEngineSettings
4844        """
4845        return cls.webProfile().settings()
4846
4847    ####################################################
4848    ## Methods below implement session related functions
4849    ####################################################
4850
4851    @classmethod
4852    def sessionManager(cls):
4853        """
4854        Class method to get a reference to the session manager.
4855
4856        @return reference to the session manager
4857        @rtype SessionManager
4858        """
4859        if cls._sessionManager is None and not cls._isPrivate:
4860            from .Session.SessionManager import SessionManager
4861            cls._sessionManager = SessionManager()
4862
4863        return cls._sessionManager
4864
4865    def __showSessionManagerDialog(self):
4866        """
4867        Private slot to show the session manager dialog.
4868        """
4869        self.sessionManager().showSessionManagerDialog()
4870
4871    ##########################################################
4872    ## Methods below implement safe browsing related functions
4873    ##########################################################
4874
4875    @classmethod
4876    def safeBrowsingManager(cls):
4877        """
4878        Class method to get a reference to the safe browsing interface.
4879
4880        @return reference to the safe browsing manager
4881        @rtype SafeBrowsingManager
4882        """
4883        if cls._safeBrowsingManager is None:
4884            from .SafeBrowsing.SafeBrowsingManager import SafeBrowsingManager
4885            cls._safeBrowsingManager = SafeBrowsingManager()
4886
4887        return cls._safeBrowsingManager
4888
4889    def __showSafeBrowsingDialog(self):
4890        """
4891        Private slot to show the safe browsing management dialog.
4892        """
4893        self.safeBrowsingManager().showSafeBrowsingDialog()
4894
4895    #############################################################
4896    ## Methods below implement protocol handler related functions
4897    #############################################################
4898
4899    @classmethod
4900    def protocolHandlerManager(cls):
4901        """
4902        Class method to get a reference to the protocol handler manager.
4903
4904        @return reference to the protocol handler manager
4905        @rtype ProtocolHandlerManager
4906        """
4907        if cls._protocolHandlerManager is None:
4908            from .Network.ProtocolHandlerManager import ProtocolHandlerManager
4909            cls._protocolHandlerManager = ProtocolHandlerManager()
4910
4911        return cls._protocolHandlerManager
4912
4913    def __showProtocolHandlerManagerDialog(self):
4914        """
4915        Private slot to show the protocol handler manager dialog.
4916        """
4917        self.protocolHandlerManager().showProtocolHandlerManagerDialog()
4918
4919    ###############################################################
4920    ## Methods below implement single application related functions
4921    ###############################################################
4922
4923    @pyqtSlot(str)
4924    def __saLoadUrl(self, urlStr):
4925        """
4926        Private slot to load an URL received via the single application
4927        protocol.
4928
4929        @param urlStr URL to be loaded
4930        @type str
4931        """
4932        url = QUrl.fromUserInput(urlStr)
4933        self.__linkActivated(url)
4934
4935        self.raise_()
4936        self.activateWindow()
4937
4938    @pyqtSlot(str)
4939    def __saNewTab(self, urlStr):
4940        """
4941        Private slot to load an URL received via the single application
4942        protocol in a new tab.
4943
4944        @param urlStr URL to be loaded
4945        @type str
4946        """
4947        url = QUrl.fromUserInput(urlStr)
4948        self.newTab(url)
4949
4950        self.raise_()
4951        self.activateWindow()
4952
4953    @pyqtSlot(str)
4954    def __saSearchWord(self, word):
4955        """
4956        Private slot to search for the given word.
4957
4958        @param word word to be searched for
4959        @type str
4960        """
4961        if WebBrowserWindow._useQtHelp:
4962            self.__searchWord = word
4963            self.__searchForWord()
4964
4965        self.raise_()
4966        self.activateWindow()
4967
4968    ######################################################
4969    ## Methods below implement shortcuts related functions
4970    ######################################################
4971
4972    def __configShortcuts(self):
4973        """
4974        Private slot to configure the keyboard shortcuts.
4975        """
4976        if self.__shortcutsDialog is None:
4977            from Preferences.ShortcutsDialog import ShortcutsDialog
4978            self.__shortcutsDialog = ShortcutsDialog(self)
4979        self.__shortcutsDialog.populate(helpViewer=self)
4980        self.__shortcutsDialog.show()
4981
4982    def __exportShortcuts(self):
4983        """
4984        Private slot to export the keyboard shortcuts.
4985        """
4986        fn, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
4987            None,
4988            self.tr("Export Keyboard Shortcuts"),
4989            "",
4990            self.tr("Keyboard Shortcuts File (*.ekj);;"
4991                    "XML Keyboard Shortcuts File (*.e4k)"),
4992            "",
4993            E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
4994
4995        if not fn:
4996            return
4997
4998        ext = QFileInfo(fn).suffix()
4999        if not ext:
5000            ex = selectedFilter.split("(*")[1].split(")")[0]
5001            if ex:
5002                fn += ex
5003
5004        ok = (
5005            E5MessageBox.yesNo(
5006                self,
5007                self.tr("Export Keyboard Shortcuts"),
5008                self.tr("""<p>The keyboard shortcuts file <b>{0}</b> exists"""
5009                        """ already. Overwrite it?</p>""").format(fn))
5010            if os.path.exists(fn) else
5011            True
5012        )
5013
5014        if ok:
5015            from Preferences import Shortcuts
5016            Shortcuts.exportShortcuts(fn, helpViewer=self)
5017
5018    def __importShortcuts(self):
5019        """
5020        Private slot to import the keyboard shortcuts.
5021        """
5022        fn = E5FileDialog.getOpenFileName(
5023            None,
5024            self.tr("Import Keyboard Shortcuts"),
5025            "",
5026            self.tr("Keyboard Shortcuts File (*.ekj);;"
5027                    "XML Keyboard shortcut file (*.e4k)"))
5028
5029        if fn:
5030            from Preferences import Shortcuts
5031            Shortcuts.importShortcuts(fn, helpViewer=self)
5032