eric6/WebBrowser/QtHelp/HelpIndexWidget.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a window for showing the QtHelp index.
8 """
9
10 from __future__ import unicode_literals
11
12 from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QUrl, QEvent
13 from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QMenu, \
14 QDialog, QApplication
15
16
17 class HelpIndexWidget(QWidget):
18 """
19 Class implementing a window for showing the QtHelp index.
20
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
27 """
28 escapePressed = pyqtSignal()
29 openUrl = pyqtSignal(QUrl)
30 newTab = pyqtSignal(QUrl)
31 newBackgroundTab = pyqtSignal(QUrl)
32 newWindow = pyqtSignal(QUrl)
33
34 def __init__(self, engine, parent=None):
35 """
36 Constructor
37
38 @param engine reference to the help engine (QHelpEngine)
39 @param parent reference to the parent widget (QWidget)
40 """
41 super(HelpIndexWidget, self).__init__(parent)
42
43 self.__engine = engine
44
45 self.__searchEdit = None
46 self.__index = None
47
48 self.__layout = QVBoxLayout(self)
49 label = QLabel(self.tr("&Look for:"))
50 self.__layout.addWidget(label)
51
52 self.__searchEdit = QLineEdit()
53 label.setBuddy(self.__searchEdit)
54 self.__searchEdit.textChanged.connect(self.__filterIndices)
55 self.__searchEdit.installEventFilter(self)
56 self.__layout.addWidget(self.__searchEdit)
57
58 self.__index = self.__engine.indexWidget()
59 self.__index.setContextMenuPolicy(Qt.CustomContextMenu)
60
61 self.__engine.indexModel().indexCreationStarted.connect(
62 self.__disableSearchEdit)
63 self.__engine.indexModel().indexCreated.connect(
64 self.__enableSearchEdit)
65 self.__index.linkActivated.connect(self.__linkActivated)
66 self.__index.linksActivated.connect(self.__linksActivated)
67 self.__index.customContextMenuRequested.connect(
68 self.__showContextMenu)
69 self.__searchEdit.returnPressed.connect(
70 self.__index.activateCurrentItem)
71 self.__layout.addWidget(self.__index)
72
73 @pyqtSlot(QUrl, str)
74 def __linkActivated(self, url, keyword, modifiers=None):
75 """
76 Private slot to handle the activation of a keyword entry.
77
78 @param url URL of the selected entry
79 @type QUrl
80 @param keyword keyword for the URL
81 @type str
82 @keyparam modifiers keyboard modifiers
83 @type Qt.KeyboardModifiers or None
84 """
85 if modifiers is None:
86 modifiers = QApplication.keyboardModifiers()
87 if not url.isEmpty() and url.isValid():
88 if modifiers & (Qt.ControlModifier | Qt.ShiftModifier) == \
89 (Qt.ControlModifier | Qt.ShiftModifier):
90 self.newBackgroundTab.emit(url)
91 elif modifiers & Qt.ControlModifier:
92 self.newTab.emit(url)
93 elif modifiers & Qt.ShiftModifier:
94 self.newWindow.emit(url)
95 else:
96 self.openUrl.emit(url)
97
98 def __linksActivated(self, links, keyword):
99 """
100 Private slot to handle the activation of an entry with multiple links.
101
102 @param links dictionary containing the links
103 @type dict of key:str and value:QUrl
104 @param keyword keyword for the entry
105 @type str
106 """
107 modifiers = QApplication.keyboardModifiers()
108 if len(links) == 1:
109 url = QUrl(links[list(links.keys())[0]])
110 else:
111 url = self.__selectLink(links, keyword)
112 self.__linkActivated(url, keyword, modifiers)
113
114 def __selectLink(self, links, keyword):
115 """
116 Private method to give the user a chance to select among the
117 returned links.
118
119 @param links dictionary of document title and URL to select from
120 @type dictionary of str (key) and QUrl (value)
121 @param keyword keyword for the link set
122 @type str
123 @return selected link
124 @rtype QUrl
125 """
126 link = QUrl()
127 from .HelpTopicDialog import HelpTopicDialog
128 dlg = HelpTopicDialog(self, keyword, links)
129 if dlg.exec_() == QDialog.Accepted:
130 link = dlg.link()
131 return link
132
133 def __filterIndices(self, indexFilter):
134 """
135 Private slot to filter the indexes according to the given filter.
136
137 @param indexFilter filter to be used (string)
138 """
139 if '*' in indexFilter:
140 self.__index.filterIndices(indexFilter, indexFilter)
141 else:
142 self.__index.filterIndices(indexFilter)
143
144 def __enableSearchEdit(self):
145 """
146 Private slot to enable the search edit.
147 """
148 self.__searchEdit.setEnabled(True)
149 self.__filterIndices(self.__searchEdit.text())
150
151 def __disableSearchEdit(self):
152 """
153 Private slot to enable the search edit.
154 """
155 self.__searchEdit.setEnabled(False)
156
157 def focusInEvent(self, evt):
158 """
159 Protected method handling focus in events.
160
161 @param evt reference to the focus event object (QFocusEvent)
162 """
163 if evt.reason() != Qt.MouseFocusReason:
164 self.__searchEdit.selectAll()
165 self.__searchEdit.setFocus()
166
167 def eventFilter(self, watched, event):
168 """
169 Public method called to filter the event queue.
170
171 @param watched the QObject being watched (QObject)
172 @param event the event that occurred (QEvent)
173 @return flag indicating whether the event was handled (boolean)
174 """
175 if self.__searchEdit and watched == self.__searchEdit and \
176 event.type() == QEvent.KeyPress:
177 idx = self.__index.currentIndex()
178 if event.key() == Qt.Key_Up:
179 idx = self.__index.model().index(
180 idx.row() - 1, idx.column(), idx.parent())
181 if idx.isValid():
182 self.__index.setCurrentIndex(idx)
183 elif event.key() == Qt.Key_Down:
184 idx = self.__index.model().index(
185 idx.row() + 1, idx.column(), idx.parent())
186 if idx.isValid():
187 self.__index.setCurrentIndex(idx)
188 elif event.key() == Qt.Key_Escape:
189 self.escapePressed.emit()
190
191 return QWidget.eventFilter(self, watched, event)
192
193 def __showContextMenu(self, pos):
194 """
195 Private slot showing the context menu.
196
197 @param pos position to show the menu at (QPoint)
198 """
199 idx = self.__index.indexAt(pos)
200 if idx.isValid():
201 menu = QMenu()
202 curTab = menu.addAction(self.tr("Open Link"))
203 newTab = menu.addAction(self.tr("Open Link in New Tab"))
204 newBackgroundTab = menu.addAction(
205 self.tr("Open Link in Background Tab"))
206 newWindow = menu.addAction(self.tr("Open Link in New Window"))
207 menu.move(self.__index.mapToGlobal(pos))
208
209 act = menu.exec_()
210 model = self.__index.model()
211 if model is not None:
212 keyword = model.data(idx, Qt.DisplayRole)
213 links = model.linksForKeyword(keyword)
214 if len(links) == 1:
215 link = QUrl(links[list(links.keys())[0]])
216 else:
217 link = self.__selectLink(links, keyword)
218
219 if not link.isEmpty() and link.isValid():
220 if act == curTab:
221 self.openUrl.emit(link)
222 elif act == newTab:
223 self.newTab.emit(link)
224 elif act == newBackgroundTab:
225 self.newBackgroundTab.emit(link)
226 elif act == newWindow:
227 self.newWindow.emit(link)

eric ide

mercurial