controls/LogViewer.py
changeset 982 e3c264099bd0
parent 981 fc671a3e95a9
child 983 7dd481eef3b5
equal deleted inserted replaced
981:fc671a3e95a9 982:e3c264099bd0
    22 #License along with this library; if not, write to the Free Software
    22 #License along with this library; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    24 
    24 
    25 from datetime import datetime
    25 from datetime import datetime
    26 from time import time as gettime
    26 from time import time as gettime
       
    27 import numpy
    27 
    28 
    28 import wx
    29 import wx
    29 
    30 
    30 from graphics import DebugViewer, REFRESH_PERIOD
    31 from graphics import DebugViewer, REFRESH_PERIOD
    31 from targets.typemapping import LogLevelsCount, LogLevels
    32 from targets.typemapping import LogLevelsCount, LogLevels
    84             elif posy < thumb_rect.y:
    85             elif posy < thumb_rect.y:
    85                 self.Parent.ScrollToLast()
    86                 self.Parent.ScrollToLast()
    86             elif posy > thumb_rect.y + thumb_rect.height:
    87             elif posy > thumb_rect.y + thumb_rect.height:
    87                 self.Parent.ScrollToFirst()
    88                 self.Parent.ScrollToFirst()
    88         elif posy < width:
    89         elif posy < width:
    89             pass
    90             self.Parent.ScrollMessagePanelByTimestamp(1)
    90         elif posy > height - width:
    91         elif posy > height - width:
    91             pass
    92             self.Parent.ScrollMessagePanelByTimestamp(-1)
    92         event.Skip()
    93         event.Skip()
    93         
    94         
    94     def OnLeftUp(self, event):
    95     def OnLeftUp(self, event):
    95         self.ThumbScrollingStartPos = None
    96         self.ThumbScrollingStartPos = None
    96         self.RefreshThumbPosition(0.)
    97         self.RefreshThumbPosition(0.)
   159     
   160     
   160     def __init__(self, tv_sec, tv_nsec, level, level_bitmap, msg):
   161     def __init__(self, tv_sec, tv_nsec, level, level_bitmap, msg):
   161         self.Date = datetime.fromtimestamp(tv_sec)
   162         self.Date = datetime.fromtimestamp(tv_sec)
   162         self.Seconds = self.Date.second + tv_nsec * 1e-9
   163         self.Seconds = self.Date.second + tv_nsec * 1e-9
   163         self.Date = self.Date.replace(second=0)
   164         self.Date = self.Date.replace(second=0)
       
   165         self.Timestamp = tv_sec + tv_nsec * 1e-9
   164         self.Level = level
   166         self.Level = level
   165         self.LevelBitmap = level_bitmap
   167         self.LevelBitmap = level_bitmap
   166         self.Message = msg
   168         self.Message = msg
   167         self.DrawDate = True
   169         self.DrawDate = True
   168     
   170     
   198 HOUR = 60 * MINUTE
   200 HOUR = 60 * MINUTE
   199 DAY = 24 * HOUR
   201 DAY = 24 * HOUR
   200 
   202 
   201 CHANGE_TIMESTAMP_BUTTONS = [(_("1d"), DAY),
   203 CHANGE_TIMESTAMP_BUTTONS = [(_("1d"), DAY),
   202                             (_("1h"), HOUR),
   204                             (_("1h"), HOUR),
   203                             (_("1m"), MINUTE),
   205                             (_("1m"), MINUTE)]
   204                             (_("1s"), SECOND)]
       
   205 REVERSE_CHANGE_TIMESTAMP_BUTTONS = CHANGE_TIMESTAMP_BUTTONS[:]
   206 REVERSE_CHANGE_TIMESTAMP_BUTTONS = CHANGE_TIMESTAMP_BUTTONS[:]
   206 REVERSE_CHANGE_TIMESTAMP_BUTTONS.reverse()
   207 REVERSE_CHANGE_TIMESTAMP_BUTTONS.reverse()
   207 
   208 
   208 class LogViewer(DebugViewer, wx.Panel):
   209 class LogViewer(DebugViewer, wx.Panel):
   209     
   210     
   287     
   288     
   288     def ResetLogMessages(self):
   289     def ResetLogMessages(self):
   289         self.previous_log_count = [None]*LogLevelsCount
   290         self.previous_log_count = [None]*LogLevelsCount
   290         self.OldestMessages = []
   291         self.OldestMessages = []
   291         self.LogMessages = []
   292         self.LogMessages = []
       
   293         self.LogMessagesTimestamp = numpy.array([])
   292         self.CurrentMessage = None
   294         self.CurrentMessage = None
   293         self.HasNewData = False
   295         self.HasNewData = False
   294     
   296     
   295     def SetLogSource(self, log_source):
   297     def SetLogSource(self, log_source):
   296         self.LogSource = log_source
   298         self.LogSource = log_source
   332         if len(new_messages) > 0:
   334         if len(new_messages) > 0:
   333             self.HasNewData = True
   335             self.HasNewData = True
   334             old_length = len(self.LogMessages)
   336             old_length = len(self.LogMessages)
   335             for new_message in new_messages:
   337             for new_message in new_messages:
   336                 self.LogMessages.append(new_message)
   338                 self.LogMessages.append(new_message)
       
   339                 self.LogMessagesTimestamp = numpy.append(self.LogMessagesTimestamp, [new_message.Timestamp])
   337             if self.CurrentMessage is None or self.CurrentMessage == old_length - 1:
   340             if self.CurrentMessage is None or self.CurrentMessage == old_length - 1:
   338                 self.CurrentMessage = len(self.LogMessages) - 1
   341                 self.CurrentMessage = len(self.LogMessages) - 1
   339             self.NewDataAvailable(None)
   342             self.NewDataAvailable(None)
   340     
   343     
   341     def FilterLogMessage(self, message):
   344     def FilterLogMessage(self, message, timestamp=None):
   342         return message.Level in self.CurrentFilter and message.Message.find(self.CurrentSearchValue) != -1
   345         return (message.Level in self.CurrentFilter and 
       
   346                 message.Message.find(self.CurrentSearchValue) != -1 and
       
   347                 (timestamp is None or message.Timestamp < timestamp))
       
   348     
       
   349     def GetMessageByTimestamp(self, timestamp):
       
   350         if self.CurrentMessage is not None:
       
   351             msgidx = numpy.argmin(abs(self.LogMessagesTimestamp - timestamp))
       
   352             message = self.LogMessages[msgidx]
       
   353             if self.FilterLogMessage(message) and message.Timestamp > timestamp:
       
   354                 return self.GetPreviousMessage(msgidx, timestamp)
       
   355             return message, msgidx
       
   356         return None, None
   343     
   357     
   344     def GetNextMessage(self, msgidx):
   358     def GetNextMessage(self, msgidx):
   345         while msgidx < len(self.LogMessages) - 1:
   359         while msgidx < len(self.LogMessages) - 1:
   346             message = self.LogMessages[msgidx + 1]
   360             message = self.LogMessages[msgidx + 1]
   347             if self.FilterLogMessage(message):
   361             if self.FilterLogMessage(message):
   348                 return message, msgidx + 1
   362                 return message, msgidx + 1
   349             msgidx += 1
   363             msgidx += 1
   350         return None, None
   364         return None, None
   351     
   365     
   352     def GetPreviousMessage(self, msgidx):
   366     def GetPreviousMessage(self, msgidx, timestamp=None):
   353         message = None
   367         message = None
   354         while 0 < msgidx < len(self.LogMessages):
   368         while 0 < msgidx < len(self.LogMessages):
   355             message = self.LogMessages[msgidx - 1]
   369             message = self.LogMessages[msgidx - 1]
   356             if self.FilterLogMessage(message):
   370             if self.FilterLogMessage(message, timestamp):
   357                 return message, msgidx - 1
   371                 return message, msgidx - 1
   358             msgidx -= 1
   372             msgidx -= 1
   359         if len(self.LogMessages) > 0:
   373         if len(self.LogMessages) > 0:
   360             message = self.LogMessages[0]
   374             message = self.LogMessages[0]
   361             while message is not None:
   375             while message is not None:
   373                 for idx, msg in self.OldestMessages:
   387                 for idx, msg in self.OldestMessages:
   374                     if msg is not None and (message is None or msg > message):
   388                     if msg is not None and (message is None or msg > message):
   375                         message = msg
   389                         message = msg
   376                 if message is not None:
   390                 if message is not None:
   377                     self.LogMessages.insert(0, message)
   391                     self.LogMessages.insert(0, message)
       
   392                     self.LogMessagesTimestamp = numpy.insert(self.LogMessagesTimestamp, [0], [message.Timestamp])
   378                     if self.CurrentMessage is not None:
   393                     if self.CurrentMessage is not None:
   379                         self.CurrentMessage += 1
   394                         self.CurrentMessage += 1
   380                     else:
   395                     else:
   381                         self.CurrentMessage = 0
   396                         self.CurrentMessage = 0
   382                     if self.FilterLogMessage(message):
   397                     if self.FilterLogMessage(message, timestamp):
   383                         return message, 0
   398                         return message, 0
   384         return None, None
   399         return None, None
   385     
   400     
   386     def RefreshNewData(self, *args, **kwargs):
   401     def RefreshNewData(self, *args, **kwargs):
   387         if self.HasNewData:
   402         if self.HasNewData:
   452                 if message is not None:
   467                 if message is not None:
   453                     self.CurrentMessage = msgidx
   468                     self.CurrentMessage = msgidx
   454                     scroll += 1
   469                     scroll += 1
   455             self.RefreshView()
   470             self.RefreshView()
   456     
   471     
       
   472     def ScrollMessagePanelByTimestamp(self, seconds):
       
   473         if self.CurrentMessage is not None:
       
   474             current_message = self.LogMessages[self.CurrentMessage]
       
   475             message, msgidx = self.GetMessageByTimestamp(current_message.Timestamp + seconds)
       
   476             if message is None or self.IsMessagePanelBottom(msgidx):
       
   477                 self.ScrollToFirst()
       
   478             else:
       
   479                 self.CurrentMessage = msgidx
       
   480                 self.Refresh()
       
   481             
   457     def ResetMessagePanel(self):
   482     def ResetMessagePanel(self):
   458         if len(self.LogMessages) > 0:
   483         if len(self.LogMessages) > 0:
   459             self.CurrentMessage = len(self.LogMessages) - 1
   484             self.CurrentMessage = len(self.LogMessages) - 1
   460             message = self.LogMessages[self.CurrentMessage]
   485             message = self.LogMessages[self.CurrentMessage]
   461             while message is not None and not self.FilterLogMessage(message):
   486             while message is not None and not self.FilterLogMessage(message):
   483         self.ResetMessagePanel()
   508         self.ResetMessagePanel()
   484         event.Skip()
   509         event.Skip()
   485     
   510     
   486     def GenerateOnDurationButton(self, duration):
   511     def GenerateOnDurationButton(self, duration):
   487         def OnDurationButton(event):
   512         def OnDurationButton(event):
       
   513             self.ScrollMessagePanelByTimestamp(duration)
   488             event.Skip()
   514             event.Skip()
   489         return OnDurationButton
   515         return OnDurationButton
   490     
   516     
   491     def OnMessagePanelMouseWheel(self, event):
   517     def OnMessagePanelMouseWheel(self, event):
   492         self.ScrollMessagePanel(event.GetWheelRotation() / event.GetWheelDelta())
   518         self.ScrollMessagePanel(event.GetWheelRotation() / event.GetWheelDelta())