import gobject import gtk import time class Logger: def __init__(self): self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self.levels = ['debug', 'notice', 'warning', 'error'] self.level_text = {'debug': 'Debug', 'notice': 'Notice', 'warning': 'Warning', 'error': 'Error'} self.components = {} self.colors = { 'debug': 'grey', 'notice': 'black', 'warning': 'brown', 'error': 'red' } def log(self, level, message): iter = self.store.append() self.store.set_value(iter, 0, level) self.store.set_value(iter, 1, message) self.store.set_value(iter, 2, self.colors[level]) class LogView(gtk.TreeView): def __init__(self, logger=None, level='notice'): self.logger = logger self.model = logger.store # Set up filter self.filter = self.model.filter_new() gtk.TreeView.__init__(self, self.filter) self.filter.set_visible_func(self.level_filter) self.set_level(level) # Set up log level column renderer = gtk.CellRendererText() self.level_col = gtk.TreeViewColumn('Level', renderer, text=0) self.level_col.add_attribute(renderer, "foreground", 2) self.append_column(self.level_col) # Set up message column renderer = gtk.CellRendererText() self.message_col = gtk.TreeViewColumn('Message', renderer, text=1) self.message_col.add_attribute(renderer, "foreground", 2) self.append_column(self.message_col) # Activate context menu self.menu = LogMenu(self.logger, self) self.connect('popup_menu', self.popup_menu) self.connect('button_press_event', self.mouse_popup_menu) #self.connect('button_release_event', None) # Make sure tree view displays bottom entry when entered def scroll_to_last(model, path, it): if path: self.scroll_to_cell(path) self.model.connect('row-changed', scroll_to_last) def set_level(self, level): self.level = level self.level_no = self.logger.levels.index(level) self.filter.refilter() self.queue_draw() def popup_menu(self, *rest): self.menu.popup(None, None, None, 0, 0) def mouse_popup_menu(self, widget, event): if event.button == 3: self.menu.popup(None, None, None, event.button, event.time) def level_filter(self, store, iter): if store.get_value(iter,0): value = self.logger.levels.index(store.get_value(iter, 0)) return value >= self.level_no else: return False class LogLevelMenu(gtk.Menu): def __init__(self, logger, view): self.logger = logger self.view = view items = [] gtk.Menu.__init__(self) for level in logger.levels: if len(items) == 0: group = None else: group = items[0] item = gtk.RadioMenuItem(group, logger.level_text[level], level) item.connect('activate', self.set_log_level, level) items.append(item) self.append(item) item.show() items[0].set_active(True) def set_log_level(self, widget, level, *rest): if widget.active: self.view.set_level(level) class LogComponentMenu(gtk.Menu): def __init__(self, logger, view): gtk.Menu.__init__(self) components = logger.components.keys() components.sort(str.__gt__) for c in components: item = gtk.MenuItem(c) self.append(item) item.show() # for component in logger.components class LogMenu(gtk.Menu): def __init__(self, logger, view): gtk.Menu.__init__(self) self.logger = logger # View Log Level self.view_menu = LogLevelMenu(logger, view) self.view_item = gtk.MenuItem('View Log Level') self.view_item.set_submenu(self.view_menu) self.append(self.view_item) self.view_item.show() # View Components self.component_menu = LogComponentMenu(logger, view) self.component_item = gtk.MenuItem('View Components') self.component_item.set_submenu(self.component_menu) self.append(self.component_item) self.component_item.show() # Clear Log clear_item = gtk.MenuItem('Clear Log') clear_item.connect('activate', self.activate_clear_button) self.append(clear_item) clear_item.show() def activate_clear_button(self, item): self.logger.store.clear() logger = Logger() log = logger.log