WebBrowser/QtHelp/HelpIndexWidget.py

Sun, 17 Jul 2016 15:36:11 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 17 Jul 2016 15:36:11 +0200
changeset 5038
df7103c3f2a6
parent 4875
4ee26909ac0d
child 5252
321c2003745d
permissions
-rw-r--r--

Added capabilities to open links in a new background tab, and several other link open actions to various context menus of the new web browser.

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

# Copyright (c) 2009 - 2016 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, 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.installEventFilter(self)
        self.__index.setContextMenuPolicy(Qt.CustomContextMenu)
        
        self.__engine.indexModel().indexCreationStarted.connect(
            self.__disableSearchEdit)
        self.__engine.indexModel().indexCreated.connect(
            self.__enableSearchEdit)
        self.__index.activated.connect(self.__activated)
        self.__index.customContextMenuRequested.connect(
            self.__showContextMenu)
        self.__searchEdit.returnPressed.connect(
            self.__index.activateCurrentItem)
        self.__layout.addWidget(self.__index)
        
        self.__index.viewport().installEventFilter(self)
    
    def __activated(self, idx, midButton=False):
        """
        Private slot to handle the activation of a keyword entry.
        
        @param idx index of the activated entry
        @type QModelIndex
        @param midButton flag indicating a middle mouse button release
        @type bool
        """
        model = self.__index.model()
        if model is not None:
            modifiers = QApplication.keyboardModifiers()
            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 modifiers & Qt.ControlModifier or midButton:
                    self.newTab.emit(link)
                elif modifiers & Qt.ShiftModifier:
                    self.newWindow.emit(link)
                else:
                    self.openUrl.emit(link)
    
    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, filter):
        """
        Private slot to filter the indices according to the given filter.
        
        @param filter filter to be used (string)
        """
        if '*' in filter:
            self.__index.filterIndices(filter, filter)
        else:
            self.__index.filterIndices(filter)
    
    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()
        elif self.__index and watched == self.__index.viewport() and \
                event.type() == QEvent.MouseButtonRelease:
            idx = self.__index.indexAt(event.pos())
            if idx.isValid():
                self.__activated(idx, midButton=event.button() == Qt.MidButton)
        
        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 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