From 46911776689384062cbf841cdac350fe0ec57e2c Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Wed, 24 Oct 2007 20:01:58 +0000 Subject: Logviewer --- (limited to 'logviewer.py') diff --git a/logviewer.py b/logviewer.py new file mode 100644 index 0000000..ead92bc --- /dev/null +++ b/logviewer.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python + +# Copyright (C) 2006-2007, Eduardo Silva +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import os +import logging +from gettext import gettext as _ + +import gtk +import dbus +import pygtk +import gobject +import pango +import gnomevfs + +from sugar.activity import activity +from sugar import env + +class MultiLogView(gtk.VBox): + def __init__(self, path, extra_files): + self._logs_path = path + self._active_log = None + self._extra_files = extra_files + + # Creating Main treeview with Actitivities list + self._tv_menu = gtk.TreeView() + self._tv_menu.connect('cursor-changed', self._load_log) + self._tv_menu.set_rules_hint(True) + + # Set width + box_width = gtk.gdk.screen_width() * 80 / 100 + self._tv_menu.set_size_request(box_width*25/100, 0) + + self._store_menu = gtk.TreeStore(str) + self._tv_menu.set_model(self._store_menu) + + self._add_column(self._tv_menu, 'Sugar logs', 0) + self._logs = {} + + # Activities menu + self.hbox = gtk.HBox(False, 3) + self.hbox.pack_start(self._tv_menu, True, True, 0) + + # Activity log, set width + self._view = LogView() + self._view.set_size_request(box_width*75/100, 0) + + self.hbox.pack_start(self._view, True, True, 0) + self.hbox.show_all() + self._configure_watcher() + self._create_log_view() + + + def _configure_watcher(self): + # Setting where gnomeVFS will be watching + gnomevfs.monitor_add('file://' + self._logs_path, + gnomevfs.MONITOR_DIRECTORY, + self._log_file_changed_cb) + + for f in self._extra_files: + gnomevfs.monitor_add('file://' + f, + gnomevfs.MONITOR_FILE, + self._log_file_changed_cb) + + def _log_file_changed_cb(self, monitor_uri, info_uri, event): + path = info_uri.split('file://')[-1] + filename = self._get_filename_from_path(path) + + if event == gnomevfs.MONITOR_EVENT_CHANGED: + self._logs[filename].update() + elif event == gnomevfs.MONITOR_EVENT_DELETED: + self._delete_log_file_view(filename) + elif event == gnomevfs.MONITOR_EVENT_CREATED: + self._add_log_file(path) + + # Load the log information in View (textview) + def _load_log(self, treeview): + treeselection = treeview.get_selection() + treestore, iter = treeselection.get_selected() + + # Get current selection + act_log = self._store_menu.get_value(iter, 0) + + # Set buffer and scroll down + self._view.textview.set_buffer(self._logs[act_log]) + self._view.textview.scroll_to_mark(self._logs[act_log].get_insert(), 0) + self._active_log = act_log + + def _create_log_view(self): + # Searching log files + for logfile in os.listdir(self._logs_path): + full_log_path = os.path.join(self._logs_path, logfile) + self._add_log_file(full_log_path) + + for ext in self._extra_files: + self._add_log_file(ext) + + return True + + def _delete_log_file_view(self, logkey): + self._store_menu.remove(self._logs[logkey].iter) + del self._logs[logkey] + + def _get_filename_from_path(self, path): + return path.split('/')[-1] + + def _add_log_file(self, path): + if os.path.isdir(path): + return False + + if not os.path.exists(path): + print "ERROR: %s don't exists" + return False + + logfile = self._get_filename_from_path(path) + + if not self._logs.has_key(logfile): + iter = self._add_log_row(logfile) + model = LogBuffer(path, iter) + self._logs[logfile] = model + + self._logs[logfile].update() + written = self._logs[logfile]._written + + # Load the first iter + if self._active_log == None: + self._active_log = logfile + iter = self._tv_menu.get_model().get_iter_root() + self._tv_menu.get_selection().select_iter(iter) + self._load_log(self._tv_menu) + + if written > 0 and self._active_log == logfile: + self._view.textview.scroll_to_mark(self._logs[logfile].get_insert(), 0) + + + def _add_log_row(self, name): + return self._insert_row(self._store_menu, None, name) + + # Add a new column to the main treeview, (code from Memphis) + def _add_column(self, treeview, column_name, index): + cell = gtk.CellRendererText() + col_tv = gtk.TreeViewColumn(column_name, cell, text=index) + col_tv.set_resizable(True) + col_tv.set_property('clickable', True) + + treeview.append_column(col_tv) + + # Set the last column index added + self.last_col_index = index + + # Insert a Row in our TreeView + def _insert_row(self, store, parent, name): + iter = store.insert_before(parent, None) + index = 0 + store.set_value(iter, index , name) + + return iter + +class LogBuffer(gtk.TextBuffer): + def __init__(self, logfile, iter=None): + gtk.TextBuffer.__init__(self) + + self._logfile = logfile + self._pos = 0 + self.iter = iter + self.update() + + def update(self): + try: + f = open(self._logfile, 'r') + init_pos = self._pos + + f.seek(self._pos) + self.insert(self.get_end_iter(), f.read()) + self._pos = f.tell() + f.close() + + self._written = (self._pos - init_pos) + except: + self.insert(self.get_end_iter(), "Console error: can't open the file\n") + self._written = 0 + +class LogView(gtk.ScrolledWindow): + def __init__(self): + gtk.ScrolledWindow.__init__(self) + + self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + + self.textview = gtk.TextView() + self.textview.set_wrap_mode(gtk.WRAP_WORD) + + font = pango.FontDescription('Sans 8') + font.set_weight(pango.WEIGHT_LIGHT) + self.textview.modify_font(font) + + # Set background color + bgcolor = gtk.gdk.color_parse("#FFFFFF") + self.textview.modify_base(gtk.STATE_NORMAL, bgcolor) + + self.textview.set_editable(False) + + self.add(self.textview) + self.textview.show() + + +class LogViewer(activity.Activity): + def __init__(self, handle): + activity.Activity.__init__(self, handle) + logging.debug('Starting the Log Viewer activity') + self.set_title(_('Log Viewer Activity')) + + # Main path to watch: ~/.sugar/someuser/logs... + main_path = os.path.join(env.get_profile_path(), 'logs') + + # extra files to watch in logviewer + ext_files = [] + ext_files.append("/var/log/Xorg.0.log") + ext_files.append("/var/log/syslog") + ext_files.append("/var/log/messages") + + viewer = MultiLogView(main_path, ext_files) + self.set_canvas(viewer.hbox) + + # TOOLBAR + toolbox = activity.ActivityToolbox(self) + toolbox.show() + + self.set_toolbox(toolbox) + self.show_all() + + # Dirty hide() + toolbar = toolbox.get_activity_toolbar() + toolbar.share.hide() + toolbar.keep.hide() -- cgit v0.9.1