src/eric7/QtHelpInterface/HelpSearchWidget.py

branch
eric7
changeset 9686
2eee7a645cba
parent 9653
e67609152c5e
child 10069
435cc5875135
equal deleted inserted replaced
9685:b43e04854aba 9686:2eee7a645cba
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009 - 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a window for showing the QtHelp index.
8 """
9
10 from PyQt6.QtCore import QPoint, Qt, QUrl, pyqtSignal, pyqtSlot
11 from PyQt6.QtGui import QClipboard, QGuiApplication
12 from PyQt6.QtWidgets import QApplication, QMenu, QTextBrowser, QVBoxLayout, QWidget
13
14
15 class HelpSearchWidget(QWidget):
16 """
17 Class implementing a window for showing the QtHelp index.
18
19 @signal escapePressed() emitted when the ESC key was pressed
20 @signal openUrl(QUrl, str) emitted to open a search result entry in the
21 current tab
22 @signal newTab(QUrl, str) emitted to open a search result entry in a
23 new tab
24 @signal newBackgroundTab(QUrl, str) emitted to open a search result entry
25 in a new background tab
26 @signal newWindow(QUrl, str) emitted to open a search result entry in a
27 new window
28 """
29
30 escapePressed = pyqtSignal()
31 openUrl = pyqtSignal(QUrl)
32 newTab = pyqtSignal(QUrl)
33 newBackgroundTab = pyqtSignal(QUrl)
34 newWindow = pyqtSignal(QUrl)
35
36 def __init__(self, engine, internal=False, parent=None):
37 """
38 Constructor
39
40 @param engine reference to the help search engine
41 @type QHelpSearchEngine
42 @param internal flag indicating the internal help viewer
43 @type bool
44 @param parent reference to the parent widget
45 @type QWidget
46 """
47 super().__init__(parent)
48
49 self.__engine = engine
50 self.__internal = internal
51
52 self.__layout = QVBoxLayout(self)
53 if internal:
54 # no margins for the internal variant
55 self.__layout.setContentsMargins(0, 0, 0, 0)
56
57 self.__result = self.__engine.resultWidget()
58 self.__query = self.__engine.queryWidget()
59
60 self.__layout.addWidget(self.__query)
61 self.__layout.addWidget(self.__result)
62
63 self.setFocusProxy(self.__query)
64
65 self.__query.search.connect(self.__search)
66 self.__result.requestShowLink.connect(self.__linkActivated)
67
68 self.__engine.searchingStarted.connect(self.__searchingStarted)
69 self.__engine.searchingFinished.connect(self.__searchingFinished)
70
71 self.__browser = self.__result.findChildren(QTextBrowser)[0]
72
73 self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
74 self.customContextMenuRequested.connect(self.__showContextMenu)
75
76 def __search(self):
77 """
78 Private slot to perform a search of the database.
79 """
80 query = self.__query.searchInput()
81 self.__engine.search(query)
82
83 def __searchingStarted(self):
84 """
85 Private slot to handle the start of a search.
86 """
87 QApplication.setOverrideCursor(Qt.CursorShape.WaitCursor)
88
89 def __searchingFinished(self, hits):
90 """
91 Private slot to handle the end of the search.
92
93 @param hits number of hits (unused)
94 @type int
95 """
96 QApplication.restoreOverrideCursor()
97
98 @pyqtSlot(QUrl)
99 def __linkActivated(self, url):
100 """
101 Private slot handling the activation of an entry.
102
103 @param url URL of the activated entry
104 @type QUrl
105 """
106 if not url.isEmpty() and url.isValid():
107 buttons = QApplication.mouseButtons()
108 modifiers = QApplication.keyboardModifiers()
109
110 if buttons & Qt.MouseButton.MiddleButton:
111 self.newTab.emit(url)
112 else:
113 if modifiers & (
114 Qt.KeyboardModifier.ControlModifier
115 | Qt.KeyboardModifier.ShiftModifier
116 ) == (
117 Qt.KeyboardModifier.ControlModifier
118 | Qt.KeyboardModifier.ShiftModifier
119 ):
120 self.newBackgroundTab.emit(url)
121 elif modifiers & Qt.KeyboardModifier.ControlModifier:
122 self.newTab.emit(url)
123 elif (
124 modifiers & Qt.KeyboardModifier.ShiftModifier
125 and not self.__internal
126 ):
127 self.newWindow.emit(url)
128 else:
129 self.openUrl.emit(url)
130
131 def keyPressEvent(self, evt):
132 """
133 Protected method handling key press events.
134
135 @param evt reference to the key press event
136 @type QKeyEvent
137 """
138 if evt.key() == Qt.Key.Key_Escape:
139 self.escapePressed.emit()
140 else:
141 evt.ignore()
142
143 @pyqtSlot(QPoint)
144 def __showContextMenu(self, pos):
145 """
146 Private slot to show a context menu.
147
148 @param pos position for the context menu
149 @type QPoint
150 """
151 point = self.mapToGlobal(pos)
152
153 if self.__browser:
154 point = self.__browser.mapFromGlobal(point)
155 if not self.__browser.rect().contains(point, True):
156 return
157 link = QUrl(self.__browser.anchorAt(point))
158 else:
159 point = self.__result.mapFromGlobal(point)
160 link = self.__result.linkAt(point)
161
162 if link.isEmpty() or not link.isValid():
163 return
164
165 menu = QMenu()
166 curTab = menu.addAction(self.tr("Open Link"))
167 if self.__internal:
168 newTab = menu.addAction(self.tr("Open Link in New Page"))
169 newBackgroundTab = menu.addAction(self.tr("Open Link in Background Page"))
170 else:
171 newTab = menu.addAction(self.tr("Open Link in New Tab"))
172 newBackgroundTab = menu.addAction(self.tr("Open Link in Background Tab"))
173 newWindow = menu.addAction(self.tr("Open Link in New Window"))
174 menu.addSeparator()
175 copyLink = menu.addAction(self.tr("Copy URL to Clipboard"))
176
177 act = menu.exec(self.mapToGlobal(pos))
178 if act == curTab:
179 self.openUrl.emit(link)
180 elif act == newTab:
181 self.newTab.emit(link)
182 elif act == newBackgroundTab:
183 self.newBackgroundTab.emit(link)
184 elif not self.__internal and act == newWindow:
185 self.newWindow.emit(link)
186 elif act == copyLink:
187 # copy the URL to both clipboard areas
188 QGuiApplication.clipboard().setText(
189 link.toString(), QClipboard.Mode.Clipboard
190 )
191 QGuiApplication.clipboard().setText(
192 link.toString(), QClipboard.Mode.Selection
193 )

eric ide

mercurial