sugar-toolkit-gtk3/services/console/interface/logviewer/logviewer.py
2007-10-07 17:09:35 -04:00

229 lines
7.2 KiB
Python

# Copyright (C) 2006, Red Hat, Inc.
#
# 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
# Rewritten by Eduardo Silva, edsiper@gmail.com
import os
import pygtk
import gtk
import gobject
import pango
import gnomevfs
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 Interface:
def __init__(self):
# 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.widget = viewer.hbox