diff options
Diffstat (limited to 'develop-activity/logviewer.py')
-rw-r--r-- | develop-activity/logviewer.py | 275 |
1 files changed, 138 insertions, 137 deletions
diff --git a/develop-activity/logviewer.py b/develop-activity/logviewer.py index 73d3007..d4e30f8 100644 --- a/develop-activity/logviewer.py +++ b/develop-activity/logviewer.py @@ -22,155 +22,154 @@ import os.path import logging from gettext import gettext as _ -import gtk -import gio +from gi.repository import Gdk +from gi.repository import Gtk +from gi.repository import Gio +from gi.repository import GObject -import activity_model -from sourceview_editor import TabLabel +from sugar3.graphics import style +from sugar3 import env -#does not import develop_app, but references internals from the activity, -# as passed to init. -#In other words, needs refactoring. +from sourceview_editor import TabLabel def _get_filename_from_path(path): return os.path.split(path)[-1] -class LogMinder(gtk.VBox): - def __init__(self, activity, namefilter, path=None, extra_files=None): - self.activity = activity +class LogFilesViewer(Gtk.ScrolledWindow): + __gtype_name__ = 'LogFileViewer' + + __gsignals__ = { + 'file-selected': (GObject.SignalFlags.RUN_FIRST, + None, + ([str])), + } + + def __init__(self, namefilter): + self._openlogs = [] - logging.info('creating MultiLogView') - if not path: - # Main path to watch: ~/.sugar/someuser/logs... - path = os.path.join(os.path.expanduser("~"), ".sugar", "default", - "logs") - - if not extra_files: - # extra files to watch in logviewer - extra_files = [] - extra_files.append("/var/log/Xorg.0.log") - extra_files.append("/var/log/syslog") - extra_files.append("/var/log/messages") - - self._logs_path = path + '/' - self._active_log = None - self._extra_files = extra_files + logging.info('creating LogFilesViewer namefilter %s', namefilter) + self._path = env.get_logs_path() + logging.error('LOGS PATH %s', self._path) + + self._extra_files = [os.path.join(self._path, 'shell.log')] self._namefilter = namefilter - # 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) - cellrenderer = gtk.CellRendererText() - self.treecolumn = gtk.TreeViewColumn(_("Sugar logs"), cellrenderer, - text=1) - self._tv_menu.append_column(self.treecolumn) - self._tv_menu.set_size_request(220, 900) + Gtk.ScrolledWindow.__init__(self) - # Create scrollbars around the tree view. - scrolled = gtk.ScrolledWindow() - scrolled.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - scrolled.add(self._tv_menu) + self.props.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC + self.props.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC + self.set_size_request(style.GRID_CELL_SIZE * 3, -1) - # the internals of the treeview - self._model = activity_model.DirectoryAndExtraModel( - path, extra_files, self._filter_by_name) + self._tree_view = Gtk.TreeView() + self._tree_view.connect('cursor-changed', self.__cursor_changed_cb) + self.add(self._tree_view) + self._tree_view.show() - self._tv_menu.set_model(self._model) + self._tree_view.props.headers_visible = False + selection = self._tree_view.get_selection() + selection.connect('changed', self.__selection_changed_cb) - self._logs = {} - self._monitors = [] + cell = Gtk.CellRendererText() + self._column = Gtk.TreeViewColumn() + self._column.pack_start(cell, True) + self._column.add_attribute(cell, 'text', 0) + self._tree_view.append_column(self._column) + self._tree_view.set_search_column(0) - # Activities menu - self.activity.treenotebook.add_page(_("Log"), scrolled) + # Configuration + self.set_title(_("Sugar logs")) + self.init_logs(self._filter_by_name) + self._monitors = [] self._configure_watcher() def _configure_watcher(self): - logging.error('Monitor directory %s', self._logs_path) - dir_monitor = gio.File(self._logs_path).monitor_directory() + logging.error('Monitor directory %s', self._path) + directory = Gio.File.new_for_path(self._path) + dir_monitor = directory.monitor_directory( + flags=Gio.FileMonitorFlags.NONE, cancellable=None) dir_monitor.set_rate_limit(2000) dir_monitor.connect('changed', self._log_file_changed_cb) self._monitors.append(dir_monitor) - for f in self._extra_files: logging.error('Monitor file %s', f) - file_monitor = gio.File(f).monitor_file() + gio_file = Gio.File.new_for_path(f) + file_monitor = gio_file.monitor_file( + Gio.FileMonitorFlags.NONE, None) file_monitor.set_rate_limit(2000) file_monitor.connect('changed', self._log_file_changed_cb) self._monitors.append(file_monitor) def _log_file_changed_cb(self, monitor, path1, path2, event): - _directory, logfile = os.path.split(str(path1)) - - if event == gio.FILE_MONITOR_EVENT_CHANGED: + if event == Gio.FileMonitorEvent.CHANGED: for log in self._openlogs: - if logfile in log.full_path: + if path1.get_path() == log.full_path: + logging.debug('updating logfile %s', path1.get_path()) log.update() - elif (event == gio.FILE_MONITOR_EVENT_DELETED - or event == gio.FILE_MONITOR_EVENT_CREATED): - self._model.refresh() - #If the log is open, just leave it that way - - # Load the log information in View (text_view) - def _load_log(self, treeview): - node = activity_model.get_selected_file(self._tv_menu) - print node - path = node["path"] - - if os.path.isdir(path): - #do not try to open folders - logging.debug("Cannot open a folder as text :)") + elif (event == Gio.FileMonitorEvent.DELETED + or event == Gio.FileMonitorEvent.CREATED): + self.load_model() + + def _filter_by_name(self, filename): + return self._namefilter in filename or filename in self._extra_files + + def init_logs(self, filter_function): + self._filter_function = filter_function + self.load_model() + + def load_model(self): + self._tree_view.set_model(Gtk.TreeStore(str, str)) + self._model = self._tree_view.get_model() + self._add_dir_to_model(self._path, self._filter_function) + + def _add_dir_to_model(self, dir_path, filter_function, parent=None): + for f in os.listdir(dir_path): + full_path = os.path.join(dir_path, f) + if os.path.isdir(full_path): + new_iter = self._model.append(parent, [f, full_path]) + self._add_dir_to_model(full_path, filter_function, new_iter) + else: + if filter_function(full_path): + self._model.append(parent, [f, full_path]) + + def __selection_changed_cb(self, selection): + model, tree_iter = selection.get_selected() + if tree_iter is None: + file_path = None + else: + file_path = model.get_value(tree_iter, 1) + self.emit('file-selected', file_path) + + def __cursor_changed_cb(self, treeview): + selection = treeview.get_selection() + store, iter_ = selection.get_selected() + if iter_ is None: + # Nothing selected. This happens at startup return + if store.iter_has_child(iter_): + path = store.get_path(iter_) + if treeview.row_expanded(path): + treeview.collapse_row(path) + else: + treeview.expand_row(path, False) - if not path: - #DummyActivityNode - return + def set_title(self, title): + self._column.set_title(title) - # Set buffer and scroll down - if self.activity.editor.set_to_page_like(path): - return - newlogview = LogView(path, self) - - scrollwnd = gtk.ScrolledWindow() - scrollwnd.set_policy(gtk.POLICY_AUTOMATIC, - gtk.POLICY_AUTOMATIC) - scrollwnd.add(newlogview) - scrollwnd.page = newlogview - tablabel = TabLabel(newlogview, label=node["name"]) - tablabel.connect( - 'tab-close', - lambda widget, child: self.activity.editor.remove_page( - self.activity.editor.page_num(child))) - self.activity.editor.append_page(scrollwnd, tablabel) - self._active_log = newlogview - self.activity.editor.show_all() - self.activity.editor.set_current_page(-1) - - def _filter_by_name(self, node): - return (self._namefilter in node.filename) or node.isDirectory - - # 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 - - def _remove_logview(self, logview): + def remove_logview(self, logview): try: self._openlogs.remove(logview) except ValueError: logging.debug("_remove_logview failed") -class LogBuffer(gtk.TextBuffer): - def __init__(self, logfile, tagtable): - gtk.TextBuffer.__init__(self, table=tagtable) +class LogBuffer(Gtk.TextBuffer): + + def __init__(self, logfile): + Gtk.TextBuffer.__init__(self) self._logfile = logfile self._pos = 0 @@ -193,62 +192,62 @@ class LogBuffer(gtk.TextBuffer): self._written = 0 -class LogView(gtk.TextView): +class LogView(Gtk.TextView): - def __init__(self, full_path, logminder): - gtk.TextView.__init__(self) + def __init__(self, full_path, log_file_viewer): + GObject.GObject.__init__(self) - self.logminder = logminder + self._log_file_viewer = log_file_viewer self.full_path = full_path - self.logminder._openlogs.append(self) + self._log_file_viewer._openlogs.append(self) - self.set_wrap_mode(gtk.WRAP_WORD) - - # Tags for search - tagtable = gtk.TextTagTable() - hilite_tag = gtk.TextTag('search-hilite') - hilite_tag.props.background = '#FFFFB0' - tagtable.add(hilite_tag) - select_tag = gtk.TextTag('search-select') - select_tag.props.background = '#B0B0FF' - tagtable.add(select_tag) + self.set_wrap_mode(Gtk.WrapMode.WORD) - newbuffer = self._create_log_buffer(full_path, tagtable) + newbuffer = self._create_log_buffer(full_path) if newbuffer: self.set_buffer(newbuffer) self.text_buffer = newbuffer # Set background color - bgcolor = gtk.gdk.color_parse("#EEEEEE") - self.modify_base(gtk.STATE_NORMAL, bgcolor) + bgcolor = Gdk.color_parse("#EEEEEE") + self.modify_base(Gtk.StateType.NORMAL, bgcolor) self.set_editable(False) self.show() def remove(self): - self.logminder._remove_logview(self) + self._log_file_viewer.remove_logview(self) - def _create_log_buffer(self, path, tagtable): + def _create_log_buffer(self, path): self._written = False if os.path.isdir(path): return False if not os.path.exists(path): - logging.error("ERROR: %s don't exists", path) + logging.error("_create_log_buffer: %s don't exists", path) return False if not os.access(path, os.R_OK): - logging.error("ERROR: I can't read '%s' file", path) + logging.error("_create_log_buffer: I can't read '%s' file", path) return False self.filename = _get_filename_from_path(path) - self._logbuffer = logbuffer = LogBuffer(path, tagtable) + self._logbuffer = LogBuffer(path) + + # Tags for search + tagtable = self._logbuffer.get_tag_table() + hilite_tag = Gtk.TextTag.new('search-hilite') + hilite_tag.props.background = '#FFFFB0' + tagtable.add(hilite_tag) + select_tag = Gtk.TextTag.new('search-select') + select_tag.props.background = '#B0B0FF' + tagtable.add(select_tag) - self._written = logbuffer._written + self._written = self._logbuffer._written - return logbuffer + return self._logbuffer def replace(self, *args, **kw): return (False, False) @@ -267,7 +266,8 @@ class LogView(gtk.TextView): text_iter = _buffer.get_start_iter() while True: - next_found = text_iter.forward_search(text, 0) + next_found = text_iter.forward_search( + text, Gtk.TextSearchFlags.CASE_INSENSITIVE, None) if next_found is None: break start, end = next_found @@ -291,9 +291,11 @@ class LogView(gtk.TextView): text_iter = _buffer.get_iter_at_mark(_buffer.get_insert()) if direction == 'backward': - return text_iter.backward_search(self.search_text, 0) + return text_iter.backward_search( + self.search_text, Gtk.TextSearchFlags.CASE_INSENSITIVE, None) else: - return text_iter.forward_search(self.search_text, 0) + return text_iter.forward_search( + self.search_text, Gtk.TextSearchFlags.CASE_INSENSITIVE, None) def search_next(self, direction): next_found = self.get_next_result(direction) @@ -306,5 +308,4 @@ class LogView(gtk.TextView): _buffer.apply_tag_by_name('search-select', start, end) _buffer.place_cursor(start) - self.scroll_to_iter(start, 0.1) - self.scroll_to_iter(end, 0.1) + self.scroll_to_iter(start, 0.1, False, 0, 0) |