00001 #!/usr/local/bin/python
00002 #
00003 # Copyright 2002
00004 # by
00005 # The Board of Trustees of the
00006 # Leland Stanford Junior University.
00007 # All rights reserved.
00008 #
00009
00010 __facility__ = "Online"
00011 __abstract__ = "GLAST LAT Message Logger GUI"
00012 __author__ = """A. Kavelaars <AliciaK@SLAC.Stanford.edu>
00013 SLAC - GLAST LAT I&T/Online"""
00014 __date__ = "12/3/2002"
00015 __version__ = "$Revision: 2.12 $"
00016 __credits__ = "SLAC"
00017
00018 import LATTE.copyright_SLAC
00019
00020
00021 from qt import *
00022 from MSGLogGUI import MSGLogGUI
00023 from select import select
00024 import sys, string, struct, types, cPickle, socket
00025 import logging, logging.handlers, logging.config
00026 logging.raiseExceptions = 1
00027 import threading
00028 import atexit
00029
00030 #~ #
00031 #~ # Levels
00032
00033 #~ CRITICAL = 50
00034 #~ FATAL = CRITICAL
00035 #~ ERROR = 40
00036 #~ WARN = 30
00037 #~ INFO = 20
00038 #~ DEBUG = 10
00039 #~ NOTSET = 0
00040
00041 #~ import RunControlCommon
00042 #~ from RunControlCommon import RunControlCommon
00043
00044 imageInfo_data = [
00045 "20 18 3 1",
00046 "# c #000080",
00047 "a c #808080",
00048 ". c #ffffff",
00049 ".......######.......",
00050 ".....##########.....",
00051 "....############....",
00052 "...######..######...",
00053 "..#######..#######..",
00054 "..################..",
00055 ".##################.",
00056 ".########..########.",
00057 ".########..########.",
00058 ".########..########.",
00059 ".########..########.",
00060 "..#######..#######a.",
00061 "..#######..#######..",
00062 "..a######..######a..",
00063 "...a############a...",
00064 "....a##########a....",
00065 ".....aa######aa.....",
00066 ".......aaaaaa......."
00067 ]
00068
00069 imageFatal_data = [
00070 "20 18 19 1",
00071 "p c #004040",
00072 "b c #484242",
00073 "d c #5e4f4f",
00074 "j c #675656",
00075 "m c #685151",
00076 "g c #695555",
00077 "a c #808080",
00078 "h c #cddcdc",
00079 "e c #cedcdc",
00080 "k c #d4e1e1",
00081 "n c #e1eded",
00082 "q c #ebefef",
00083 "i c #ecf6f6",
00084 "f c #edf7f7",
00085 "l c #f1fafa",
00086 "o c #f2f6f6",
00087 "c c #f3fcfc",
00088 "# c #ff0000",
00089 ". c #ffffff",
00090 "......########......",
00091 ".....##########.....",
00092 "....############....",
00093 "...#####....#####...",
00094 "..#####......#####..",
00095 ".#####........#####.",
00096 ".####..aa..aa..####.",
00097 ".####...a..a...####.",
00098 ".####..........####.",
00099 ".#####...aa...#####.",
00100 ".######......######.",
00101 ".a######.aa.######a.",
00102 ".ba#####....#####aa.",
00103 ".cda####....####aae.",
00104 "..fga##########aah..",
00105 "...ija########aak...",
00106 "....lmaaaaaaaaan....",
00107 ".....oppppppppq....."
00108 ]
00109
00110 imageWarn_data = [
00111 "20 18 4 1",
00112 "a c #004040",
00113 "b c #808080",
00114 "# c #ffff00",
00115 ". c #ffffff",
00116 ".........##.........",
00117 "........####........",
00118 "........####........",
00119 ".......######.......",
00120 ".......##aa##.......",
00121 "......###aa###......",
00122 "......###aa###......",
00123 ".....####aa####.....",
00124 ".....####aa####.....",
00125 "....#####aa#####....",
00126 "....#####aa#####....",
00127 "...######aa######...",
00128 "...##############...",
00129 "..################..",
00130 "..#######aa#######..",
00131 ".########aa########.",
00132 ".##################.",
00133 "..bbbbbbbbbbbbbbbbb."
00134 ]
00135
00136 imageError_data = [
00137 "20 18 3 1",
00138 "a c #808080",
00139 "# c #ff0000",
00140 ". c #ffffff",
00141 ".......######.......",
00142 ".....##########.....",
00143 "....############....",
00144 "...##############...",
00145 "..###..#####..####..",
00146 "..###...###...####..",
00147 ".#####...#...######.",
00148 ".######.....#######.",
00149 ".#######...########.",
00150 ".######.....#######.",
00151 ".#####...#...######.",
00152 ".a###...###...####a.",
00153 "..###..#####..####..",
00154 "..a##############a..",
00155 "...a############a...",
00156 "....a##########a....",
00157 ".....aa######aa.....",
00158 ".......aaaaaa......."
00159 ]
00160
00161 imageNotset_data = [
00162 "20 18 19 1",
00163 "p c #004040",
00164 "# c #008000",
00165 "b c #484242",
00166 "d c #5e4f4f",
00167 "j c #675656",
00168 "m c #685151",
00169 "g c #695555",
00170 "a c #808080",
00171 "h c #cddcdc",
00172 "e c #cedcdc",
00173 "k c #d4e1e1",
00174 "n c #e1eded",
00175 "q c #ebefef",
00176 "i c #ecf6f6",
00177 "f c #edf7f7",
00178 "l c #f1fafa",
00179 "o c #f2f6f6",
00180 "c c #f3fcfc",
00181 ". c #ffffff",
00182 "......########......",
00183 ".....##########.....",
00184 "....#####..#####....",
00185 "...######..######...",
00186 "..#######..#######..",
00187 ".########..########.",
00188 ".########..########.",
00189 ".########..########.",
00190 ".########..########.",
00191 ".########..########.",
00192 ".##################.",
00193 ".a################a.",
00194 ".ba######..######aa.",
00195 ".cda#####..#####aae.",
00196 "..fga##########aah..",
00197 "...ija########aak...",
00198 "....lmaaaaaaaaan....",
00199 ".....oppppppppq....."
00200 ]
00201
00202 imageDebug_data = [
00203 "20 18 19 1",
00204 "p c #004040",
00205 "b c #484242",
00206 "d c #5e4f4f",
00207 "j c #675656",
00208 "m c #685151",
00209 "g c #695555",
00210 "a c #808080",
00211 "# c #c0c0c0",
00212 "h c #cddcdc",
00213 "e c #cedcdc",
00214 "k c #d4e1e1",
00215 "n c #e1eded",
00216 "q c #ebefef",
00217 "i c #ecf6f6",
00218 "f c #edf7f7",
00219 "l c #f1fafa",
00220 "o c #f2f6f6",
00221 "c c #f3fcfc",
00222 ". c #ffffff",
00223 "......########......",
00224 ".....##########.....",
00225 "....#####..#####....",
00226 "...######..######...",
00227 "..################..",
00228 ".##################.",
00229 ".########..########.",
00230 ".########..########.",
00231 ".########..########.",
00232 ".########..########.",
00233 ".########..########.",
00234 ".a#######..#######a.",
00235 ".ba######..######aa.",
00236 ".cda#####..#####aae.",
00237 "..fga##########aah..",
00238 "...ija########aak...",
00239 "....lmaaaaaaaaan....",
00240 ".....oppppppppq....."
00241 ]
00242
00243 #~##
00244 from SocketServer import ThreadingTCPServer, StreamRequestHandler
00245 import errno
00246 import select
00247
00248
00249 MAX_ENTRIES = 9000
00250 DELETE_ENTRIES = 100
00251
00252 class LogRecordStreamHandler(StreamRequestHandler):
00253 """
00254 Handler for a streaming logging request. It basically logs the record
00255 using whatever logging policy is configured locally.
00256 """
00257
00258 def handle(self):
00259 """
00260 Handle multiple requests - each expected to be a 4-byte length,
00261 followed by the LogRecord in pickle format. Logs the record
00262 according to whatever policy is configured locally.
00263 """
00264 while 1:
00265 try:
00266 chunk = self.connection.recv(4)
00267 if len(chunk) < 4:
00268 break
00269 slen = struct.unpack(">L", chunk)[0]
00270 #print slen
00271 chunk = self.connection.recv(slen)
00272 while len(chunk) < slen:
00273 chunk = chunk + self.connection.recv(slen - len(chunk))
00274 obj = self.unPickle(chunk)
00275 record = logging.makeLogRecord(obj)
00276 #record = logging.LogRecord(None, None, "", 0, "", (), None)
00277 #record.__dict__.update(obj)
00278 self.handleLogRecord(record)
00279 except socket.error, e:
00280 if type(e.args) != types.TupleType:
00281 raise e
00282 else:
00283 errcode = e.args[0]
00284 if errcode != errno.ECONNRESET:
00285 raise e
00286 break
00287
00288 def unPickle(self, data):
00289 return cPickle.loads(data)
00290
00291 def handleLogRecord(self, record):
00292 #if a name is specified, we use the named logger rather than the one
00293 #implied by the record. This is so test harnesses don't get into
00294 #endless loops (particularly log_test.py, which has this code and the
00295 #client code in the same Python instance)
00296 if self.server.logname is not None:
00297 name = self.server.logname
00298 else:
00299 name = record.name
00300 logger = logging.getLogger(name)
00301 #logger.handle(record)
00302 #print logger.handlers[0].format(record)
00303
00304 #~ self.__actualData = logger.handlers[0].format(record)
00305
00306 self.server.gui.appendLogData(logger.handlers[0].format(record))
00307
00308
00309 class MSGLogSocketReceiver(ThreadingTCPServer):
00310 allow_reuse_address = 1
00311
00312 def __init__(self, gui, host='', port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
00313 handler=LogRecordStreamHandler):
00314 ThreadingTCPServer.__init__(self, (host, port), handler)
00315 self.__abort = 0
00316 self.timeout = 1
00317 self.logname = None
00318 self.gui = gui
00319 self.handler = handler
00320
00321 def abort(self):
00322 self.__abort = 1
00323
00324 def serve_until_stopped(self):
00325 while not self.__abort:
00326 rd, wr, ex = select.select([self.socket.fileno()],
00327 [], [],
00328 self.timeout)
00329 if rd:
00330 self.handle_request()
00331
00332 class MSGLogGUIImpl(MSGLogGUI):
00333
00334 def __init__(self, port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
00335 updateInterval=100, parent = None,name = None,fl = 0):
00336 MSGLogGUI.__init__(self,parent,name,fl)
00337 #self.setCentralWidget( self.Logger )
00338 self.__secure = 0
00339 self.__timer = QTimer(self)
00340 QObject.connect(self.__timer, SIGNAL("timeout()"), self.addLogDataToView)
00341 self.__updateInterval = updateInterval
00342 self.__timer.start(self.__updateInterval)
00343 self.__port = port
00344 self.__level = 0
00345 self.__filename = None
00346 self.printer = QPrinter()
00347 self.filename = QString.null
00348 self.tcpserver = None
00349 self.__logname = "MSGLogger"
00350 self.__logData = []
00351 self.__logList = []
00352 self.__count = 0
00353 self.__previousMSG = ["","","",""]
00354 self.__previousMSGcut = ["",""]
00355
00356 self.imageFatal = QPixmap(imageFatal_data)
00357 self.imageError = QPixmap(imageError_data)
00358 self.imageWarn = QPixmap(imageWarn_data)
00359 self.imageInfo = QPixmap(imageInfo_data)
00360 self.imageDebug = QPixmap(imageDebug_data)
00361 self.imageNotset = QPixmap(imageNotset_data)
00362
00363 self.connect(self.filterbyCritical,SIGNAL("activated()"),self.levelCritical)
00364 self.connect(self.filterbyFatal,SIGNAL("activated()"),self.levelFatal)
00365 self.connect(self.filterbyError,SIGNAL("activated()"),self.levelError)
00366 self.connect(self.filterbyWarn,SIGNAL("activated()"),self.levelWarn)
00367 self.connect(self.filterbyInfo,SIGNAL("activated()"),self.levelInfo)
00368 self.connect(self.filterbyDebug,SIGNAL("activated()"),self.levelDebug)
00369 self.connect(self.filterbyNotset,SIGNAL("activated()"),self.levelNotset)
00370 self.connect(self.noFilter,SIGNAL("activated()"),self.levelNoFilter)
00371
00372 #~ self.connect(self.Logger,SIGNAL("currentChanged(QListViewItem*)"),self.preventSaturation)
00373 self.connect(self.Logger,SIGNAL("currentChanged(QListViewItem*)"),self.showEntries)
00374 self.connect(self.Logger, SIGNAL('clicked(QListViewItem*)'), self.preventCheck)
00375 self.connect(self.RunningLogButton,SIGNAL("clicked()"),self.switchToRunningLog)
00376 self.connect(self.FileLogButton,SIGNAL("clicked()"),self.fileOpen)
00377
00378 #atexit.register(logging.shutdown)
00379 atexit.register(self.__shutdown)
00380
00381 self.__hdlr = logging.StreamHandler()
00382 fmt = logging.Formatter("%(asctime)s %(filename)s:%(lineno)d %(levelname)-5s - %(message)s")
00383 self.__hdlr.setFormatter(fmt)
00384 logger = logging.getLogger(self.__logname)
00385 logger.addHandler(self.__hdlr)
00386 #logger.propagate = 0
00387
00388 self.Logger.setColumnAlignment(0, Qt.AlignCenter)
00389 self.Logger.header().setMovingEnabled(0)
00390
00391 self.Logger.setSorting(-1,1)
00392
00393 self.Logger.setColumnWidth(0,0)
00394 #~ self.Logger.setColumnWidth(1,40)
00395 #~ self.Logger.setColumnWidth(2,20)
00396 #~ self.Logger.setColumnWidth(3,80)
00397 #~ self.Logger.setColumnWidth(4,30)
00398
00399 #~ self.noFilter.setOn(1)
00400 logging.addLevelName(60, 'ALERT')
00401 logging.ALERT = 60
00402
00403 def preventSaturation(self):
00404 if self.Logger.childCount() >= MAX_ENTRIES:
00405 #print "too many entries"
00406 self.__timer.stop()
00407 item = self.Logger.firstChild()
00408 count = 0
00409 while (count < DELETE_ENTRIES):
00410 if QString.compare(item.text(1),'CRITICAL') != 0 and QString.compare(item.text(1),'FATAL') != 0 :
00411 count += 1
00412 if count >= self.Logger.childCount(): break
00413 saveItem = item.nextSibling()
00414 self.Logger.takeItem(item)
00415 item = saveItem
00416 else:
00417 item = item.nextSibling()
00418
00419 #~ item = item.nextSibling()
00420 self.__timer.start(self.__updateInterval)
00421
00422 def showEntries(self):
00423 self.statusBar().message('Number of entries: ' + str(self.Logger.childCount()))
00424
00425 def preventCheck(self):
00426 item = self.Logger.currentItem()
00427 if item is not None:
00428 if item.isOn():
00429 if QString.compare(item.text(1),'CRITICAL') == 0 or QString.compare(item.text(1),'FATAL') == 0 :
00430 self.statusBar().message('CRITICAL or FATAL error: Uncheck to Acknowledge',2000)
00431 else:
00432 self.statusBar().message('CRITICAL and FATAL errors check boxes ONLY are enabled to be acknowledged',2500)
00433 item.setOn(0)
00434
00435 def appendLogData(self, data):
00436 self.__logData.append(data)
00437 # if len(self.__logList) > 10000:
00438 # rc = QMessageBox.information(self,'GLAT Online Message Logger',
00439 # 'The Active Logger has reached the maximum of 10000 entries and will now close. Would you like to keep listening in a new log?',
00440 # 'Yes','No')
00441 # if rc == 0:
00442 # # Fill in here what to do
00443 # e.ignore()
00444 # else:
00445 # e.accept()
00446 # else:
00447 # self.__logList.append(data)
00448
00449 def switchToRunningLog(self):
00450 self.LogType.setText("Active Run Control Log")
00451 self.Logger.clear()
00452 #~ print "Data: ", self.__logData
00453 self.addLogDataToView()
00454 if not self.runTCPThread.isAlive():
00455 self.startListenerThread()
00456
00457 #~ for data in self.__logData:
00458
00459
00460 def abortListenerThread(self):
00461 if self.runTCPThread.isAlive():
00462 self.tcpserver.abort()
00463 self.runTCPThread.join()
00464
00465
00466 def startListenerThread(self):
00467 self.Logger.clear()
00468 self.LogType.setText("Active Run Control Log")
00469 self.LogType.setAlignment(QLineEdit.AlignLeft)
00470
00471 self.tcpserver = MSGLogSocketReceiver(self, host='', port=self.__port)
00472 self.tcpserver.logname = self.__logname
00473 self.runTCPThread = threading.Thread(target=self.runTCP, name=self.__logname, args=(self.tcpserver,))
00474 self.runTCPThread.start()
00475
00476
00477 def runTCP(self, tcpserver):
00478 try:
00479 tcpserver.serve_until_stopped()
00480 finally:
00481 tcpserver.server_close()
00482
00483
00484 def clearLevels(self):
00485 self.filterbyCritical.setOn(0)
00486 self.filterbyError.setOn(0)
00487 self.filterbyInfo.setOn(0)
00488 self.filterbyDebug.setOn(0)
00489 self.filterbyNotset.setOn(0)
00490 self.filterbyFatal.setOn(0)
00491 self.filterbyWarn.setOn(0)
00492 self.noFilter.setOn(0)
00493
00494 def levelCritical(self):
00495 self.clearLevels()
00496 self.filterbyCritical.setOn(1)
00497 self.__level = logging.CRITICAL
00498 #~ for i in range(self.Logger.childCount()-1):
00499 if QString.compare(self.LogType.text(), "Active Run Control Log") == 0 :
00500 self.switchToRunningLog()
00501 else:
00502 self.load( )
00503
00504 def levelFatal(self):
00505 self.clearLevels()
00506 self.filterbyFatal.setOn(1)
00507 self.__level = logging.CRITICAL
00508 if QString.compare(self.LogType.text(), "Active Run Control Log") == 0 :
00509 self.switchToRunningLog()
00510 else:
00511 self.load( )
00512
00513 def levelError(self):
00514 self.clearLevels()
00515 self.filterbyError.setOn(1)
00516 self.__level = logging.ERROR
00517 if QString.compare(self.LogType.text(), "Active Run Control Log") == 0 :
00518 self.switchToRunningLog()
00519 else:
00520 self.load( )
00521
00522 def levelWarn(self):
00523 self.clearLevels()
00524 self.filterbyWarn.setOn(1)
00525 self.__level = logging.WARN
00526 if QString.compare(self.LogType.text(), "Active Run Control Log") == 0 :
00527 self.switchToRunningLog()
00528 else:
00529 self.load( )
00530
00531 def levelInfo(self):
00532 self.clearLevels()
00533 self.filterbyInfo.setOn(1)
00534 self.__level = logging.INFO
00535 if QString.compare(self.LogType.text(), "Active Run Control Log") == 0 :
00536 self.switchToRunningLog()
00537 else:
00538 self.load( )
00539
00540 def levelDebug(self):
00541 self.clearLevels()
00542 self.filterbyDebug.setOn(1)
00543 self.__level = logging.DEBUG
00544 if QString.compare(self.LogType.text(), "Active Run Control Log") == 0 :
00545 self.switchToRunningLog()
00546 else:
00547 self.load( )
00548
00549 def levelNotset(self):
00550 self.clearLevels()
00551 self.filterbyNotset.setOn(1)
00552 self.__level = logging.NOTSET
00553 if QString.compare(self.LogType.text(), "Active Run Control Log") == 0 :
00554 self.switchToRunningLog()
00555 else:
00556 self.load( )
00557
00558 def levelNoFilter(self):
00559 self.clearLevels()
00560 self.noFilter.setOn(1)
00561 self.__level = logging.NOTSET
00562 if QString.compare(self.LogType.text(), "Active Run Control Log") == 0 :
00563 #~ self.addLogDataToView()
00564 self.switchToRunningLog()
00565 else:
00566 self.load( )
00567
00568 def setListViewItem(self, data):
00569 #~ imageFatal = QPixmap(imageFatal_data)
00570 #~ imageError = QPixmap(imageError_data)
00571 #~ imageWarn = QPixmap(imageWarn_data)
00572 #~ imageInfo = QPixmap(imageInfo_data)
00573 #~ imageDebug = QPixmap(imageDebug_data)
00574 #~ imageNotset = QPixmap(imageNotset_data)
00575
00576 level = self.__level
00577
00578 p = data.rstrip()
00579
00580 s = string.splitfields(p)
00581 temps = string.splitfields(p)
00582 r = string.splitfields(p, ' - ',3)
00583
00584 #Corrects the fact that FATAL is not included in the defs of
00585 # __init__.py for logging in python22
00586
00587 if temps[3] == 'FATAL':
00588 temps[3] = 'CRITICAL'
00589
00590 if logging._levelNames[temps[3]] >= level:
00591 if s[2] == self.__previousMSG[2] and s[3] == self.__previousMSG[3] \
00592 and r[1] == self.__previousMSGcut:
00593 #print s[2], s[3], r[1], self.__count
00594 self.__count += 1
00595
00596 else:
00597 if self.__count >= 3:
00598 messageItem = QCheckListItem( self.Logger,self.Logger.lastItem(), "", QCheckListItem.CheckBox )
00599
00600 messageItem.setText( 1, self.__previousMSG[3])
00601 messageItem.setText( 2, self.__previousMSG[0])
00602 messageItem.setText( 3, self.__previousMSG[1])
00603 messageItem.setText( 4, self.__previousMSG[2])
00604 #~ for i in range (0, 4):
00605 #~ messageItem.setText( i, self.__previousMSG[i])
00606 self.__countMSG = "The previous message was repeated " + str(self.__count) + " time(s)."
00607 messageItem.setText(5, self.__countMSG)
00608
00609 if self.__previousMSG[3] == 'CRITICAL' or \
00610 self.__previousMSG[3] == 'FATAL' or \
00611 self.__previousMSG[3] == 'ALERT':
00612 messageItem.setPixmap(1, self.imageFatal)
00613 messageItem.setOn(1)
00614
00615 elif self.__previousMSG[3] == 'ERROR':
00616 messageItem.setPixmap(1, self.imageError)
00617
00618 elif self.__previousMSG[3] == 'WARNING':
00619 messageItem.setPixmap(1, self.imageWarn)
00620
00621 elif self.__previousMSG[3] == 'INFO':
00622 messageItem.setPixmap(1, self.imageInfo)
00623
00624 elif self.__previousMSG[3] == 'DEBUG':
00625 messageItem.setPixmap(1, self.imageDebug)
00626
00627 elif self.__previousMSG[3] == 'NOTSET':
00628 messageItem.setPixmap(1, self.imageNotset)
00629 self.__count = 0
00630
00631 item = QCheckListItem( self.Logger, self.Logger.lastItem(), "", QCheckListItem.CheckBox)
00632
00633 item.setText( 1, s[3])
00634 item.setText( 2, s[0])
00635 item.setText( 3, s[1])
00636 item.setText( 4, s[2])
00637 #~ for i in range (0, 4):
00638 #~ item
00639 #~ item.setText( i, s[i])
00640 item.setText(5, r[1])
00641
00642 if s[3] == 'ALERT':
00643 item.setPixmap(1, self.imageFatal)
00644 item.setOn(1)
00645 self.handleAlert(s)
00646
00647 elif s[3] == 'CRITICAL' or s[3] == 'FATAL':
00648 item.setPixmap(1, self.imageFatal)
00649 item.setOn(1)
00650
00651 elif s[3] == 'ERROR':
00652 item.setPixmap(1, self.imageError)
00653
00654 elif s[3] == 'WARNING':
00655 item.setPixmap(1, self.imageWarn)
00656
00657 elif s[3] == 'INFO':
00658 item.setPixmap(1, self.imageInfo)
00659
00660 elif s[3] == 'DEBUG':
00661 item.setPixmap(1, self.imageDebug)
00662
00663 elif s[3] == 'NOTSET':
00664 item.setPixmap(1, self.imageNotset)
00665
00666 self.__previousMSG = s
00667 self.__previousMSGcut = r[1]
00668
00669 self.preventSaturation()
00670
00671 def handleAlert(self, s):
00672 pass
00673 # print "handleAlert", s
00674
00675 def addLogDataToView(self):
00676 #~ list = []
00677 #~ list.append(data)
00678 self.Logger.blockSignals(1)
00679 while len(self.__logData) > 0:
00680 data = self.__logData.pop(0)
00681 self.setListViewItem(data)
00682
00683 vScroll = self.Logger.verticalScrollBar()
00684 #~ print vScroll.value(), vScroll.maxValue()
00685 if not self.PauseLogButton.isOn() and not vScroll.draggingSlider() :
00686 vScroll.setValue(vScroll.maxValue())
00687
00688 self.Logger.blockSignals(0)
00689 self.showEntries()
00690
00691 #~ def switchToRunningLog(self):
00692 #~ self.Logger.clear()
00693 #~ for data in self.__logList:
00694 #~ self.setListViewItem(data)
00695
00696 def load( self ):
00697
00698 if self.tcpserver is not None:
00699 self.abortListenerThread()
00700 self.Logger.clear()
00701
00702 f = file( str(self.__filename), 'r' )
00703
00704 #~ if not f.open( IO_ReadOnly ):
00705 #~ return
00706
00707 #self.__filename = filename
00708 #~ t = QTextStream( f )
00709
00710 #~ self.noFilter.setOn(1)
00711 multi_line = 0
00712 while 1:
00713 data = f.readline()
00714 data = data[:len(data)-1]
00715 if data == "":
00716 break
00717 if multi_line == 0:
00718 (data1, data2) = data.split(" - ",1)
00719 if data2.startswith("<
00720 datax = data1 + " - " + data2[3:]
00721 multi_line = 1
00722 continue
00723 if multi_line:
00724 if data.endswith("
00725 datax += "\n" + data[:-3]
00726 multi_line = 0
00727 else:
00728 datax += "\n" + data
00729 continue
00730 else:
00731 datax = data
00732 self.setListViewItem(datax)
00733
00734 f.close()
00735
00736 def filePrint(self):
00737 Margin = 50
00738 pageNo = 1
00739 column = [0, 50, 110, 180, 260, 400]#, 325] # Magic numbers
00740
00741 # If there are no items, don't try to print
00742 if not self.Logger.firstChild():
00743 return
00744
00745 if self.printer.setup(self):
00746 self.statusBar().message('Printing...')
00747
00748 p = QPainter()
00749 p.begin(self.printer)
00750 p.setFont(self.Logger.font())
00751 yPos = 0
00752 fm = p.fontMetrics()
00753 metrics = QPaintDeviceMetrics(self.printer)
00754
00755 if QString.compare(self.LogType.text(), "Active Run Control Log") == 0 :
00756 header = "Message Logger Source: Active Run Control Log"
00757 else:
00758 header = "Message Logger Source: " + str(self.__filename)
00759
00760 page = "Page: 1"
00761 p.drawText(Margin,Margin + yPos,metrics.width(),fm.lineSpacing(),Qt.ExpandTabs | Qt.DontClip, header)
00762 yPos = yPos + fm.lineSpacing()
00763 p.drawText(Margin,Margin + yPos,metrics.width(),fm.lineSpacing(),Qt.ExpandTabs | Qt.DontClip, page)
00764 yPos = yPos + 2*fm.lineSpacing()
00765
00766 columnHeader = ['','Severity','Date','Time','Source','Message']
00767
00768 for i in range (0,6):
00769 p.drawText(column[i],Margin + yPos,metrics.width(),fm.lineSpacing(),
00770 Qt.ExpandTabs | Qt.DontClip, columnHeader[i])
00771 yPos = yPos + fm.lineSpacing()
00772
00773 item = self.Logger.firstChild()
00774 for j in range(self.Logger.childCount()):
00775 if Margin + yPos > metrics.height() - Margin:
00776 pageNo = pageNo + 1
00777 page = "Page: " + str(pageNo)
00778 self.statusBar().message('Printing (page %d)...' % (pageNo))
00779 self.printer.newPage()
00780 yPos = 0
00781 p.drawText(Margin,Margin + yPos,metrics.width(),fm.lineSpacing(),Qt.ExpandTabs | Qt.DontClip, header)
00782 yPos = yPos + fm.lineSpacing()
00783 p.drawText(Margin,Margin + yPos,metrics.width(),fm.lineSpacing(),Qt.ExpandTabs | Qt.DontClip, page)
00784 yPos = yPos + 2*fm.lineSpacing()
00785
00786 for i in range (0,6):
00787 p.drawText(column[i],Margin + yPos,metrics.width(),fm.lineSpacing(),
00788 Qt.ExpandTabs | Qt.DontClip, columnHeader[i])
00789 yPos = yPos + fm.lineSpacing()
00790
00791 for i in range (0,6):
00792 p.drawText(column[i],Margin + yPos,metrics.width(),fm.lineSpacing(),
00793 Qt.ExpandTabs | Qt.DontClip,item.text(i))
00794 yPos = yPos + fm.lineSpacing()
00795 item = item.nextSibling()
00796
00797 p.end()
00798 self.statusBar().message('Printing completed',2000)
00799 else:
00800 self.statusBar().message('Printing aborted',2000)
00801
00802 def Help(self):
00803 pass
00804
00805 def fileNew(self):
00806 print "MSGLogGUIImpl.fileNew(): Not implemented yet"
00807
00808 def fileOpen(self):
00809 fn = QFileDialog.getOpenFileName( QString.null, "(*.log)", self, "Log file dialog",
00810 "Choose a Log File" )
00811 if not fn.isEmpty():
00812 self.__filename = fn
00813 self.LogType.setText(str(self.__filename))
00814 self.LogType.setAlignment(QLineEdit.AlignRight)
00815 self.load( )
00816
00817 def fileSave(self):
00818 if self.__filename.isEmpty():
00819 self.fileSaveAs()
00820 return
00821
00822 self.Logger.save( self.__filename )
00823
00824 def fileSaveAs(self):
00825 fn = QFileDialog.getSaveFileName( QString.null, QString.null, self )
00826 if not fn.isEmpty():
00827 self.__filename = fn
00828 self.fileSave()
00829
00830 def fileExit(self):
00831 self.close()
00832
00833 def closeEvent(self, e):
00834 if self.__secure:
00835 e.ignore()
00836 return
00837 if self.Logger.childCount() == 0:
00838 e.accept()
00839 item = self.Logger.firstChild()
00840 for i in range(self.Logger.childCount()-1):
00841 if item.isOn() :#and item.text(3) == "CRITICAL":# or item.text(3) == 'FATAL':
00842 rc = QMessageBox.information(self,'GLAT Online Message Logger',
00843 'Please acknowledge all CRITICAL and FATAL errors before exit by unchecking the box at the beginning of the entry',
00844 'OK','Exit Anyway')
00845 if rc == 0:
00846 e.ignore()
00847 break
00848 else:
00849 e.accept()
00850 break
00851
00852 item = item.nextSibling()
00853 e.accept()
00854
00855 def __shutdown(self):
00856 self.abortListenerThread()
00857
00858 def setSecure(self, secure):
00859 self.__secure = secure
00860
00861
00862 if __name__ == "__main__":
00863 import logging.handlers
00864 from LATTE.client.gOptions import Options
00865 def usage(msg):
00866 print """
00867 Error %s
00868 Usage: python MSGLogGUIImpl.py [--port <portno>] (default: %d)
00869 """ % (msg, logging.handlers.DEFAULT_TCP_LOGGING_PORT)
00870
00871 options = Options([],['port'],[])
00872 try:
00873 options.parse()
00874 except Exception, msg:
00875 usage(msg)
00876 sys.exit()
00877
00878 a = QApplication(sys.argv)
00879 QObject.connect(a,SIGNAL("lastWindowClosed()"),a,SLOT("quit()"))
00880 if options.port is None:
00881 port = logging.handlers.DEFAULT_TCP_LOGGING_PORT
00882 else:
00883 port = int(options.port)
00884 w = MSGLogGUIImpl(port)
00885 w.startListenerThread()
00886 a.setMainWidget(w)
00887 w.show()
00888 a.exec_loop()