--- a/Helpviewer/HelpIndexWidget.py Mon Oct 17 18:57:24 2016 +0200 +++ b/Helpviewer/HelpIndexWidget.py Mon Oct 17 19:51:51 2016 +0200 @@ -9,9 +9,9 @@ from __future__ import unicode_literals -from PyQt5.QtCore import pyqtSignal, Qt, QUrl, QEvent +from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QUrl, QEvent from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QMenu, \ - QDialog + QDialog, QApplication class HelpIndexWidget(QWidget): @@ -54,32 +54,73 @@ 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.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) - - self.__index.viewport().installEventFilter(self) - def __activated(self, idx): + @pyqtSlot(QUrl, str) + def __linkActivated(self, url, keyword, modifiers=None): """ Private slot to handle the activation of a keyword entry. - @param idx index of the activated entry (QModelIndex) + @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: + self.__mw.newTab(url) + else: + self.linkActivated.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 """ - model = self.__index.model() - if model is not None: - keyword = model.data(idx, Qt.DisplayRole) - links = model.linksForKeyword(keyword) - if len(links) == 1: - self.linkActivated.emit(QUrl(links[list(links.keys())[0]])) - else: - self.linksActivated.emit(links, keyword) + 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, filter): """ @@ -138,44 +179,34 @@ self.__index.setCurrentIndex(idx) elif event.key() == Qt.Key_Escape: self.escapePressed.emit() - elif self.__index and watched == self.__index and \ - event.type() == QEvent.ContextMenu: - idx = self.__index.indexAt(event.pos()) - if idx.isValid(): - menu = QMenu() - curTab = menu.addAction(self.tr("Open Link")) - newTab = menu.addAction(self.tr("Open Link in New Tab")) - menu.move(self.__index.mapToGlobal(event.pos())) - - act = menu.exec_() - if act == curTab: - self.__activated(idx) - elif act == newTab: - model = self.__index.model() - if model is not None: - keyword = model.data(idx, Qt.DisplayRole) - links = model.linksForKeyword(keyword) - if len(links) == 1: - self.__mw.newTab(list(links.values())[0]) - elif len(links) > 1: - from .HelpTopicDialog import HelpTopicDialog - dlg = HelpTopicDialog(self, keyword, links) - if dlg.exec_() == QDialog.Accepted: - self.__mw.newTab(dlg.link()) - elif self.__index and watched == self.__index.viewport() and \ - event.type() == QEvent.MouseButtonRelease: - idx = self.__index.indexAt(event.pos()) - if idx.isValid() and event.button() == Qt.MidButton: - model = self.__index.model() - if model is not None: - keyword = model.data(idx, Qt.DisplayRole) - links = model.linksForKeyword(keyword) - if len(links) == 1: - self.__mw.newTab(list(links.values())[0]) - elif len(links) > 1: - from .HelpTopicDialog import HelpTopicDialog - dlg = HelpTopicDialog(self, keyword, links) - if dlg.exec_() == QDialog.Accepted: - self.__mw.newTab(dlg.link()) 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")) + 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.linkActivated.emit(link) + elif act == newTab: + self.__mw.newTab(link)