eric6/UI/LogView.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7201
6b42677d7043
diff -r f99d60d6b59b -r 2602857055c5 eric6/UI/LogView.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/UI/LogView.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,332 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2006 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the log viewer widget and the log widget.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import pyqtSignal, Qt, QRegExp
+from PyQt5.QtGui import QBrush, QTextCursor, QTextDocument
+from PyQt5.QtWidgets import QTextEdit, QApplication, QMenu, QWidget, \
+    QHBoxLayout, QSizePolicy
+
+from E5Gui.E5Application import e5App
+
+from Globals import qVersionTuple
+
+import UI.PixmapCache
+import Preferences
+import Utilities
+
+
+class LogViewer(QWidget):
+    """
+    Class implementing the containing widget for the log viewer.
+    """
+    def __init__(self, ui, parent=None):
+        """
+        Constructor
+        
+        @param ui reference to the main window (UserInterface)
+        @param parent reference to the parent widget (QWidget)
+        """
+        super(LogViewer, self).__init__(parent)
+        
+        self.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
+        
+        self.__ui = ui
+        
+        self.__logViewer = LogViewerEdit(self)
+        from .SearchWidget import SearchWidget
+        self.__searchWidget = SearchWidget(
+            self.__logViewer, self, hideRegExp=qVersionTuple() < (5, 3, 0))
+        self.__searchWidget.setSizePolicy(
+            QSizePolicy.Fixed, QSizePolicy.Preferred)
+        self.__searchWidget.hide()
+        
+        self.__layout = QHBoxLayout(self)
+        self.__layout.setContentsMargins(1, 1, 1, 1)
+        self.__layout.addWidget(self.__logViewer)
+        self.__layout.addWidget(self.__searchWidget)
+        
+        self.__searchWidget.searchNext.connect(self.__logViewer.searchNext)
+        self.__searchWidget.searchPrevious.connect(self.__logViewer.searchPrev)
+        self.__logViewer.searchStringFound.connect(
+            self.__searchWidget.searchStringFound)
+        
+    def appendToStdout(self, txt):
+        """
+        Public slot to appand text to the "stdout" tab.
+        
+        @param txt text to be appended (string)
+        """
+        added = self.__logViewer.appendToStdout(txt)
+        if added:
+            self.__ui.showLogViewer()
+        
+    def appendToStderr(self, txt):
+        """
+        Public slot to appand text to the "stderr" tab.
+        
+        @param txt text to be appended (string)
+        """
+        added = self.__logViewer.appendToStderr(txt)
+        if added:
+            self.__ui.showLogViewer()
+        
+    def preferencesChanged(self):
+        """
+        Public slot to handle a change of the preferences.
+        """
+        self.__logViewer.preferencesChanged()
+        
+    def showFind(self, txt=""):
+        """
+        Public method to display the search widget.
+        
+        @param txt text to be shown in the combo (string)
+        """
+        self.__searchWidget.showFind(txt)
+
+
+class LogViewerEdit(QTextEdit):
+    """
+    Class providing a specialized text edit for displaying logging information.
+    
+    @signal searchStringFound(found) emitted to indicate the search result
+        (boolean)
+    """
+    searchStringFound = pyqtSignal(bool)
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        super(LogViewerEdit, self).__init__(parent)
+        self.setAcceptRichText(False)
+        self.setLineWrapMode(QTextEdit.NoWrap)
+        self.setReadOnly(True)
+        
+        self.__mainWindow = parent
+        self.__lastSearch = ()
+        
+        # create the context menu
+        self.__menu = QMenu(self)
+        self.__menu.addAction(self.tr('Clear'), self.clear)
+        self.__menu.addAction(self.tr('Copy'), self.copy)
+        self.__menu.addSeparator()
+        self.__menu.addAction(self.tr('Find'), self.__find)
+        self.__menu.addSeparator()
+        self.__menu.addAction(self.tr('Select All'), self.selectAll)
+        self.__menu.addSeparator()
+        self.__menu.addAction(self.tr("Configure..."), self.__configure)
+        
+        self.setContextMenuPolicy(Qt.CustomContextMenu)
+        self.customContextMenuRequested.connect(self.__handleShowContextMenu)
+        
+        self.cNormalFormat = self.currentCharFormat()
+        self.cErrorFormat = self.currentCharFormat()
+        self.cErrorFormat.setForeground(
+            QBrush(Preferences.getUI("LogStdErrColour")))
+        
+        self.__stdoutFilter = Preferences.getUI("LogViewerStdoutFilter")
+        self.__stderrFilter = Preferences.getUI("LogViewerStderrFilter")
+        self.__stdxxxFilter = Preferences.getUI("LogViewerStdxxxFilter")
+        
+    def __handleShowContextMenu(self, coord):
+        """
+        Private slot to show the context menu.
+        
+        @param coord the position of the mouse pointer (QPoint)
+        """
+        coord = self.mapToGlobal(coord)
+        self.__menu.popup(coord)
+        
+    def __appendText(self, txt, isErrorMessage=False):
+        """
+        Private method to append text to the end.
+        
+        @param txt text to insert (string)
+        @param isErrorMessage flag indicating to insert error text (boolean)
+        """
+        tc = self.textCursor()
+        tc.movePosition(QTextCursor.End)
+        self.setTextCursor(tc)
+        if isErrorMessage:
+            self.setCurrentCharFormat(self.cErrorFormat)
+        else:
+            self.setCurrentCharFormat(self.cNormalFormat)
+        self.insertPlainText(Utilities.filterAnsiSequences(txt))
+        self.ensureCursorVisible()
+        
+    def __filterMessage(self, message, isErrorMessage=False):
+        """
+        Private method to filter messages.
+        
+        @param message message to be checked (string)
+        @param isErrorMessage flag indicating to check an error message
+            (boolean)
+        @return flag indicating that the message should be filtered out
+            (boolean)
+        """
+        message = Utilities.filterAnsiSequences(message)
+        
+        if isErrorMessage:
+            filters = self.__stderrFilter + self.__stdxxxFilter
+        else:
+            filters = self.__stdoutFilter + self.__stdxxxFilter
+        for msgFilter in filters:
+            if msgFilter in message:
+                return True
+        
+        return False
+        
+    def appendToStdout(self, txt):
+        """
+        Public slot to appand text to the "stdout" tab.
+        
+        @param txt text to be appended (string)
+        @return flag indicating text was appended (boolean)
+        """
+        if self.__filterMessage(txt, isErrorMessage=False):
+            return False
+        
+        self.__appendText(txt, isErrorMessage=False)
+        QApplication.processEvents()
+        return True
+        
+    def appendToStderr(self, txt):
+        """
+        Public slot to appand text to the "stderr" tab.
+        
+        @param txt text to be appended (string)
+        @return flag indicating text was appended (boolean)
+        """
+        if self.__filterMessage(txt, isErrorMessage=True):
+            return False
+        
+        self.__appendText(txt, isErrorMessage=True)
+        QApplication.processEvents()
+        return True
+        
+    def preferencesChanged(self):
+        """
+        Public slot to handle a change of the preferences.
+        """
+        self.cErrorFormat.setForeground(
+            QBrush(Preferences.getUI("LogStdErrColour")))
+        
+        self.__stdoutFilter = Preferences.getUI("LogViewerStdoutFilter")
+        self.__stderrFilter = Preferences.getUI("LogViewerStderrFilter")
+        self.__stdxxxFilter = Preferences.getUI("LogViewerStdxxxFilter")
+        
+    def __configure(self):
+        """
+        Private method to open the configuration dialog.
+        """
+        e5App().getObject("UserInterface").showPreferences("logViewerPage")
+        
+    def __find(self):
+        """
+        Private slot to show the find widget.
+        """
+        txt = self.textCursor().selectedText()
+        self.__mainWindow.showFind(txt)
+        
+    def searchNext(self, txt, caseSensitive, wholeWord, regexp):
+        """
+        Public method to search the next occurrence of the given text.
+        
+        @param txt text to search for
+        @type str
+        @param caseSensitive flag indicating to perform a case sensitive
+            search
+        @type bool
+        @param wholeWord flag indicating to search for whole words
+            only
+        @type bool
+        @param regexp flag indicating a regular expression search
+        @type bool
+        """
+        self.__lastSearch = (txt, caseSensitive, wholeWord, regexp)
+        flags = QTextDocument.FindFlags()
+        if caseSensitive:
+            flags |= QTextDocument.FindCaseSensitively
+        if wholeWord:
+            flags |= QTextDocument.FindWholeWords
+        if regexp:
+            ok = self.find(QRegExp(
+                txt,
+                Qt.CaseSensitive if caseSensitive else Qt.CaseInsensitive),
+                flags
+            )
+        else:
+            ok = self.find(txt, flags)
+        self.searchStringFound.emit(ok)
+        
+    def searchPrev(self, txt, caseSensitive, wholeWord, regexp):
+        """
+        Public method to search the previous occurrence of the given text.
+        
+        @param txt text to search for
+        @type str
+        @param caseSensitive flag indicating to perform a case sensitive
+            search
+        @type bool
+        @param wholeWord flag indicating to search for whole words
+            only
+        @type bool
+        @param regexp flag indicating a regular expression search
+        @type bool
+        """
+        self.__lastSearch = (txt, caseSensitive, wholeWord, regexp)
+        flags = QTextDocument.FindFlags(QTextDocument.FindBackward)
+        if caseSensitive:
+            flags |= QTextDocument.FindCaseSensitively
+        if wholeWord:
+            flags |= QTextDocument.FindWholeWords
+        if regexp:
+            ok = self.find(QRegExp(
+                txt,
+                Qt.CaseSensitive if caseSensitive else Qt.CaseInsensitive),
+                flags
+            )
+        else:
+            ok = self.find(txt, flags)
+        self.searchStringFound.emit(ok)
+        
+    def keyPressEvent(self, evt):
+        """
+        Protected method handling key press events.
+        
+        @param evt key press event (QKeyEvent)
+        """
+        if evt.modifiers() == Qt.ControlModifier:
+            if evt.key() == Qt.Key_F:
+                self.__find()
+                evt.accept()
+                return
+            elif evt.key() == Qt.Key_C:
+                self.copy()
+                evt.accept()
+                return
+            elif evt.key() == Qt.Key_A:
+                self.selectAll()
+                evt.accept()
+                return
+        elif evt.modifiers() == Qt.NoModifier:
+            if evt.key() == Qt.Key_F3 and self.__lastSearch:
+                self.searchNext(*self.__lastSearch)
+                evt.accept()
+                return
+        elif evt.modifiers() == Qt.ShiftModifier and self.__lastSearch:
+            if evt.key() == Qt.Key_F3 and self.__lastSearch:
+                self.searchPrev(*self.__lastSearch)
+                evt.accept()
+                return

eric ide

mercurial