
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])

    def level_number(self, level):
        return self.levels.index(level)

class LogView(gtk.TreeView):

    def __init__(self, logger=None, level='notice'):
        self.logger = logger 
        self.model = logger.store
        self.level = level
        self.level_no = logger.level_number(level)

        # Set up filter
        self.filter = self.model.filter_new()
        gtk.TreeView.__init__(self, self.filter)
        self.filter.set_visible_func(self.level_filter)

        # 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)

        # 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()

        item_no = logger.level_number(view.level)
        items[item_no].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
