gui/log: fix performance problems

This commit is contained in:
Sebastien Bourdeauducq 2015-10-31 00:34:14 +08:00
parent b61eb866b6
commit d8b98ae5d4
1 changed files with 80 additions and 34 deletions

View File

@ -6,7 +6,6 @@ from quamash import QtGui, QtCore
from pyqtgraph import dockarea, LayoutWidget from pyqtgraph import dockarea, LayoutWidget
from artiq.protocols.sync_struct import Subscriber from artiq.protocols.sync_struct import Subscriber
from artiq.gui.tools import ListSyncModel
try: try:
QSortFilterProxyModel = QtCore.QSortFilterProxyModel QSortFilterProxyModel = QtCore.QSortFilterProxyModel
@ -26,11 +25,19 @@ def _level_to_name(level):
return "DEBUG" return "DEBUG"
class _LogModel(ListSyncModel): class _LogModel(QtCore.QAbstractTableModel):
def __init__(self, parent, init): def __init__(self, parent, init):
ListSyncModel.__init__(self, QtCore.QAbstractTableModel.__init__(self, parent)
["Level", "Source", "Time", "Message"],
parent, init) self.headers = ["Level", "Source", "Time", "Message"]
self.entries = init
self.pending_entries = []
self.depth = 1000
timer = QtCore.QTimer(self)
timer.timeout.connect(self.timer_tick)
timer.start(100)
self.fixed_font = QtGui.QFont() self.fixed_font = QtGui.QFont()
self.fixed_font.setFamily("Monospace") self.fixed_font.setFamily("Monospace")
@ -40,36 +47,75 @@ class _LogModel(ListSyncModel):
self.warning_bg = QtGui.QBrush(QtGui.QColor(255, 255, 180)) self.warning_bg = QtGui.QBrush(QtGui.QColor(255, 255, 180))
self.error_bg = QtGui.QBrush(QtGui.QColor(255, 150, 150)) self.error_bg = QtGui.QBrush(QtGui.QColor(255, 150, 150))
def data(self, index, role): def headerData(self, col, orientation, role):
if (role == QtCore.Qt.FontRole and index.isValid() if (orientation == QtCore.Qt.Horizontal
and index.column() == 3): and role == QtCore.Qt.DisplayRole):
return self.fixed_font return self.headers[col]
elif role == QtCore.Qt.BackgroundRole and index.isValid(): return None
level = self.backing_store[index.row()][0]
if level >= logging.ERROR:
return self.error_bg
elif level >= logging.WARNING:
return self.warning_bg
else:
return self.white
elif role == QtCore.Qt.ForegroundRole and index.isValid():
level = self.backing_store[index.row()][0]
if level <= logging.DEBUG:
return self.debug_fg
else:
return self.black
else:
return ListSyncModel.data(self, index, role)
def convert(self, v, column): def rowCount(self, parent):
if column == 0: return len(self.entries)
return _level_to_name(v[0])
elif column == 1: def columnCount(self, parent):
return v[1] return len(self.headers)
elif column == 2:
return time.strftime("%m/%d %H:%M:%S", time.localtime(v[2])) def __delitem__(self, k):
else: pass
return v[3]
def append(self, v):
self.pending_entries.append(v)
def insertRows(self, position, rows=1, index=QtCore.QModelIndex()):
self.beginInsertRows(QtCore.QModelIndex(), position, position+rows-1)
self.endInsertRows()
def removeRows(self, position, rows=1, index=QtCore.QModelIndex()):
self.beginRemoveRows(QtCore.QModelIndex(), position, position+rows-1)
self.endRemoveRows()
def timer_tick(self):
if not self.pending_entries:
return
nrows = len(self.entries)
records = self.pending_entries
self.pending_entries = []
self.entries.extend(records)
self.insertRows(nrows, len(records))
if len(self.entries) > self.depth:
start = len(self.entries) - self.depth
self.entries = self.entries[start:]
self.removeRows(0, start)
def data(self, index, role):
if index.isValid():
if (role == QtCore.Qt.FontRole
and index.column() == 3):
return self.fixed_font
elif role == QtCore.Qt.BackgroundRole:
level = self.entries[index.row()][0]
if level >= logging.ERROR:
return self.error_bg
elif level >= logging.WARNING:
return self.warning_bg
else:
return self.white
elif role == QtCore.Qt.ForegroundRole:
level = self.entries[index.row()][0]
if level <= logging.DEBUG:
return self.debug_fg
else:
return self.black
elif role == QtCore.Qt.DisplayRole:
v = self.entries[index.row()]
column = index.column()
if column == 0:
return _level_to_name(v[0])
elif column == 1:
return v[1]
elif column == 2:
return time.strftime("%m/%d %H:%M:%S", time.localtime(v[2]))
else:
return v[3]
class _LogFilterProxyModel(QSortFilterProxyModel): class _LogFilterProxyModel(QSortFilterProxyModel):