src/eric7/UI/LogView.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
8 """ 8 """
9 9
10 from PyQt6.QtCore import pyqtSignal, Qt, QRegularExpression 10 from PyQt6.QtCore import pyqtSignal, Qt, QRegularExpression
11 from PyQt6.QtGui import QBrush, QTextCursor, QTextDocument 11 from PyQt6.QtGui import QBrush, QTextCursor, QTextDocument
12 from PyQt6.QtWidgets import ( 12 from PyQt6.QtWidgets import (
13 QTextEdit, QApplication, QMenu, QWidget, QHBoxLayout, QSizePolicy 13 QTextEdit,
14 QApplication,
15 QMenu,
16 QWidget,
17 QHBoxLayout,
18 QSizePolicy,
14 ) 19 )
15 20
16 from EricWidgets.EricApplication import ericApp 21 from EricWidgets.EricApplication import ericApp
17 22
18 import UI.PixmapCache 23 import UI.PixmapCache
22 27
23 class LogViewer(QWidget): 28 class LogViewer(QWidget):
24 """ 29 """
25 Class implementing the containing widget for the log viewer. 30 Class implementing the containing widget for the log viewer.
26 """ 31 """
32
27 def __init__(self, ui, parent=None): 33 def __init__(self, ui, parent=None):
28 """ 34 """
29 Constructor 35 Constructor
30 36
31 @param ui reference to the main window (UserInterface) 37 @param ui reference to the main window (UserInterface)
32 @param parent reference to the parent widget (QWidget) 38 @param parent reference to the parent widget (QWidget)
33 """ 39 """
34 super().__init__(parent) 40 super().__init__(parent)
35 41
36 self.setWindowIcon(UI.PixmapCache.getIcon("eric")) 42 self.setWindowIcon(UI.PixmapCache.getIcon("eric"))
37 43
38 self.__ui = ui 44 self.__ui = ui
39 45
40 self.__logViewer = LogViewerEdit(self) 46 self.__logViewer = LogViewerEdit(self)
41 from .SearchWidget import SearchWidget 47 from .SearchWidget import SearchWidget
48
42 self.__searchWidget = SearchWidget(self.__logViewer, self) 49 self.__searchWidget = SearchWidget(self.__logViewer, self)
43 self.__searchWidget.setSizePolicy( 50 self.__searchWidget.setSizePolicy(
44 QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Preferred) 51 QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Preferred
52 )
45 self.__searchWidget.hide() 53 self.__searchWidget.hide()
46 54
47 self.__layout = QHBoxLayout(self) 55 self.__layout = QHBoxLayout(self)
48 self.__layout.setContentsMargins(1, 1, 1, 1) 56 self.__layout.setContentsMargins(1, 1, 1, 1)
49 self.__layout.addWidget(self.__logViewer) 57 self.__layout.addWidget(self.__logViewer)
50 self.__layout.addWidget(self.__searchWidget) 58 self.__layout.addWidget(self.__searchWidget)
51 59
52 self.__searchWidget.searchNext.connect(self.__logViewer.searchNext) 60 self.__searchWidget.searchNext.connect(self.__logViewer.searchNext)
53 self.__searchWidget.searchPrevious.connect(self.__logViewer.searchPrev) 61 self.__searchWidget.searchPrevious.connect(self.__logViewer.searchPrev)
54 self.__logViewer.searchStringFound.connect( 62 self.__logViewer.searchStringFound.connect(
55 self.__searchWidget.searchStringFound) 63 self.__searchWidget.searchStringFound
56 64 )
65
57 def appendToStdout(self, txt): 66 def appendToStdout(self, txt):
58 """ 67 """
59 Public slot to appand text to the "stdout" tab. 68 Public slot to appand text to the "stdout" tab.
60 69
61 @param txt text to be appended (string) 70 @param txt text to be appended (string)
62 """ 71 """
63 added = self.__logViewer.appendToStdout(txt) 72 added = self.__logViewer.appendToStdout(txt)
64 if added: 73 if added:
65 self.__ui.showLogViewer() 74 self.__ui.showLogViewer()
66 75
67 def appendToStderr(self, txt): 76 def appendToStderr(self, txt):
68 """ 77 """
69 Public slot to appand text to the "stderr" tab. 78 Public slot to appand text to the "stderr" tab.
70 79
71 @param txt text to be appended (string) 80 @param txt text to be appended (string)
72 """ 81 """
73 added = self.__logViewer.appendToStderr(txt) 82 added = self.__logViewer.appendToStderr(txt)
74 if added: 83 if added:
75 self.__ui.showLogViewer() 84 self.__ui.showLogViewer()
76 85
77 def preferencesChanged(self): 86 def preferencesChanged(self):
78 """ 87 """
79 Public slot to handle a change of the preferences. 88 Public slot to handle a change of the preferences.
80 """ 89 """
81 self.__logViewer.preferencesChanged() 90 self.__logViewer.preferencesChanged()
82 91
83 def showFind(self, txt=""): 92 def showFind(self, txt=""):
84 """ 93 """
85 Public method to display the search widget. 94 Public method to display the search widget.
86 95
87 @param txt text to be shown in the combo (string) 96 @param txt text to be shown in the combo (string)
88 """ 97 """
89 self.__searchWidget.showFind(txt) 98 self.__searchWidget.showFind(txt)
90 99
91 100
92 class LogViewerEdit(QTextEdit): 101 class LogViewerEdit(QTextEdit):
93 """ 102 """
94 Class providing a specialized text edit for displaying logging information. 103 Class providing a specialized text edit for displaying logging information.
95 104
96 @signal searchStringFound(found) emitted to indicate the search result 105 @signal searchStringFound(found) emitted to indicate the search result
97 (boolean) 106 (boolean)
98 """ 107 """
108
99 searchStringFound = pyqtSignal(bool) 109 searchStringFound = pyqtSignal(bool)
100 110
101 def __init__(self, parent=None): 111 def __init__(self, parent=None):
102 """ 112 """
103 Constructor 113 Constructor
104 114
105 @param parent reference to the parent widget (QWidget) 115 @param parent reference to the parent widget (QWidget)
106 """ 116 """
107 super().__init__(parent) 117 super().__init__(parent)
108 self.setAcceptRichText(False) 118 self.setAcceptRichText(False)
109 self.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap) 119 self.setLineWrapMode(QTextEdit.LineWrapMode.NoWrap)
110 self.setReadOnly(True) 120 self.setReadOnly(True)
111 121
112 self.__mainWindow = parent 122 self.__mainWindow = parent
113 self.__lastSearch = () 123 self.__lastSearch = ()
114 124
115 # create the context menu 125 # create the context menu
116 self.__menu = QMenu(self) 126 self.__menu = QMenu(self)
117 self.__menu.addAction(self.tr('Clear'), self.clear) 127 self.__menu.addAction(self.tr("Clear"), self.clear)
118 self.__menu.addAction(self.tr('Copy'), self.copy) 128 self.__menu.addAction(self.tr("Copy"), self.copy)
119 self.__menu.addSeparator() 129 self.__menu.addSeparator()
120 self.__menu.addAction(self.tr('Find'), self.__find) 130 self.__menu.addAction(self.tr("Find"), self.__find)
121 self.__menu.addSeparator() 131 self.__menu.addSeparator()
122 self.__menu.addAction(self.tr('Select All'), self.selectAll) 132 self.__menu.addAction(self.tr("Select All"), self.selectAll)
123 self.__menu.addSeparator() 133 self.__menu.addSeparator()
124 self.__menu.addAction(self.tr("Configure..."), self.__configure) 134 self.__menu.addAction(self.tr("Configure..."), self.__configure)
125 135
126 self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) 136 self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
127 self.customContextMenuRequested.connect(self.__handleShowContextMenu) 137 self.customContextMenuRequested.connect(self.__handleShowContextMenu)
128 138
129 self.cNormalFormat = self.currentCharFormat() 139 self.cNormalFormat = self.currentCharFormat()
130 self.cErrorFormat = self.currentCharFormat() 140 self.cErrorFormat = self.currentCharFormat()
131 self.cErrorFormat.setForeground( 141 self.cErrorFormat.setForeground(QBrush(Preferences.getUI("LogStdErrColour")))
132 QBrush(Preferences.getUI("LogStdErrColour"))) 142
133
134 self.__stdoutFilter = Preferences.getUI("LogViewerStdoutFilter") 143 self.__stdoutFilter = Preferences.getUI("LogViewerStdoutFilter")
135 self.__stderrFilter = Preferences.getUI("LogViewerStderrFilter") 144 self.__stderrFilter = Preferences.getUI("LogViewerStderrFilter")
136 self.__stdxxxFilter = Preferences.getUI("LogViewerStdxxxFilter") 145 self.__stdxxxFilter = Preferences.getUI("LogViewerStdxxxFilter")
137 146
138 def __handleShowContextMenu(self, coord): 147 def __handleShowContextMenu(self, coord):
139 """ 148 """
140 Private slot to show the context menu. 149 Private slot to show the context menu.
141 150
142 @param coord the position of the mouse pointer (QPoint) 151 @param coord the position of the mouse pointer (QPoint)
143 """ 152 """
144 coord = self.mapToGlobal(coord) 153 coord = self.mapToGlobal(coord)
145 self.__menu.popup(coord) 154 self.__menu.popup(coord)
146 155
147 def __appendText(self, txt, isErrorMessage=False): 156 def __appendText(self, txt, isErrorMessage=False):
148 """ 157 """
149 Private method to append text to the end. 158 Private method to append text to the end.
150 159
151 @param txt text to insert (string) 160 @param txt text to insert (string)
152 @param isErrorMessage flag indicating to insert error text (boolean) 161 @param isErrorMessage flag indicating to insert error text (boolean)
153 """ 162 """
154 tc = self.textCursor() 163 tc = self.textCursor()
155 tc.movePosition(QTextCursor.MoveOperation.End) 164 tc.movePosition(QTextCursor.MoveOperation.End)
158 self.setCurrentCharFormat(self.cErrorFormat) 167 self.setCurrentCharFormat(self.cErrorFormat)
159 else: 168 else:
160 self.setCurrentCharFormat(self.cNormalFormat) 169 self.setCurrentCharFormat(self.cNormalFormat)
161 self.insertPlainText(Utilities.filterAnsiSequences(txt)) 170 self.insertPlainText(Utilities.filterAnsiSequences(txt))
162 self.ensureCursorVisible() 171 self.ensureCursorVisible()
163 172
164 def __filterMessage(self, message, isErrorMessage=False): 173 def __filterMessage(self, message, isErrorMessage=False):
165 """ 174 """
166 Private method to filter messages. 175 Private method to filter messages.
167 176
168 @param message message to be checked (string) 177 @param message message to be checked (string)
169 @param isErrorMessage flag indicating to check an error message 178 @param isErrorMessage flag indicating to check an error message
170 (boolean) 179 (boolean)
171 @return flag indicating that the message should be filtered out 180 @return flag indicating that the message should be filtered out
172 (boolean) 181 (boolean)
173 """ 182 """
174 message = Utilities.filterAnsiSequences(message) 183 message = Utilities.filterAnsiSequences(message)
175 184
176 filters = ( 185 filters = (
177 self.__stderrFilter + self.__stdxxxFilter 186 self.__stderrFilter + self.__stdxxxFilter
178 if isErrorMessage else 187 if isErrorMessage
179 self.__stdoutFilter + self.__stdxxxFilter 188 else self.__stdoutFilter + self.__stdxxxFilter
180 ) 189 )
181 190
182 return any(msgFilter in message for msgFilter in filters) 191 return any(msgFilter in message for msgFilter in filters)
183 192
184 def appendToStdout(self, txt): 193 def appendToStdout(self, txt):
185 """ 194 """
186 Public slot to appand text to the "stdout" tab. 195 Public slot to appand text to the "stdout" tab.
187 196
188 @param txt text to be appended (string) 197 @param txt text to be appended (string)
189 @return flag indicating text was appended (boolean) 198 @return flag indicating text was appended (boolean)
190 """ 199 """
191 if self.__filterMessage(txt, isErrorMessage=False): 200 if self.__filterMessage(txt, isErrorMessage=False):
192 return False 201 return False
193 202
194 self.__appendText(txt, isErrorMessage=False) 203 self.__appendText(txt, isErrorMessage=False)
195 QApplication.processEvents() 204 QApplication.processEvents()
196 return True 205 return True
197 206
198 def appendToStderr(self, txt): 207 def appendToStderr(self, txt):
199 """ 208 """
200 Public slot to appand text to the "stderr" tab. 209 Public slot to appand text to the "stderr" tab.
201 210
202 @param txt text to be appended (string) 211 @param txt text to be appended (string)
203 @return flag indicating text was appended (boolean) 212 @return flag indicating text was appended (boolean)
204 """ 213 """
205 if self.__filterMessage(txt, isErrorMessage=True): 214 if self.__filterMessage(txt, isErrorMessage=True):
206 return False 215 return False
207 216
208 self.__appendText(txt, isErrorMessage=True) 217 self.__appendText(txt, isErrorMessage=True)
209 QApplication.processEvents() 218 QApplication.processEvents()
210 return True 219 return True
211 220
212 def preferencesChanged(self): 221 def preferencesChanged(self):
213 """ 222 """
214 Public slot to handle a change of the preferences. 223 Public slot to handle a change of the preferences.
215 """ 224 """
216 self.cErrorFormat.setForeground( 225 self.cErrorFormat.setForeground(QBrush(Preferences.getUI("LogStdErrColour")))
217 QBrush(Preferences.getUI("LogStdErrColour"))) 226
218
219 self.__stdoutFilter = Preferences.getUI("LogViewerStdoutFilter") 227 self.__stdoutFilter = Preferences.getUI("LogViewerStdoutFilter")
220 self.__stderrFilter = Preferences.getUI("LogViewerStderrFilter") 228 self.__stderrFilter = Preferences.getUI("LogViewerStderrFilter")
221 self.__stdxxxFilter = Preferences.getUI("LogViewerStdxxxFilter") 229 self.__stdxxxFilter = Preferences.getUI("LogViewerStdxxxFilter")
222 230
223 def __configure(self): 231 def __configure(self):
224 """ 232 """
225 Private method to open the configuration dialog. 233 Private method to open the configuration dialog.
226 """ 234 """
227 ericApp().getObject("UserInterface").showPreferences("logViewerPage") 235 ericApp().getObject("UserInterface").showPreferences("logViewerPage")
228 236
229 def __find(self): 237 def __find(self):
230 """ 238 """
231 Private slot to show the find widget. 239 Private slot to show the find widget.
232 """ 240 """
233 txt = self.textCursor().selectedText() 241 txt = self.textCursor().selectedText()
234 self.__mainWindow.showFind(txt) 242 self.__mainWindow.showFind(txt)
235 243
236 def searchNext(self, txt, caseSensitive, wholeWord, regexp): 244 def searchNext(self, txt, caseSensitive, wholeWord, regexp):
237 """ 245 """
238 Public method to search the next occurrence of the given text. 246 Public method to search the next occurrence of the given text.
239 247
240 @param txt text to search for 248 @param txt text to search for
241 @type str 249 @type str
242 @param caseSensitive flag indicating to perform a case sensitive 250 @param caseSensitive flag indicating to perform a case sensitive
243 search 251 search
244 @type bool 252 @type bool
253 if caseSensitive: 261 if caseSensitive:
254 flags |= QTextDocument.FindFlag.FindCaseSensitively 262 flags |= QTextDocument.FindFlag.FindCaseSensitively
255 if wholeWord: 263 if wholeWord:
256 flags |= QTextDocument.FindFlag.FindWholeWords 264 flags |= QTextDocument.FindFlag.FindWholeWords
257 ok = ( 265 ok = (
258 self.find(QRegularExpression( 266 self.find(
259 txt, 267 QRegularExpression(
260 QRegularExpression.PatternOption.NoPatternOption 268 txt,
261 if caseSensitive 269 QRegularExpression.PatternOption.NoPatternOption
262 else QRegularExpression.PatternOption.CaseInsensitiveOption), 270 if caseSensitive
263 flags 271 else QRegularExpression.PatternOption.CaseInsensitiveOption,
272 ),
273 flags,
264 ) 274 )
265 if regexp else 275 if regexp
266 self.find(txt, flags) 276 else self.find(txt, flags)
267 ) 277 )
268 self.searchStringFound.emit(ok) 278 self.searchStringFound.emit(ok)
269 279
270 def searchPrev(self, txt, caseSensitive, wholeWord, regexp): 280 def searchPrev(self, txt, caseSensitive, wholeWord, regexp):
271 """ 281 """
272 Public method to search the previous occurrence of the given text. 282 Public method to search the previous occurrence of the given text.
273 283
274 @param txt text to search for 284 @param txt text to search for
275 @type str 285 @type str
276 @param caseSensitive flag indicating to perform a case sensitive 286 @param caseSensitive flag indicating to perform a case sensitive
277 search 287 search
278 @type bool 288 @type bool
287 if caseSensitive: 297 if caseSensitive:
288 flags |= QTextDocument.FindFlag.FindCaseSensitively 298 flags |= QTextDocument.FindFlag.FindCaseSensitively
289 if wholeWord: 299 if wholeWord:
290 flags |= QTextDocument.FindFlag.FindWholeWords 300 flags |= QTextDocument.FindFlag.FindWholeWords
291 ok = ( 301 ok = (
292 self.find(QRegularExpression( 302 self.find(
293 txt, 303 QRegularExpression(
294 QRegularExpression.PatternOption.NoPatternOption 304 txt,
295 if caseSensitive 305 QRegularExpression.PatternOption.NoPatternOption
296 else QRegularExpression.PatternOption.CaseInsensitiveOption), 306 if caseSensitive
297 flags 307 else QRegularExpression.PatternOption.CaseInsensitiveOption,
308 ),
309 flags,
298 ) 310 )
299 if regexp else 311 if regexp
300 self.find(txt, flags) 312 else self.find(txt, flags)
301 ) 313 )
302 self.searchStringFound.emit(ok) 314 self.searchStringFound.emit(ok)
303 315
304 def keyPressEvent(self, evt): 316 def keyPressEvent(self, evt):
305 """ 317 """
306 Protected method handling key press events. 318 Protected method handling key press events.
307 319
308 @param evt key press event (QKeyEvent) 320 @param evt key press event (QKeyEvent)
309 """ 321 """
310 if evt.modifiers() == Qt.KeyboardModifier.ControlModifier: 322 if evt.modifiers() == Qt.KeyboardModifier.ControlModifier:
311 if evt.key() == Qt.Key.Key_F: 323 if evt.key() == Qt.Key.Key_F:
312 self.__find() 324 self.__find()
319 elif evt.key() == Qt.Key.Key_A: 331 elif evt.key() == Qt.Key.Key_A:
320 self.selectAll() 332 self.selectAll()
321 evt.accept() 333 evt.accept()
322 return 334 return
323 elif ( 335 elif (
324 evt.modifiers() == Qt.KeyboardModifier.NoModifier and 336 evt.modifiers() == Qt.KeyboardModifier.NoModifier
325 evt.key() == Qt.Key.Key_F3 and 337 and evt.key() == Qt.Key.Key_F3
326 self.__lastSearch 338 and self.__lastSearch
327 ): 339 ):
328 self.searchNext(*self.__lastSearch) 340 self.searchNext(*self.__lastSearch)
329 evt.accept() 341 evt.accept()
330 return 342 return
331 elif ( 343 elif (
332 evt.modifiers() == Qt.KeyboardModifier.ShiftModifier and 344 evt.modifiers() == Qt.KeyboardModifier.ShiftModifier
333 evt.key() == Qt.Key.Key_F3 and 345 and evt.key() == Qt.Key.Key_F3
334 self.__lastSearch 346 and self.__lastSearch
335 ): 347 ):
336 self.searchPrev(*self.__lastSearch) 348 self.searchPrev(*self.__lastSearch)
337 evt.accept() 349 evt.accept()
338 return 350 return

eric ide

mercurial