WebBrowser/QtHelp/HelpIndexWidget.py

changeset 5038
df7103c3f2a6
parent 4875
4ee26909ac0d
child 5252
321c2003745d
equal deleted inserted replaced
5037:b2b37d7c0791 5038:df7103c3f2a6
9 9
10 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11 11
12 from PyQt5.QtCore import pyqtSignal, Qt, QUrl, QEvent 12 from PyQt5.QtCore import pyqtSignal, Qt, QUrl, QEvent
13 from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QMenu, \ 13 from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QMenu, \
14 QDialog 14 QDialog, QApplication
15 15
16 16
17 class HelpIndexWidget(QWidget): 17 class HelpIndexWidget(QWidget):
18 """ 18 """
19 Class implementing a window for showing the QtHelp index. 19 Class implementing a window for showing the QtHelp index.
20 20
21 @signal linkActivated(QUrl) emitted when an index entry is activated
22 @signal linksActivated(links, keyword) emitted when an index entry
23 referencing multiple targets is activated
24 @signal escapePressed() emitted when the ESC key was pressed 21 @signal escapePressed() emitted when the ESC key was pressed
22 @signal openUrl(QUrl, str) emitted to open an entry in the current tab
23 @signal newTab(QUrl, str) emitted to open an entry in a new tab
24 @signal newBackgroundTab(QUrl, str) emitted to open an entry in a
25 new background tab
26 @signal newWindow(QUrl, str) emitted to open an entry in a new window
25 """ 27 """
26 linkActivated = pyqtSignal(QUrl)
27 linksActivated = pyqtSignal(dict, str)
28 escapePressed = pyqtSignal() 28 escapePressed = pyqtSignal()
29 29 openUrl = pyqtSignal(QUrl)
30 def __init__(self, engine, mainWindow, parent=None): 30 newTab = pyqtSignal(QUrl)
31 newBackgroundTab = pyqtSignal(QUrl)
32 newWindow = pyqtSignal(QUrl)
33
34 def __init__(self, engine, parent=None):
31 """ 35 """
32 Constructor 36 Constructor
33 37
34 @param engine reference to the help engine (QHelpEngine) 38 @param engine reference to the help engine (QHelpEngine)
35 @param mainWindow reference to the main window object (QMainWindow)
36 @param parent reference to the parent widget (QWidget) 39 @param parent reference to the parent widget (QWidget)
37 """ 40 """
38 super(HelpIndexWidget, self).__init__(parent) 41 super(HelpIndexWidget, self).__init__(parent)
39 42
40 self.__engine = engine 43 self.__engine = engine
41 self.__mw = mainWindow
42 44
43 self.__searchEdit = None 45 self.__searchEdit = None
44 self.__index = None 46 self.__index = None
45 47
46 self.__layout = QVBoxLayout(self) 48 self.__layout = QVBoxLayout(self)
53 self.__searchEdit.installEventFilter(self) 55 self.__searchEdit.installEventFilter(self)
54 self.__layout.addWidget(self.__searchEdit) 56 self.__layout.addWidget(self.__searchEdit)
55 57
56 self.__index = self.__engine.indexWidget() 58 self.__index = self.__engine.indexWidget()
57 self.__index.installEventFilter(self) 59 self.__index.installEventFilter(self)
60 self.__index.setContextMenuPolicy(Qt.CustomContextMenu)
61
58 self.__engine.indexModel().indexCreationStarted.connect( 62 self.__engine.indexModel().indexCreationStarted.connect(
59 self.__disableSearchEdit) 63 self.__disableSearchEdit)
60 self.__engine.indexModel().indexCreated.connect( 64 self.__engine.indexModel().indexCreated.connect(
61 self.__enableSearchEdit) 65 self.__enableSearchEdit)
62 self.__index.activated.connect(self.__activated) 66 self.__index.activated.connect(self.__activated)
67 self.__index.customContextMenuRequested.connect(
68 self.__showContextMenu)
63 self.__searchEdit.returnPressed.connect( 69 self.__searchEdit.returnPressed.connect(
64 self.__index.activateCurrentItem) 70 self.__index.activateCurrentItem)
65 self.__layout.addWidget(self.__index) 71 self.__layout.addWidget(self.__index)
66 72
67 self.__index.viewport().installEventFilter(self) 73 self.__index.viewport().installEventFilter(self)
68 74
69 def __activated(self, idx): 75 def __activated(self, idx, midButton=False):
70 """ 76 """
71 Private slot to handle the activation of a keyword entry. 77 Private slot to handle the activation of a keyword entry.
72 78
73 @param idx index of the activated entry (QModelIndex) 79 @param idx index of the activated entry
80 @type QModelIndex
81 @param midButton flag indicating a middle mouse button release
82 @type bool
74 """ 83 """
75 model = self.__index.model() 84 model = self.__index.model()
76 if model is not None: 85 if model is not None:
86 modifiers = QApplication.keyboardModifiers()
77 keyword = model.data(idx, Qt.DisplayRole) 87 keyword = model.data(idx, Qt.DisplayRole)
78 links = model.linksForKeyword(keyword) 88 links = model.linksForKeyword(keyword)
79 if len(links) == 1: 89 if len(links) == 1:
80 self.linkActivated.emit(QUrl(links[list(links.keys())[0]])) 90 link = QUrl(links[list(links.keys())[0]])
81 else: 91 else:
82 self.linksActivated.emit(links, keyword) 92 link = self.__selectLink(links, keyword)
93 if not link.isEmpty() and link.isValid():
94 if modifiers & Qt.ControlModifier or midButton:
95 self.newTab.emit(link)
96 elif modifiers & Qt.ShiftModifier:
97 self.newWindow.emit(link)
98 else:
99 self.openUrl.emit(link)
100
101 def __selectLink(self, links, keyword):
102 """
103 Private method to give the user a chance to select among the
104 returned links.
105
106 @param links dictionary of document title and URL to select from
107 @type dictionary of str (key) and QUrl (value)
108 @param keyword keyword for the link set
109 @type str
110 @return selected link
111 @rtype QUrl
112 """
113 link = QUrl()
114 from .HelpTopicDialog import HelpTopicDialog
115 dlg = HelpTopicDialog(self, keyword, links)
116 if dlg.exec_() == QDialog.Accepted:
117 link = dlg.link()
118 return link
83 119
84 def __filterIndices(self, filter): 120 def __filterIndices(self, filter):
85 """ 121 """
86 Private slot to filter the indices according to the given filter. 122 Private slot to filter the indices according to the given filter.
87 123
136 idx.row() + 1, idx.column(), idx.parent()) 172 idx.row() + 1, idx.column(), idx.parent())
137 if idx.isValid(): 173 if idx.isValid():
138 self.__index.setCurrentIndex(idx) 174 self.__index.setCurrentIndex(idx)
139 elif event.key() == Qt.Key_Escape: 175 elif event.key() == Qt.Key_Escape:
140 self.escapePressed.emit() 176 self.escapePressed.emit()
141 elif self.__index and watched == self.__index and \
142 event.type() == QEvent.ContextMenu:
143 idx = self.__index.indexAt(event.pos())
144 if idx.isValid():
145 menu = QMenu()
146 curTab = menu.addAction(self.tr("Open Link"))
147 newTab = menu.addAction(self.tr("Open Link in New Tab"))
148 menu.move(self.__index.mapToGlobal(event.pos()))
149
150 act = menu.exec_()
151 if act == curTab:
152 self.__activated(idx)
153 elif act == newTab:
154 model = self.__index.model()
155 if model is not None:
156 keyword = model.data(idx, Qt.DisplayRole)
157 links = model.linksForKeyword(keyword)
158 if len(links) == 1:
159 self.__mw.newTab(list(links.values())[0])
160 elif len(links) > 1:
161 from .HelpTopicDialog import HelpTopicDialog
162 dlg = HelpTopicDialog(self, keyword, links)
163 if dlg.exec_() == QDialog.Accepted:
164 self.__mw.newTab(dlg.link())
165 elif self.__index and watched == self.__index.viewport() and \ 177 elif self.__index and watched == self.__index.viewport() and \
166 event.type() == QEvent.MouseButtonRelease: 178 event.type() == QEvent.MouseButtonRelease:
167 idx = self.__index.indexAt(event.pos()) 179 idx = self.__index.indexAt(event.pos())
168 if idx.isValid() and event.button() == Qt.MidButton: 180 if idx.isValid():
169 model = self.__index.model() 181 self.__activated(idx, midButton=event.button() == Qt.MidButton)
170 if model is not None:
171 keyword = model.data(idx, Qt.DisplayRole)
172 links = model.linksForKeyword(keyword)
173 if len(links) == 1:
174 self.__mw.newTab(list(links.values())[0])
175 elif len(links) > 1:
176 from .HelpTopicDialog import HelpTopicDialog
177 dlg = HelpTopicDialog(self, keyword, links)
178 if dlg.exec_() == QDialog.Accepted:
179 self.__mw.newTab(dlg.link())
180 182
181 return QWidget.eventFilter(self, watched, event) 183 return QWidget.eventFilter(self, watched, event)
184
185 def __showContextMenu(self, pos):
186 """
187 Private slot showing the context menu.
188
189 @param pos position to show the menu at (QPoint)
190 """
191 idx = self.__index.indexAt(pos)
192 if idx.isValid():
193 menu = QMenu()
194 curTab = menu.addAction(self.tr("Open Link"))
195 newTab = menu.addAction(self.tr("Open Link in New Tab"))
196 newBackgroundTab = menu.addAction(
197 self.tr("Open Link in Background Tab"))
198 newWindow = menu.addAction(self.tr("Open Link in New Window"))
199 menu.move(self.__index.mapToGlobal(pos))
200
201 act = menu.exec_()
202 model = self.__index.model()
203 if model is not None:
204 keyword = model.data(idx, Qt.DisplayRole)
205 links = model.linksForKeyword(keyword)
206 if len(links) == 1:
207 link = QUrl(links[list(links.keys())[0]])
208 else:
209 link = self.__selectLink(links, keyword)
210
211 if act == curTab:
212 self.openUrl.emit(link)
213 elif act == newTab:
214 self.newTab.emit(link)
215 elif act == newBackgroundTab:
216 self.newBackgroundTab.emit(link)
217 elif act == newWindow:
218 self.newWindow.emit(link)

eric ide

mercurial