eric7/HelpViewer/HelpViewerWidget.py

Thu, 14 Oct 2021 20:15:58 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Thu, 14 Oct 2021 20:15:58 +0200
branch
eric7
changeset 8685
b0669ce1066d
parent 8683
e8a907801549
child 8686
af2ee3a303ac
permissions
-rw-r--r--

Continued implementing the embedded help viewer widget. Added the help index and help search widgets.

# -*- coding: utf-8 -*-

# Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing an embedded viewer for QtHelp and local HTML files.
"""

import os

from PyQt6.QtCore import pyqtSlot, Qt, QUrl, QTimer
from PyQt6.QtGui import QAction, QFont, QFontMetrics
from PyQt6.QtHelp import QHelpEngine
from PyQt6.QtWidgets import (
    QWidget, QHBoxLayout, QVBoxLayout, QComboBox, QSizePolicy, QStackedWidget,
    QToolButton, QButtonGroup, QAbstractButton, QMenu, QFrame, QLabel,
    QProgressBar
)

from EricWidgets import EricFileDialog, EricMessageBox

import UI.PixmapCache
import Utilities
import Preferences

from .OpenPagesWidget import OpenPagesWidget

from WebBrowser.QtHelp.HelpTocWidget import HelpTocWidget
from WebBrowser.QtHelp.HelpIndexWidget import HelpIndexWidget
from WebBrowser.QtHelp.HelpSearchWidget import HelpSearchWidget


class HelpViewerWidget(QWidget):
    """
    Class implementing an embedded viewer for QtHelp and local HTML files.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (defaults to None)
        @type QWidget (optional)
        """
        super().__init__(parent)
        self.setObjectName("HelpViewerWidget")
        
        self.__ui = parent
        
        self.__initHelpEngine()
        
        self.__layout = QVBoxLayout()
        self.__layout.setObjectName("MainLayout")
        self.__layout.setContentsMargins(0, 3, 0, 0)
        
        ###################################################################
        
        self.__selectorLayout = QHBoxLayout()
        
        self.__helpSelector = QComboBox(self)
        self.__helpSelector.setSizePolicy(
            QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
        self.__selectorLayout.addWidget(self.__helpSelector)
        self.__populateHelpSelector()
        self.__helpSelector.currentIndexChanged.connect(
            self.__helpTopicSelected)
        
        self.__openButton = QToolButton(self)
        self.__openButton.setIcon(UI.PixmapCache.getIcon("open"))
        self.__openButton.setToolTip(self.tr("Open a local file"))
        self.__openButton.clicked.connect(self.__openFile)
        self.__selectorLayout.addWidget(self.__openButton)
        
        self.__actionsButton = QToolButton(self)
        self.__actionsButton.setIcon(
            UI.PixmapCache.getIcon("actionsToolButton"))
        self.__actionsButton.setToolTip(
            self.tr("Select action from menu"))
        self.__actionsButton.setPopupMode(
            QToolButton.ToolButtonPopupMode.InstantPopup)
        self.__selectorLayout.addWidget(self.__actionsButton)
        
        self.__layout.addLayout(self.__selectorLayout)
        
        ###################################################################
        
        self.__navButtonsLayout = QHBoxLayout()
        
        self.__navButtonsLayout.addStretch()
        
        self.__backwardButton = QToolButton(self)
        self.__backwardButton.setIcon(UI.PixmapCache.getIcon("back"))
        self.__backwardButton.setToolTip(self.tr("Move one page backward"))
        self.__backwardButton.clicked.connect(self.__backward)
        
        self.__forwardButton = QToolButton(self)
        self.__forwardButton.setIcon(UI.PixmapCache.getIcon("forward"))
        self.__forwardButton.setToolTip(self.tr("Move one page forward"))
        self.__forwardButton.clicked.connect(self.__forward)
        
        self.__backForButtonLayout = QHBoxLayout()
        self.__backForButtonLayout.setContentsMargins(0, 0, 0, 0)
        self.__backForButtonLayout.setSpacing(0)
        self.__backForButtonLayout.addWidget(self.__backwardButton)
        self.__backForButtonLayout.addWidget(self.__forwardButton)
        self.__navButtonsLayout.addLayout(self.__backForButtonLayout)
        
        self.__reloadButton = QToolButton(self)
        self.__reloadButton.setIcon(UI.PixmapCache.getIcon("reload"))
        self.__reloadButton.setToolTip(self.tr("Reload the current page"))
        self.__reloadButton.clicked.connect(self.__reload)
        self.__navButtonsLayout.addWidget(self.__reloadButton)
        
        self.__buttonLine1 = QFrame(self)
        self.__buttonLine1.setFrameShape(QFrame.Shape.VLine)
        self.__buttonLine1.setFrameShadow(QFrame.Shadow.Sunken)
        self.__navButtonsLayout.addWidget(self.__buttonLine1)
        
        self.__zoomInButton = QToolButton(self)
        self.__zoomInButton.setIcon(UI.PixmapCache.getIcon("zoomIn"))
        self.__zoomInButton.setToolTip(
            self.tr("Zoom in on the current page"))
        self.__zoomInButton.clicked.connect(self.__zoomIn)
        self.__navButtonsLayout.addWidget(self.__zoomInButton)
        
        self.__zoomOutButton = QToolButton(self)
        self.__zoomOutButton.setIcon(UI.PixmapCache.getIcon("zoomOut"))
        self.__zoomOutButton.setToolTip(
            self.tr("Zoom out on the current page"))
        self.__zoomOutButton.clicked.connect(self.__zoomOut)
        self.__navButtonsLayout.addWidget(self.__zoomOutButton)
        
        self.__zoomResetButton = QToolButton(self)
        self.__zoomResetButton.setIcon(UI.PixmapCache.getIcon("zoomReset"))
        self.__zoomResetButton.setToolTip(
            self.tr("Reset the zoom level of the current page"))
        self.__zoomResetButton.clicked.connect(self.__zoomReset)
        self.__navButtonsLayout.addWidget(self.__zoomResetButton)
        
        self.__navButtonsLayout.addStretch()
        
        self.__layout.addLayout(self.__navButtonsLayout)
                
        self.__backMenu = QMenu(self)
        self.__backMenu.triggered.connect(self.__navigationMenuActionTriggered)
        self.__backwardButton.setMenu(self.__backMenu)
        self.__backMenu.aboutToShow.connect(self.__showBackMenu)
        
        self.__forwardMenu = QMenu(self)
        self.__forwardMenu.triggered.connect(
            self.__navigationMenuActionTriggered)
        self.__forwardButton.setMenu(self.__forwardMenu)
        self.__forwardMenu.aboutToShow.connect(self.__showForwardMenu)

        ###################################################################
        
        self.__helpStack = QStackedWidget(self)
        self.__helpStack.setSizePolicy(
            QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
        self.__layout.addWidget(self.__helpStack)
        
        ###################################################################
        
        self.__helpNavigationStack = QStackedWidget(self)
        self.__helpNavigationStack.setSizePolicy(
            QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
        self.__helpNavigationStack.setMaximumHeight(200)
        self.__layout.addWidget(self.__helpNavigationStack)
        self.__populateNavigationStack()
        
        ###################################################################
        
        self.__buttonLayout = QHBoxLayout()
        
        self.__buttonGroup = QButtonGroup(self)
        self.__buttonGroup.setExclusive(True)
        self.__buttonGroup.buttonClicked.connect(
            self.__selectNavigationWidget)
        
        self.__buttonLayout.addStretch()
        
        self.__openPagesButton = self.__addNavigationButton(
            "fileMisc", self.tr("Show list of open pages"))
        self.__helpTocButton = self.__addNavigationButton(
            "tableOfContents", self.tr("Show the table of contents"))
        self.__helpIndexButton = self.__addNavigationButton(
            "helpIndex",  self.tr("Show the help document index"))
        self.__helpSearchButton = self.__addNavigationButton(
            "documentFind", self.tr("Show the help search window"))
        self.__openPagesButton.setChecked(True)
        
        self.__buttonLayout.addStretch()
        
        self.__helpFilterWidget = self.__initFilterWidget()
        self.__buttonLayout.addWidget(self.__helpFilterWidget)
        
        self.__layout.addLayout(self.__buttonLayout)
        
        self.__indexingProgressWidget = self.__initIndexingProgress()
        self.__layout.addWidget(self.__indexingProgressWidget)
        self.__indexingProgressWidget.hide()
        
        ###################################################################
        
        self.setLayout(self.__layout)
        
        self.__openPagesButton.setChecked(True)
        
        self.__initHelpEngine()
        
        self.__ui.preferencesChanged.connect(self.__populateHelpSelector)
        
        self.__initActionsMenu()
        
        self.addPage()
        self.__checkActionButtons()
        
        QTimer.singleShot(50, self.__lookForNewDocumentation)
    
    def __addNavigationButton(self, iconName, toolTip):
        """
        Private method to create and add a navigation button.
        
        @param iconName name of the icon
        @type str
        @param toolTip tooltip to be shown
        @type str
        @return reference to the created button
        @rtype QToolButton
        """
        button = QToolButton(self)
        button.setIcon(UI.PixmapCache.getIcon(iconName))
        button.setToolTip(toolTip)
        button.setCheckable(True)
        self.__buttonGroup.addButton(button)
        self.__buttonLayout.addWidget(button)
        
        return button
    
    def __populateNavigationStack(self):
        """
        Private method to populate the stack of navigation widgets.
        """
        # Open Pages
        self.__openPagesList = OpenPagesWidget(self.__helpStack, self)
        self.__openPagesList.currentChanged.connect(self.__checkActionButtons)
        self.__helpNavigationStack.addWidget(self.__openPagesList)
        
        # QtHelp TOC widget
        self.__helpTocWidget = HelpTocWidget(
            self.__helpEngine, internal=True)
        self.__helpTocWidget.escapePressed.connect(self.__activateCurrentPage)
        self.__helpTocWidget.openUrl.connect(self.openUrl)
        self.__helpTocWidget.newTab.connect(self.openUrlNewPage)
        self.__helpTocWidget.newBackgroundTab.connect(
            self.openUrlNewBackgroundPage)
        self.__helpNavigationStack.addWidget(self.__helpTocWidget)
        
        # QtHelp Index widget
        self.__helpIndexWidget = HelpIndexWidget(
            self.__helpEngine, internal=True)
        self.__helpIndexWidget.escapePressed.connect(
            self.__activateCurrentPage)
        self.__helpIndexWidget.openUrl.connect(self.openUrl)
        self.__helpIndexWidget.newTab.connect(self.openUrlNewPage)
        self.__helpIndexWidget.newBackgroundTab.connect(
            self.openUrlNewBackgroundPage)
        self.__helpNavigationStack.addWidget(self.__helpIndexWidget)
        
        # QtHelp Search widget
        self.__indexing = False
        self.__indexingProgress = None
        self.__helpSearchEngine = self.__helpEngine.searchEngine()
        self.__helpSearchEngine.indexingStarted.connect(
            self.__indexingStarted)
        self.__helpSearchEngine.indexingFinished.connect(
            self.__indexingFinished)
        
        self.__helpSearchWidget = HelpSearchWidget(
            self.__helpSearchEngine, internal=True)
        self.__helpSearchWidget.escapePressed.connect(
            self.__activateCurrentPage)
        self.__helpSearchWidget.openUrl.connect(self.openUrl)
        self.__helpSearchWidget.newTab.connect(self.openUrlNewPage)
        self.__helpSearchWidget.newBackgroundTab.connect(
            self.openUrlNewBackgroundPage)
        self.__helpNavigationStack.addWidget(self.__helpSearchWidget)
    
    @pyqtSlot(QAbstractButton)
    def __selectNavigationWidget(self, button):
        """
        Private slot to select the navigation widget.
        
        @param button reference to the clicked button
        @type QAbstractButton
        """
        if button == self.__openPagesButton:
            self.__helpNavigationStack.setCurrentWidget(
                self.__openPagesList)
        elif button == self.__helpTocButton:
            self.__helpNavigationStack.setCurrentWidget(
                self.__helpTocWidget)
        elif button == self.__helpIndexButton:
            self.__helpNavigationStack.setCurrentWidget(
                self.__helpIndexWidget)
        elif button == self.__helpSearchButton:
            self.__helpNavigationStack.setCurrentWidget(
                self.__helpSearchWidget)
    
    def __populateHelpSelector(self):
        """
        Private method to populate the help selection combo box.
        """
        self.__helpSelector.clear()
        
        self.__helpSelector.addItem("", "")
        
        for key, topic in [
            ("EricDocDir", self.tr("eric API Documentation")),
            ("PythonDocDir", self.tr("Python 3 Documentation")),
            ("Qt5DocDir", self.tr("Qt5 Documentation")),
            ("Qt6DocDir", self.tr("Qt6 Documentation")),
            ("PyQt5DocDir", self.tr("PyQt5 Documentation")),
            ("PyQt6DocDir", self.tr("PyQt6 Documentation")),
            ("PySide2DocDir", self.tr("PySide2 Documentation")),
            ("PySide6DocDir", self.tr("PySide6 Documentation")),
        ]:
            urlStr = Preferences.getHelp(key)
            if urlStr:
                self.__helpSelector.addItem(topic, urlStr)
    
    @pyqtSlot()
    def __helpTopicSelected(self):
        """
        Private slot handling the selection of a new help topic.
        """
        urlStr = self.__helpSelector.currentData()
        if urlStr:
            url = QUrl(urlStr)
            self.currentViewer().setUrl(url)
    
    def activate(self, searchWord=None):
        """
        Public method to activate the widget and search for a given word.
        
        @param searchWord word to search for (defaults to None)
        @type str (optional)
        """
        cv = self.currentViewer()
        if cv:
            cv.setFocus(Qt.FocusReason.OtherFocusReason)
        
        if searchWord:
            self.searchQtHelp(searchWord)
    
    def shutdown(self):
        """
        Public method to perform shut down actions.
        """
        self.__helpSearchEngine.cancelIndexing()
        self.__helpSearchEngine.cancelSearching()
        
        self.__helpInstaller.stop()
    
    @pyqtSlot()
    def __openFile(self):
        """
        Private slot to open a local help file (*.html).
        """
        htmlFile = EricFileDialog.getOpenFileName(
            self,
            self.tr("Open HTML File"),
            "",
            self.tr("HTML Files (*.htm *.html);;All Files (*)")
        )
        if htmlFile:
            self.currentViewer().setUrl(QUrl.fromLocalFile(htmlFile))
    
    def addPage(self, url=QUrl("about:blank"), background=False):
        """
        Public method to add a new help page with the given URL.
        
        @param url requested URL (defaults to QUrl("about:blank"))
        @type QUrl (optional)
        @param background flag indicating to open the page in the background
            (defaults to False)
        @type bool (optional)
        """
        viewer = self.__newViewer()
        viewer.setUrl(url)
        
        if background:
            cv = self.currentViewer()
            if cv:
                index = self.__helpStack.indexOf(cv) + 1
                self.__helpStack.insertWidget(index, viewer)
                self.__openPagesList.insertPage(
                    index, viewer, background=background)
                return
        
        self.__helpStack.addWidget(viewer)
        self.__openPagesList.addPage(viewer, background=background)

    @pyqtSlot(QUrl)
    def openUrl(self, url):
        """
        Public slot to load a URL in the current page.
        
        @param url URL to be opened
        @type QUrl
        """
        cv = self.currentViewer()
        if cv:
            cv.setUrl(url)
    
    @pyqtSlot(QUrl)
    def openUrlNewPage(self, url):
        """
        Public slot to load a URL in a new page.
        
        @param url URL to be opened
        @type QUrl
        """
        self.addPage(url=url)
    
    @pyqtSlot(QUrl)
    def openUrlNewBackgroundPage(self, url):
        """
        Public slot to load a URL in a new background page.
        
        @param url URL to be opened
        @type QUrl
        """
        self.addPage(url=url, background=True)
    
    @pyqtSlot()
    def __activateCurrentPage(self):
        """
        Private slot to activate the current page.
        """
        cv = self.currentViewer()
        if cv:
            cv.setFocus()
    
    def __newViewer(self):
        """
        Private method to create a new help viewer.
        
        @return help viewer
        @rtype HelpViewerImpl
        """
        try:
            from .HelpViewerImpl_qwe import HelpViewerImpl_qwe
            viewer = HelpViewerImpl_qwe(self.__helpEngine, self)
        except ImportError:
            from .HelpViewerImpl_qtb import HelpViewerImpl_qtb
            viewer = HelpViewerImpl_qtb(self.__helpEngine, self)
        
        viewer.zoomChanged.connect(self.__checkActionButtons)
        
        return viewer
    
    def currentViewer(self):
        """
        Public method to get the active viewer.
        
        @return reference to the active help viewer
        @rtype HelpViewerImpl
        """
        return self.__helpStack.currentWidget()
    
    #######################################################################
    ## QtHelp related code below
    #######################################################################
    
    def __initHelpEngine(self):
        """
        Private method to initialize the QtHelp related stuff.
        """
        self.__helpEngine = QHelpEngine(
            self.__getQtHelpCollectionFileName(),
            self)
        self.__helpEngine.setReadOnly(False)
        self.__helpEngine.setUsesFilterEngine(True)
        self.__helpEngine.setupData()
        self.__removeOldDocumentation()
        self.__helpEngine.warning.connect(self.__warning)
    
    def __getQtHelpCollectionFileName(cls):
        """
        Private method to determine the name of the QtHelp collection file.
        
        @return path of the QtHelp collection file
        @rtype str
        """
        qthelpDir = os.path.join(Utilities.getConfigDir(), "qthelp")
        if not os.path.exists(qthelpDir):
            os.makedirs(qthelpDir)
        return os.path.join(qthelpDir, "eric7help.qhc")
    
    @pyqtSlot(str)
    def __warning(self, msg):
        """
        Private slot handling warnings of the help engine.
        
        @param msg message sent by the help  engine
        @type str
        """
        EricMessageBox.warning(
            self,
            self.tr("Help Engine"), msg)
    
    @pyqtSlot()
    def __removeOldDocumentation(self):
        """
        Private slot to remove non-existing documentation from the help engine.
        """
        for namespace in self.__helpEngine.registeredDocumentations():
            docFile = self.__helpEngine.documentationFileName(namespace)
            if not os.path.exists(docFile):
                self.__helpEngine.unregisterDocumentation(namespace)
    
    @pyqtSlot()
    def __lookForNewDocumentation(self):
        """
        Private slot to look for new documentation to be loaded into the
        help database.
        """
        from WebBrowser.QtHelp.HelpDocsInstaller import HelpDocsInstaller
        self.__helpInstaller = HelpDocsInstaller(
            self.__helpEngine.collectionFile())
        self.__helpInstaller.errorMessage.connect(
            self.__showInstallationError)
        self.__helpInstaller.docsInstalled.connect(self.__docsInstalled)
        
        self.__ui.statusBar().showMessage(
            self.tr("Looking for Documentation..."))
        self.__helpInstaller.installDocs()
    
    @pyqtSlot(str)
    def __showInstallationError(self, message):
        """
        Private slot to show installation errors.
        
        @param message message to be shown
        @type str
        """
        EricMessageBox.warning(
            self,
            self.tr("eric Web Browser"),
            message)
    
    @pyqtSlot(bool)
    def __docsInstalled(self, installed):
        """
        Private slot handling the end of documentation installation.
        
        @param installed flag indicating that documents were installed
        @type bool
        """
        self.__ui.statusBar().clearMessage()
        self.__helpEngine.setupData()
    
    @pyqtSlot()
    def __manageQtHelpDocuments(self):
        """
        Private slot to manage the QtHelp documentation database.
        """
        from WebBrowser.QtHelp.QtHelpDocumentationConfigurationDialog import (
            QtHelpDocumentationConfigurationDialog
        )
        dlg = QtHelpDocumentationConfigurationDialog(
            self.__helpEngine, self)
        dlg.exec()
    
    @pyqtSlot()
    def __reindexDocumentation(self):
        """
        Private slot 
        """
    
    #######################################################################
    ## Actions Menu related methods
    #######################################################################
    
    def __initActionsMenu(self):
        """
        Private method to initialize the actions menu.
        """
        self.__actionsMenu = QMenu()
        self.__actionsMenu.setToolTipsVisible(True)
        
        self.__actionsMenu.addAction(self.tr("Manage QtHelp Documents"),
                                     self.__manageQtHelpDocuments)
        act = self.__actionsMenu.addAction(self.tr("Reindex Documentation"),
                                           self.__reindexDocumentation)
        act.triggered.connect(self.__helpSearchEngine.reindexDocumentation)
        
        self.__actionsButton.setMenu(self.__actionsMenu)
    
    #######################################################################
    ## Navigation related methods below
    #######################################################################
    
    @pyqtSlot()
    def __backward(self):
        """
        Private slot to move one page backward.
        """
        cv = self.currentViewer()
        if cv:
            cv.backward()
    
    @pyqtSlot()
    def __forward(self):
        """
        Private slot to move one page foreward.
        """
        cv = self.currentViewer()
        if cv:
            cv.forward()
    
    @pyqtSlot()
    def __reload(self):
        """
        Private slot to reload the current page.
        """
        cv = self.currentViewer()
        if cv:
            cv.reload()
    
    @pyqtSlot()
    def __checkActionButtons(self):
        """
        Private slot to set the enabled state of the action buttons.
        """
        cv = self.currentViewer()
        if cv:
            self.__backwardButton.setEnabled(cv.isBackwardAvailable())
            self.__forwardButton.setEnabled(cv.isForwardAvailable())
            self.__zoomInButton.setEnabled(cv.isScaleUpAvailable())
            self.__zoomOutButton.setEnabled(cv.isScaleDownAvailable())
        else:
            self.__backwardButton.setEnabled(False)
            self.__forwardButton.setEnabled(False)
            self.__zoomInButton.setEnabled(False)
            self.__zoomOutButton.setEnabled(False)
    
    def __showBackMenu(self):
        """
        Private slot showing the backward navigation menu.
        """
        cv = self.currentViewer()
        if cv:
            self.__backMenu.clear()
            backwardHistoryCount = min(cv.backwardHistoryCount(), 20)
            # show max. 20 items
            
            for index in range(1, backwardHistoryCount + 1):
                act = QAction(self)
                act.setData(-index)
                act.setText(cv.historyTitle(-index))
                self.__backMenu.addAction(act)
            
            self.__backMenu.addSeparator()
            self.__backMenu.addAction(self.tr("Clear History"),
                                      self.__clearHistory)
    
    def __showForwardMenu(self):
        """
        Private slot showing the forward navigation menu.
        """
        cv = self.currentViewer()
        if cv:
            self.__forwardMenu.clear()
            forwardHistoryCount = min(cv.forwardHistoryCount(), 20)
            # show max. 20 items
        
            for index in range(1, forwardHistoryCount + 1):
                act = QAction(self)
                act.setData(index)
                act.setText(cv.historyTitle(index))
                self.__forwardMenu.addAction(act)
            
            self.__forwardMenu.addSeparator()
            self.__forwardMenu.addAction(self.tr("Clear History"),
                                         self.__clearHistory)
    
    def __navigationMenuActionTriggered(self, act):
        """
        Private slot to go to the selected page.
        
        @param act reference to the action selected in the navigation menu
        @type QAction
        """
        cv = self.currentViewer()
        if cv:
            index = act.data()
            if index is not None:
                cv.gotoHistory(index)
    
    def __clearHistory(self):
        """
        Private slot to clear the history of the current viewer.
        """
        cv = self.currentViewer()
        if cv:
            cv.clearHistory()
            self.__checkActionButtons()
    
    #######################################################################
    ## Zoom related methods below
    #######################################################################
    
    @pyqtSlot()
    def __zoomIn(self):
        """
        Private slot to zoom in.
        """
        cv = self.currentViewer()
        if cv:
            cv.scaleUp()
    
    @pyqtSlot()
    def __zoomOut(self):
        """
        Private slot to zoom out.
        """
        cv = self.currentViewer()
        if cv:
            cv.scaleDown()
    
    @pyqtSlot()
    def __zoomReset(self):
        """
        Private slot to reset the zoom level.
        """
        cv = self.currentViewer()
        if cv:
            cv.resetScale()
    
    #######################################################################
    ## QtHelp Search related methods below
    #######################################################################
    
    def __initIndexingProgress(self):
        """
        Private method to initialize the help documents indexing progress
        widget.
        
        @return reference to the generated widget
        @rtype QWidget
        """
        progressWidget = QWidget(self)
        layout = QHBoxLayout(progressWidget)
        layout.setContentsMargins(0, 0, 0, 0)
        
        label = QLabel(self.tr("Updating search index"))
        layout.addWidget(label)
        
        progressBar = QProgressBar()
        progressBar.setRange(0, 0)
        progressBar.setTextVisible(False)
        progressBar.setFixedHeight(16)
        layout.addWidget(progressBar)
        
        return progressWidget
    
    @pyqtSlot()
    def __indexingStarted(self):
        """
        Private slot handling the start of the indexing process.
        """
        self.__indexing = True
        self.__indexingProgressWidget.show()
    
    @pyqtSlot()
    def __indexingFinished(self):
        """
        Private slot handling the end of the indexing process.
        """
        self.__indexingProgressWidget.hide()
        self.__indexing = False
    
    @pyqtSlot(str)
    def searchQtHelp(self, searchExpression):
        """
        Public slot to search for a given search expression.
        
        @param searchExpression expression to search for
        @type str
        """
        if searchExpression:
            if self.__indexing:
                # Try again a second later
                QTimer.singleShot(
                    1000,
                    lambda: self.searchQtHelp(searchExpression)
                )
            else:
                self.__helpSearchButton.setChecked(True)
                self.__helpSearchEngine.search(searchExpression)
    
    #######################################################################
    ## QtHelp filter related methods below
    #######################################################################
    
    def __initFilterWidget(self):
        """
        Private method to initialize the filter selection widget.
        
        @return reference to the generated widget
        @rtype QWidget
        """
        filterWidget = QWidget()
        layout = QHBoxLayout(filterWidget)
        layout.setContentsMargins(0, 0, 0, 0)
        
        label = QLabel(self.tr("Filtered by: "))
        layout.addWidget(label)
        
        self.__helpFilterCombo = QComboBox()
        comboWidth = QFontMetrics(QFont()).horizontalAdvance(
            "ComboBoxWithEnoughWidth")
        self.__helpFilterCombo.setMinimumWidth(comboWidth)
        layout.addWidget(self.__helpFilterCombo)
        
        self.__helpEngine.setupFinished.connect(self.__setupFilterCombo)
        self.__helpFilterCombo.currentIndexChanged.connect(
            self.__filterQtHelpDocumentation)
        
        self.__setupFilterCombo()
        
        return filterWidget
    
    @pyqtSlot()
    def __setupFilterCombo(self):
        """
        Private slot to setup the filter combo box.
        """
        activeFilter = self.__helpFilterCombo.currentText()
        if not activeFilter:
            activeFilter = self.__helpEngine.filterEngine().activeFilter()
        if not activeFilter:
            activeFilter = self.tr("Unfiltered")
        allFilters = self.__helpEngine.filterEngine().filters()
        
        blocked = self.__helpFilterCombo.blockSignals(True)
        self.__helpFilterCombo.clear()
        self.__helpFilterCombo.addItem(self.tr("Unfiltered"))
        if allFilters:
            self.__helpFilterCombo.insertSeparator(1)
            for helpFilter in sorted(allFilters):
                self.__helpFilterCombo.addItem(helpFilter, helpFilter)
        self.__helpFilterCombo.blockSignals(blocked)
        
        self.__helpFilterCombo.setCurrentText(activeFilter)
    
    @pyqtSlot(int)
    def __filterQtHelpDocumentation(self, index):
        """
        Private slot to filter the QtHelp documentation.
        
        @param index index of the selected QtHelp documentation filter
        @type int
        """
        if self.__helpEngine:
            helpFilter = self.__helpFilterCombo.itemData(index)
            self.__helpEngine.filterEngine().setActiveFilter(helpFilter)

eric ide

mercurial