88 from MyGui import Log
99 Log.run()
1010"""
11-
12- from PyQt4 import QtCore , QtGui
11+ #get compatible to python3
12+ from __future__ import absolute_import , division , print_function
1313
1414import os
15+
16+ #enable compatibility to both pyqt4 and pyqt5
17+ _modname = os .environ .setdefault ('QT_API' , 'pyqt' )
18+ assert _modname in ('pyqt' , 'pyqt5' )
19+
20+ if os .environ ['QT_API' ].startswith ('pyqt' ):
21+ try :
22+ if os .environ ['QT_API' ] == 'pyqt5' :
23+ from PyQt5 .QtWidgets import (QApplication , QDockWidget , QFileDialog ,
24+ QMainWindow )
25+
26+ ### import ui created with qtdesigner
27+ ### create python file with:
28+ ### pyuic5 Log.ui > ui_Log_qt5.py
29+ from ui_Log_qt5 import Ui_DockWidget
30+
31+ from PyQt5 import QtCore
32+
33+ else :
34+ from PyQt4 .QtGui import (QApplication , QDockWidget , QFileDialog ,
35+ QMainWindow )
36+
37+ ### import ui created with qtdesigner
38+ ### create python file with:
39+ ### pyuic4 Log.ui > ui_Log_qt4.py
40+ from ui_Log_qt4 import Ui_DockWidget
41+
42+ from PyQt4 import QtCore
43+ except ImportError as e :
44+ print (e )
45+ raise ImportError ("GUI Logger requires PyQt4 or PyQt5. "
46+ "QT_API: {!s}" .format (os .environ ['QT_API' ]))
47+
48+
1549import logging
1650
1751
@@ -79,7 +113,7 @@ def emit(self, record):
79113 self .logSig .emit_log (text )
80114 ### otherwise just print log message
81115 else :
82- print text
116+ print ( text )
83117
84118
85119class LogFormat (logging .Formatter ):
@@ -99,59 +133,40 @@ class LogFormat(logging.Formatter):
99133# err_fmt = "[ERROR] %(module)s:%(funcName)s >> %(msg)s"
100134#My Formattes (prints just the messages):
101135#
102- dbg_fmt = " [DEBUG]%(asctime)s %(msg)s"
103- info_fmt = " [INFO]%(asctime)s %(msg)s"
104- warn_fmt = " [WARNING]%(asctime)s %(msg)s"
105- err_fmt = "[ ERROR]%(asctime)s %(msg)s"
106- crit_fmt = "[ CRITICAL]%(asctime)s %(msg)s"
136+ level_translation = { "10: " : " [DEBUG] " ,
137+ "20: " : " [INFO] " ,
138+ "30: " : " [WARNING] " ,
139+ "40: " : " ERROR " ,
140+ "50: " : " CRITICAL " }
107141 datefmt = ""
108142
109- def __init__ (self , fmt = "%(levelno)s: %(msg)s" ,datefmt = None ,infoString = True ):
143+ def __init__ (self , fmt = "%(levelno)s: %(asctime)s %(msg)s" , datefmt = None ,
144+ infoString = True ):
110145 logging .Formatter .__init__ (self , fmt ,datefmt )
111146 self .datefmt = datefmt
147+
112148
113149 if not infoString :
114- self .info_fmt = "%(asctime)s %(msg)s"
150+ self .level_tranlsation ["20: " ] = ""
151+ # self.info_fmt = "%(asctime)s %(msg)s"
115152
116153 def format (self , record ):
117-
118- # Save the original format configured by the user
119- # when the logger formatter was instantiated
120- format_orig = self ._fmt
121-
122- # Replace the original format with one customized by logging level
123- if record .levelno == 10 : # DEBUG
124- self ._fmt = self .dbg_fmt
125-
126- elif record .levelno == 20 : # INFO
127- self ._fmt = self .info_fmt
128-
129- elif record .levelno == 30 : # WARNING
130- self ._fmt = self .warn_fmt
131-
132- elif record .levelno == 40 : # ERROR
133- self ._fmt = self .err_fmt
134-
135- elif record .levelno == 50 : # CRITICAL
136- self ._fmt = self .crit_fmt
154+ # Call the base class formatter to do the grunt work
155+ result = logging .Formatter .format (self , record )
156+
157+ #replace the numeric logging levels with strings
158+ result = self .level_translation [result [0 :4 ]] + result [4 :]
159+
137160
138161
139- # Call the original formatter class to do the grunt work
140- result = logging .Formatter .format (self , record )
141162
142- # Restore the original format configured by the user
143- self ._fmt = format_orig
144163
145164 return result
146165
147166
148167
149- ### import ui created with qtdesigner
150- ### create python file with:
151- ### pyuic4 Log.ui > ui_Log.py
152- from ui_Log import Ui_DockWidget
153168
154- class QtDockLog (QtGui . QDockWidget ):
169+ class QtDockLog (QDockWidget ):
155170 """
156171 Log Dock Widget to use in a PyQt GUI
157172 Will output all the logging.info(), logging.debug() etc. info
@@ -181,7 +196,7 @@ def __init__(self,datefmt=None,infoString = True):
181196 if false info messages are not prefixed with the log level string
182197 """
183198
184- QtGui . QDockWidget .__init__ (self )
199+ QDockWidget .__init__ (self )
185200
186201 # Set up the user interface from Designer.
187202 self .ui = Ui_DockWidget ()
@@ -213,12 +228,16 @@ def __init__(self,datefmt=None,infoString = True):
213228 lambda : self .setLevel (self .ui .comboBox .currentText ()))
214229 self .ui .pushButtonSave .clicked .connect (self .saveLog )
215230
216-
217231 def saveLog (self ):
218232 """
219233 Saves the shown log to file 'filename'
220234 """
221- savePath = QtGui .QFileDialog .getSaveFileName (self ,'select save file' )
235+ savePath = QFileDialog .getSaveFileName (self ,caption = 'select save file' ,
236+ filter = "Text files (*.txt);;All files (*)" )
237+ #in pyqt5 a tuple is returned, unpack it
238+ if os .environ ['QT_API' ] == 'pyqt5' :
239+ savePath , _ = savePath
240+
222241 if savePath != '' :
223242 text = str (self .ui .textBrowser .toPlainText ()) # get log text
224243 f = open (savePath , 'w' ) # open file
@@ -236,29 +255,28 @@ def setLevel(self, level):
236255 # clear the text window
237256 self .ui .textBrowser .clear ()
238257 # open the log file
239- f = open (self .filename , 'r' )
240- # go through lines in log file
241- for line in f :
242- line = line .strip () # delete end of line
243- try :
244- level_line = line .split ('[' )[1 ].split (']' )[0 ] # get level of line
245- except IndexError :
246- level_line = "INFO" #default to info
247-
248- level_line_int = eval ("logging.%s" % (level_line ))
249- # if number of line level is greater equal to number of
250- # the global level, append to text in color
251- if level_line_int >= level_int :
252- text = "<font color='%s'> %s </font>" \
253- % ( self .handler .COLORS [level_line ], line )
254- self .ui .textBrowser .append (text )
255- # close file
256- f .close ()
258+ with open (self .filename , 'r' ) as f :
259+ # go through lines in log file
260+ for line in f :
261+ line = line .strip () # delete end of line
262+ try :
263+ level_line = line .split ('[' )[1 ].split (']' )[0 ] # get level of line
264+ except IndexError :
265+ level_line = "INFO" #default to info
266+
267+ level_line_int = eval ("logging.%s" % (level_line ))
268+ # if number of line level is greater equal to number of
269+ # the global level, append to text in color
270+ if level_line_int >= level_int :
271+ text = "<font color='%s'> %s </font>" \
272+ % ( self .handler .COLORS [level_line ], line )
273+ self .ui .textBrowser .append (text )
257274
258275 cmd = "self.handler.setLevel(logging.%s)" % (level )
259276 eval (cmd )
260277 ### print new level
261278 self .logger .debug ("Logging level set to %s." % (level ))
279+
262280
263281 ### pyQt SLOT used to receive emitted SIGNAL from LogHandler()
264282 ### pass self to LogHandler to make this work
@@ -271,8 +289,8 @@ def printLog(self, text):
271289def run ():
272290 import sys
273291
274- app = QtGui . QApplication (sys .argv )
275- win = QtGui . QMainWindow ()
292+ app = QApplication (sys .argv )
293+ win = QMainWindow ()
276294 win .addDockWidget (QtCore .Qt .TopDockWidgetArea , QtDockLog ())
277295 win .show ()
278296 sys .exit (app .exec_ ())
0 commit comments