eric6/WebBrowser/QtHelp/HelpIndexWidget.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/WebBrowser/QtHelp/HelpIndexWidget.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,227 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2009 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a window for showing the QtHelp index.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QUrl, QEvent
+from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QMenu, \
+    QDialog, QApplication
+
+
+class HelpIndexWidget(QWidget):
+    """
+    Class implementing a window for showing the QtHelp index.
+    
+    @signal escapePressed() emitted when the ESC key was pressed
+    @signal openUrl(QUrl, str) emitted to open an entry in the current tab
+    @signal newTab(QUrl, str) emitted to open an entry in a new tab
+    @signal newBackgroundTab(QUrl, str) emitted to open an entry in a
+        new background tab
+    @signal newWindow(QUrl, str) emitted to open an entry in a new window
+    """
+    escapePressed = pyqtSignal()
+    openUrl = pyqtSignal(QUrl)
+    newTab = pyqtSignal(QUrl)
+    newBackgroundTab = pyqtSignal(QUrl)
+    newWindow = pyqtSignal(QUrl)
+    
+    def __init__(self, engine, parent=None):
+        """
+        Constructor
+        
+        @param engine reference to the help engine (QHelpEngine)
+        @param parent reference to the parent widget (QWidget)
+        """
+        super(HelpIndexWidget, self).__init__(parent)
+        
+        self.__engine = engine
+        
+        self.__searchEdit = None
+        self.__index = None
+        
+        self.__layout = QVBoxLayout(self)
+        label = QLabel(self.tr("&Look for:"))
+        self.__layout.addWidget(label)
+        
+        self.__searchEdit = QLineEdit()
+        label.setBuddy(self.__searchEdit)
+        self.__searchEdit.textChanged.connect(self.__filterIndices)
+        self.__searchEdit.installEventFilter(self)
+        self.__layout.addWidget(self.__searchEdit)
+        
+        self.__index = self.__engine.indexWidget()
+        self.__index.setContextMenuPolicy(Qt.CustomContextMenu)
+        
+        self.__engine.indexModel().indexCreationStarted.connect(
+            self.__disableSearchEdit)
+        self.__engine.indexModel().indexCreated.connect(
+            self.__enableSearchEdit)
+        self.__index.linkActivated.connect(self.__linkActivated)
+        self.__index.linksActivated.connect(self.__linksActivated)
+        self.__index.customContextMenuRequested.connect(
+            self.__showContextMenu)
+        self.__searchEdit.returnPressed.connect(
+            self.__index.activateCurrentItem)
+        self.__layout.addWidget(self.__index)
+    
+    @pyqtSlot(QUrl, str)
+    def __linkActivated(self, url, keyword, modifiers=None):
+        """
+        Private slot to handle the activation of a keyword entry.
+        
+        @param url URL of the selected entry
+        @type QUrl
+        @param keyword keyword for the URL
+        @type str
+        @keyparam modifiers keyboard modifiers
+        @type Qt.KeyboardModifiers or None
+        """
+        if modifiers is None:
+            modifiers = QApplication.keyboardModifiers()
+        if not url.isEmpty() and url.isValid():
+            if modifiers & (Qt.ControlModifier | Qt.ShiftModifier) == \
+                    (Qt.ControlModifier | Qt.ShiftModifier):
+                self.newBackgroundTab.emit(url)
+            elif modifiers & Qt.ControlModifier:
+                self.newTab.emit(url)
+            elif modifiers & Qt.ShiftModifier:
+                self.newWindow.emit(url)
+            else:
+                self.openUrl.emit(url)
+    
+    def __linksActivated(self, links, keyword):
+        """
+        Private slot to handle the activation of an entry with multiple links.
+        
+        @param links dictionary containing the links
+        @type dict of key:str and value:QUrl
+        @param keyword keyword for the entry
+        @type str
+        """
+        modifiers = QApplication.keyboardModifiers()
+        if len(links) == 1:
+            url = QUrl(links[list(links.keys())[0]])
+        else:
+            url = self.__selectLink(links, keyword)
+        self.__linkActivated(url, keyword, modifiers)
+    
+    def __selectLink(self, links, keyword):
+        """
+        Private method to give the user a chance to select among the
+        returned links.
+        
+        @param links dictionary of document title and URL to select from
+        @type dictionary of str (key) and QUrl (value)
+        @param keyword keyword for the link set
+        @type str
+        @return selected link
+        @rtype QUrl
+        """
+        link = QUrl()
+        from .HelpTopicDialog import HelpTopicDialog
+        dlg = HelpTopicDialog(self, keyword, links)
+        if dlg.exec_() == QDialog.Accepted:
+            link = dlg.link()
+        return link
+    
+    def __filterIndices(self, indexFilter):
+        """
+        Private slot to filter the indexes according to the given filter.
+        
+        @param indexFilter filter to be used (string)
+        """
+        if '*' in indexFilter:
+            self.__index.filterIndices(indexFilter, indexFilter)
+        else:
+            self.__index.filterIndices(indexFilter)
+    
+    def __enableSearchEdit(self):
+        """
+        Private slot to enable the search edit.
+        """
+        self.__searchEdit.setEnabled(True)
+        self.__filterIndices(self.__searchEdit.text())
+    
+    def __disableSearchEdit(self):
+        """
+        Private slot to enable the search edit.
+        """
+        self.__searchEdit.setEnabled(False)
+    
+    def focusInEvent(self, evt):
+        """
+        Protected method handling focus in events.
+        
+        @param evt reference to the focus event object (QFocusEvent)
+        """
+        if evt.reason() != Qt.MouseFocusReason:
+            self.__searchEdit.selectAll()
+            self.__searchEdit.setFocus()
+    
+    def eventFilter(self, watched, event):
+        """
+        Public method called to filter the event queue.
+        
+        @param watched the QObject being watched (QObject)
+        @param event the event that occurred (QEvent)
+        @return flag indicating whether the event was handled (boolean)
+        """
+        if self.__searchEdit and watched == self.__searchEdit and \
+           event.type() == QEvent.KeyPress:
+            idx = self.__index.currentIndex()
+            if event.key() == Qt.Key_Up:
+                idx = self.__index.model().index(
+                    idx.row() - 1, idx.column(), idx.parent())
+                if idx.isValid():
+                    self.__index.setCurrentIndex(idx)
+            elif event.key() == Qt.Key_Down:
+                idx = self.__index.model().index(
+                    idx.row() + 1, idx.column(), idx.parent())
+                if idx.isValid():
+                    self.__index.setCurrentIndex(idx)
+            elif event.key() == Qt.Key_Escape:
+                self.escapePressed.emit()
+        
+        return QWidget.eventFilter(self, watched, event)
+    
+    def __showContextMenu(self, pos):
+        """
+        Private slot showing the context menu.
+        
+        @param pos position to show the menu at (QPoint)
+        """
+        idx = self.__index.indexAt(pos)
+        if idx.isValid():
+            menu = QMenu()
+            curTab = menu.addAction(self.tr("Open Link"))
+            newTab = menu.addAction(self.tr("Open Link in New Tab"))
+            newBackgroundTab = menu.addAction(
+                self.tr("Open Link in Background Tab"))
+            newWindow = menu.addAction(self.tr("Open Link in New Window"))
+            menu.move(self.__index.mapToGlobal(pos))
+            
+            act = menu.exec_()
+            model = self.__index.model()
+            if model is not None:
+                keyword = model.data(idx, Qt.DisplayRole)
+                links = model.linksForKeyword(keyword)
+                if len(links) == 1:
+                    link = QUrl(links[list(links.keys())[0]])
+                else:
+                    link = self.__selectLink(links, keyword)
+                
+                if not link.isEmpty() and link.isValid():
+                    if act == curTab:
+                        self.openUrl.emit(link)
+                    elif act == newTab:
+                        self.newTab.emit(link)
+                    elif act == newBackgroundTab:
+                        self.newBackgroundTab.emit(link)
+                    elif act == newWindow:
+                        self.newWindow.emit(link)

eric ide

mercurial