17691N/A@@ -18,25 +18,15 @@ distuninstallcheck:
17691N/A distcleancheck_listfiles = find . -type f -print | grep -v 'omf\.out' | grep -v '
legal.xml'
17691N/A@@ -85,6 +85,7 @@ GNOMEVFS_REQUIRED=2.8.4
17691N/A LIBPANEL_APPLET_REQUIRED=2.13.4
17691N/A dnl *****************************************
17691N/A dnl libgnome, libgnomeui needed for all utils
17691N/A@@ -149,29 +150,6 @@ PKG_CHECK_MODULES(SCREENSHOT, gio-2.0 >= $GLIB_REQUIRED dnl
17691N/A-dnl ****************************************
17691N/A-dnl HAL for floppy detection in gfloppy
17691N/A-dnl ****************************************
17691N/A- AC_HELP_STRING([--enable-hal], [use HAL if available]), [
17691N/A- *) AC_MSG_ERROR(bad value ${enableval} for --enable-hal) ;;
17691N/A- [ENABLE_HAL=yes]) dnl Default value
17691N/A-if test "x$ENABLE_HAL" = "xyes"; then
17691N/A- PKG_CHECK_MODULES(HAL, hal >= 0.5.0,
17691N/A- AC_DEFINE(USE_HAL, 1, [defined if using libhal]),
17691N/A dnl *********************************************
17691N/A dnl *********************************************
17691N/A@@ -424,6 +402,9 @@ AC_SUBST(GREP_COMMAND)
17691N/A+PKG_CHECK_MODULES(GMODULE, gmodule-2.0 >= $GMODULE_REQUIRED)
17691N/A dnl This is where the binary actually resides,
17691N/A dnl not the console helper link
17691N/A EXPANDED_LOGVIEWDIR=`eval echo $LOGVIEWDIR_TMP`
17691N/A+PLUGIN_LIBTOOL_FLAGS="-module -avoid-version"
18268N/A@@ -469,34 +451,13 @@ AC_OUTPUT([
-baobab/pixmaps/24x24/Makefile
-gnome-dictionary/Makefile
-gnome-screenshot/Makefile
dnl <= Configuration summary =>
# Process this file with automake to produce
Makefile.in+SUBDIRS = . plugins help docs
+gnome_system_log_includedir = $(includedir)/gnome-system-log
+gnome_system_log_include_HEADERS = \
Utilitiesdir = $(datadir)/applications
additionaldir = $(datadir)/gnome-system-log
@@ -10,7 +21,8 @@ INCLUDES = \
-DG_LOG_DOMAIN=\"gnome-system-log\" \
-DGNOMELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-DDATADIR=\""$(datadir)"\" \
- -DLOGVIEWINSTALLPREFIX=\""$(prefix)/\"" \
+ -DLOGVIEWINSTALLPREFIX=\""$(prefix)/"\" \
@@ -24,12 +36,8 @@ gnome_system_log_SOURCES = \
@@ -37,12 +45,44 @@ gnome_system_log_SOURCES = \
gnome_system_log_LDADD = \
-man_MANS = gnome-system-log.1
+libgnome_system_log_la_SOURCES = \
+libgnome_system_log_la_LIBADD = \
Utilities_DATA = $(Utilities_in_files:
.desktop.in=.desktop)
@@ -98,3 +138,4 @@ CLEANFILES = \
cd $(distdir) ; rm -f $(CLEANFILES)
@@ -64,7 +64,7 @@ calendar_init_data (Calendar *calendar, LogviewWindow *logview)
g_return_if_fail (IS_CALENDAR (calendar));
g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
- g_object_get (G_OBJECT (logview), "days", &(calendar->priv->days), NULL);
+ g_object_get (G_OBJECT (logview->curlog), "days", &(calendar->priv->days), NULL);
calendar->priv->first_pass = TRUE;
calendar_mark_dates (calendar);
@@ -77,23 +77,6 @@ calendar_month_changed (GtkWidget *widget, gpointer data)
calendar_mark_dates (CALENDAR (widget));
-log_find_day (Log *log, int d, int m, int y)
- Day *day, *found_day = NULL;
- date = g_date_new_dmy (d, m+1, y);
- for (days = log->days; days!=NULL; days=g_slist_next(days)) {
- if (g_date_compare (day->date, date) == 0) {
calendar_day_selected (GtkWidget *widget, LogviewWindow *logview)
@@ -101,6 +84,9 @@ calendar_day_selected (GtkWidget *widget, LogviewWindow *logview)
+ GtkTreePath *select_first;
calendar = CALENDAR (widget);
@@ -113,11 +99,20 @@ calendar_day_selected (GtkWidget *widget, LogviewWindow *logview)
gtk_calendar_get_date (GTK_CALENDAR (calendar), &year, &month, &day);
- found_day = log_find_day (logview->curlog, day, month, year);
+ date = g_date_new_dmy (day, month+1, year);
+ found_day = log_find_day (logview->curlog, date);
+ g_object_get (G_OBJECT (logview->curlog),
+ "selected-paths", &selected_paths,
+ g_assert (selected_paths);
+ select_first = g_list_first (selected_paths)->data;
+ if ((gtk_tree_path_compare (path, select_first) != 0) &&
+ (!gtk_tree_path_is_descendant (select_first, path)))
gtk_tree_view_set_cursor (GTK_TREE_VIEW(logview->view), path, NULL, FALSE);
+# Process this file with automake to produce
Makefile.in+# Process this file with automake to produce
Makefile.in+## Process this file with automake to produce
Makefile.in+# The name of the module,
e.g. 'glib'.
+# The top-level SGML file. Change it if you want.
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting functions and macros.
+DOC_SOURCE_DIR=$(top_srcdir)/logview
+# Extra options to supply to gtkdoc-scan.
+# Extra options to pass to gtkdoc-scangobj
+# Extra options to supply to gtkdoc-mkdb.
+MKDB_OPTIONS=--sgml-mode --output-format=xml
+# Extra options to supply to gtkdoc-mktmpl
+#
e.g. MKTMPL_OPTIONS=--only-section-tmpl
+# Extra options to supply to gtkdoc-fixref.
+# Used for dependencies.
+HFILE_GLOB=$(top_srcdir)/logview/*.h
+CFILE_GLOB=$(top_srcdir)/logview/*.c
+# Header files to ignore when scanning.
+# Images to copy into HTML directory.
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
+# These files must be listed here *and* in content_files
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
+# signals and properties.
+#
e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+#
e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
+ $(GNOME_UTILS_CFLAGS) \
+ -I$(top_srcdir)/logview \
+ -I$(top_builddir)/logview
+# This includes the standard gtk-doc make rules, copied by gtkdocize.
+# Other files to distribute
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ <title>GNOME System Log Plugin Interfaces Reference Manual</title>
+ <para>This manual documents the Gnome System Log Plugin Interfaces.</para>
+ <title>Introduction</title>
+ <para>The Gnome System Log Plugin Interfaces enable endusers to implement
+ plugins to display non-ASCII formatted log files.</para>
+ <para>It was created for the GNOME System Log application, but it has been
+ made available for each developer whom wishes to implement plugins for
+ <title>API reference</title>
+ &LogviewIfaceCollector;
+ <title>Miscellaneous Utility Functions</title>
+logview_iface_collector_get_type
+logview_iface_view_get_type
+logview_iface_io_get_type
index a06ba81..5a2be33 100644
@@ -7,6 +7,7 @@ Terminal=false
Categories=GTK;GNOME;System;Monitor;
X-GNOME-Bugzilla-Bugzilla=GNOME
index 24ceab0..2c777c2 100644
static gboolean busy_cursor = FALSE;
logview_show_busy_cursor (LogviewWindow *logview)
- if (GTK_WIDGET_VISIBLE (logview->view) && logview->curlog->model == NULL) {
- cursor = gdk_cursor_new (GDK_WATCH);
- gdk_window_set_cursor (GTK_WIDGET (logview)->window, cursor);
- gdk_cursor_unref (cursor);
- gdk_display_flush (gtk_widget_get_display (GTK_WIDGET (logview)));
+ g_assert (logview->curlog);
+ g_object_get (G_OBJECT (logview->curlog), "model", &model, NULL);
+ if (GTK_WIDGET_VISIBLE (logview->view) && model == NULL) {
+ cursor = gdk_cursor_new (GDK_WATCH);
+ gdk_window_set_cursor (GTK_WIDGET (logview)->window, cursor);
+ gdk_cursor_unref (cursor);
+ gdk_display_flush (gtk_widget_get_display (GTK_WIDGET (logview)));
logview_show_normal_cursor (LogviewWindow *logview)
- gdk_window_set_cursor (GTK_WIDGET (logview)->window, NULL);
- gdk_display_flush (gtk_widget_get_display (GTK_WIDGET (logview)));
+ gdk_window_set_cursor (GTK_WIDGET (logview)->window, NULL);
+ gdk_display_flush (gtk_widget_get_display (GTK_WIDGET (logview)));
@@ -80,443 +77,296 @@ row_toggled_cb (GtkTreeView *treeview, GtkTreeIter *iter,
tree_path_find_row (GtkTreeModel *model, GtkTreePath *path, gboolean has_date)
- GtkTreePath *date_path;
- g_assert (GTK_IS_TREE_MODEL (model));
+ g_assert (GTK_IS_TREE_MODEL (model));
- indices = gtk_tree_path_get_indices (path);
+ indices = gtk_tree_path_get_indices (path);
- for (j = 0; j < indices[0]; j++) {
- date_path = gtk_tree_path_new_from_indices (j, -1);
- gtk_tree_model_get_iter (model, &iter, date_path);
- row += gtk_tree_model_iter_n_children (model, &iter);
- if (gtk_tree_path_get_depth (path) > 1)
+ for (j = 0; j < indices[0]; j++) {
+ GtkTreePath *date_path;
+ date_path = gtk_tree_path_new_from_indices (j, -1);
+ gtk_tree_model_get_iter (model, &iter, date_path);
+ gtk_tree_path_free (date_path);
+ row += gtk_tree_model_iter_n_children (model, &iter);
+ if (gtk_tree_path_get_depth (path) > 1)
selection_changed_cb (GtkTreeSelection *selection, gpointer data)
- int selected_first = -1, selected_last = -1;
- LogviewWindow *logview = data;
- GtkTreePath *selected_path;
- GList *selected_paths, *path;
+ LogviewWindow *logview = data;
+ GtkTreePath *selected_path;
- g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
- g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
- selected_paths = gtk_tree_selection_get_selected_rows (selection, &model);
+ g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
+ g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
- if (selected_paths == NULL)
- for (path = selected_paths; path != NULL; path = g_list_next (path)) {
- selected_path = path->data;
- row = tree_path_find_row (model, selected_path, (log->days != NULL));
- if (selected_last == -1 || row > selected_last) {
- if (selected_first == -1 || row < selected_first) {
- log->selected_line_first = selected_first;
- log->selected_line_last = selected_last;
- g_list_foreach (selected_paths, (GFunc) gtk_tree_path_free, NULL);
- g_list_free (selected_paths);
+ g_object_get (G_OBJECT (log),
+ "groupable", &groupable,
+ selected_paths = gtk_tree_selection_get_selected_rows (selection, &model);
+ if (selected_paths == NULL)
+ g_object_set (G_OBJECT (log), "selected-paths", selected_paths, NULL);
+ selected_path = gtk_tree_path_copy (g_list_first (selected_paths)->data);
- if (gtk_tree_path_get_depth (selected_path) > 1)
- gtk_tree_path_up (selected_path);
- gtk_tree_model_get_iter (model, &iter, selected_path);
- gtk_tree_model_get (model, &iter, DAY_POINTER, &day, -1);
- calendar_select_date (CALENDAR (logview->calendar), day->date);
- gtk_tree_path_free (selected_path);
+ if (gtk_tree_path_get_depth (selected_path) > 1)
+ gtk_tree_path_up (selected_path);
+ gtk_tree_model_get_iter (model, &iter, selected_path);
+ gtk_tree_model_get (model, &iter, DAY_POINTER, &day, -1);
+ calendar_select_date (CALENDAR (logview->calendar), day->date);
+ gtk_tree_path_free (selected_path);
logview_update_statusbar (LogviewWindow *logview)
- char *size, *modified, *index;
+ char *size, *modified, *index;
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
- gtk_statusbar_pop (GTK_STATUSBAR (logview->statusbar), 0);
+ gtk_statusbar_pop (GTK_STATUSBAR (logview->statusbar), 0);
- /* ctime returned string has "\n\0" causes statusbar display a invalid char */
- modified = ctime (&(log->stats->file_time));
- index = strrchr (modified, '\n');
- if (index && *index != '\0')
- modified = g_strdup_printf (_("last update: %s"), modified);
- size = gnome_vfs_format_file_size_for_display (log->stats->file_size);
- statusbar_text = g_strdup_printf (_("%d lines (%s) - %s"),
- log->total_lines, size, modified);
- gtk_statusbar_pop (GTK_STATUSBAR(logview->statusbar), 0);
- gtk_statusbar_push (GTK_STATUSBAR(logview->statusbar), 0, statusbar_text);
- g_free (statusbar_text);
+ /* ctime returned string has "\n\0" causes statusbar display a invalid char */
+ g_object_get (G_OBJECT (log),
+ "mtime", (glong *)&time,
+ "total-lines", &total_lines,
+ modified = ctime (&time);
+ index = strrchr (modified, '\n');
+ if (index && *index != '\0')
+ modified = g_strdup_printf (_("last update: %s"), modified);
+ size = gnome_vfs_format_file_size_for_display (log_size);
+ statusbar_text = g_strdup_printf (_("%d lines (%s) - %s"),
+ total_lines, size, modified);
+ gtk_statusbar_pop (GTK_STATUSBAR(logview->statusbar), 0);
+ gtk_statusbar_push (GTK_STATUSBAR(logview->statusbar), 0, statusbar_text);
+ g_free (statusbar_text);
logview_update_version_bar (LogviewWindow *logview)
- gtk_widget_hide (logview->version_bar);
- if (log->versions > 0 || log->parent_log != NULL) {
- gtk_widget_show_all (logview->version_bar);
- if (log->current_version > 0)
- recent = log->parent_log;
- gtk_combo_box_remove_text (GTK_COMBO_BOX (logview->version_selector), i);
- gtk_combo_box_append_text (GTK_COMBO_BOX (logview->version_selector), _("Current"));
- for (i=0; i<(recent->versions); i++) {
- label = g_strdup_printf ("Archive %d", i+1);
- gtk_combo_box_append_text (GTK_COMBO_BOX (logview->version_selector),
+ /* recreate the list, and emit the set active item signal */
+ if (logview->curlog == NULL) {
+ gtk_widget_hide_all (logview->version_bar);
+ g_assert (LOGVIEW_IS_LOG (logview->curlog));
+ /* get parent log. if only it hasn't parent log, update achive list. */
+ g_object_get (G_OBJECT (logview->curlog),
+ /* log is always the parent */
+ /* retrieve children list */
+ g_object_get (G_OBJECT (log),
+ "archives", &older_logs,
+ gtk_widget_hide_all (logview->version_bar);
+ /* the maximum text items of the combo box togather with "Current"
+ for (i = OLD_LOG_NUM; i >= 0; i--)
+ gtk_combo_box_remove_text (
+ GTK_COMBO_BOX (logview->version_selector),
+ gtk_combo_box_append_text (
+ GTK_COMBO_BOX (logview->version_selector),
+ for (i=0; i<OLD_LOG_NUM; i++) {
+ if (older_logs[i] == NULL)
+ g_object_get (G_OBJECT (older_logs[i]),
+ label = g_strdup_printf ("Archive %d", i);
+ gtk_combo_box_append_text (
+ GTK_COMBO_BOX (logview->version_selector),
+ gtk_widget_show_all (logview->version_bar);
- gtk_combo_box_set_active (GTK_COMBO_BOX (logview->version_selector),
- gtk_widget_hide (logview->version_bar);
+ g_object_get (G_OBJECT (log),
+ "current-version", ¤t_version, NULL);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (logview->version_selector),
-model_fill_date_iter (GtkTreeStore *model, GtkTreeIter *iter, Day *day)
- g_assert (GTK_IS_TREE_STORE (model));
- utf8 = date_get_string (day->date);
- gtk_tree_store_set (model, iter, MESSAGE, utf8, DAY_POINTER, day, -1);
-logview_unbold_rows (Log *log)
- LogviewWindow *logview;
- TreePathRange *bold_rows;
- if (log->bold_rows_list == NULL)
- if (logview->curlog != log)
- bold_rows = g_list_first (log->bold_rows_list)->data;
- g_assert (bold_rows != NULL);
- for (path = bold_rows->first;
- gtk_tree_path_compare (path, bold_rows->last)<=0;
- gtk_tree_path_next (path)) {
- gtk_tree_model_get_iter (log->model, &iter, path);
- gtk_tree_store_set (GTK_TREE_STORE (log->model), &iter,
- LOG_LINE_WEIGHT, PANGO_WEIGHT_NORMAL,
- LOG_LINE_WEIGHT_SET, TRUE, -1);
- gtk_tree_path_free (bold_rows->first);
- gtk_tree_path_free (bold_rows->last);
- log->bold_rows_list = g_list_remove (log->bold_rows_list, bold_rows);
-log_add_new_log_lines (Log *log)
- GtkTreeIter iter, child_iter, *iter_ptr;
- TreePathRange *bold_rows;
- if (log_read_new_lines (log) == FALSE)
- /* Find the last expandable row */
- day = g_slist_last (log->days)->data;
- gtk_tree_model_get_iter (log->model, &iter, day->path);
- for (i=log->displayed_lines; i<log->total_lines; i++) {
- gtk_tree_store_append (GTK_TREE_STORE (log->model), &child_iter, iter_ptr);
- gtk_tree_store_set (GTK_TREE_STORE (log->model), &child_iter,
- LOG_LINE_WEIGHT, PANGO_WEIGHT_BOLD,
- LOG_LINE_WEIGHT_SET, TRUE, -1);
- /* Remember the first and last bold lines in the model to
- if (i==log->displayed_lines) {
- bold_rows = g_new0 (TreePathRange, 1);
- bold_rows->first = gtk_tree_model_get_path (log->model, &child_iter);
- if (i == log->total_lines-1) {
- bold_rows->last = gtk_tree_model_get_path (log->model, &child_iter);
- log->displayed_lines = log->total_lines;
- log->bold_rows_list = g_list_append (log->bold_rows_list, bold_rows);
- g_timeout_add (5000, (GSourceFunc) logview_unbold_rows, log);
logview_scroll_and_focus_path (LogviewWindow *logview, Log *log)
- g_assert (LOGVIEW_IS_WINDOW (logview));
- GtkTreeSelection *selection;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (logview->view));
- if (log->bold_rows_list != NULL) {
- TreePathRange *bold_rows;
- bold_rows = g_list_last (log->bold_rows_list)->data;
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (logview->view),
- if (log->visible_first != NULL) {
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (logview->view),
+ GtkTreePath *last_bold_row;
+ GtkTreePath *visible_first;
+ GList *selected_paths, *idx;
+ GtkTreePath *selected_path;
-log_fill_model_no_date (Log *log, GtkTreeModel *model)
+ g_assert (LOGVIEW_IS_WINDOW (logview));
- for (i=log->total_lines-1; i>=0; i--) {
- gtk_tree_store_prepend (GTK_TREE_STORE (model), &iter, NULL);
- gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
- MESSAGE, line, DAY_POINTER, NULL, -1);
- if (i == (log->total_lines-1)) {
- path = gtk_tree_model_get_path (model, &iter);
- log->visible_first = gtk_tree_path_copy (path);
- gtk_tree_path_free (path);
-log_fill_day_iter (Log *log, GtkTreeModel *model, Day *day, GtkTreeIter *iter)
- GtkTreeIter child_iter;
- for (i = day->last_line; i >= day->first_line; i--) {
- gtk_tree_store_prepend (GTK_TREE_STORE (model), &child_iter, iter);
- gtk_tree_store_set (GTK_TREE_STORE (model), &child_iter,
- MESSAGE, log->lines[i], DAY_POINTER, NULL, -1);
-log_fill_model_with_date (Log *log, GtkTreeModel *model)
- g_assert (log->total_lines > 0);
- /* Cycle on the days in the log */
- /* It's not worth it to prepend instead of append */
- for (days = log->days; days != NULL; days = g_slist_next (days)) {
- gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
- model_fill_date_iter (GTK_TREE_STORE (model), &iter, day);
- day->path = gtk_tree_model_get_path (model, &iter);
- log_fill_day_iter (log, model, day, &iter);
- while (gtk_events_pending ())
- log->visible_first = gtk_tree_path_copy (day->path);
+ g_object_get (G_OBJECT (log),
+ "last-bold-row", &last_bold_row,
+ "visible-first", &visible_first,
+ "selected-paths", &selected_paths,
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (logview->view));
+ for (idx = selected_paths; idx; idx = g_list_next (idx)) {
+ GtkTreePath *selected_path = idx->data;
+ gtk_tree_selection_select_path (selection, selected_path);
- log->displayed_lines = log->total_lines;
+ if (last_bold_row != NULL) {
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (logview->view),
+ if (visible_first != NULL) {
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (logview->view),
-log_create_model (Log *log)
- g_assert (log != NULL);
- model = GTK_TREE_MODEL(gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER,
- G_TYPE_INT, G_TYPE_BOOLEAN));
- log_fill_model_with_date (log, model);
- log_fill_model_no_date (log, model);
logview_set_log_model (LogviewWindow *window, Log *log)
- g_assert (LOGVIEW_IS_WINDOW (window));
- g_assert (GTK_IS_TREE_MODEL (log->model));
- if (log->filter != NULL)
- gtk_tree_view_set_model (GTK_TREE_VIEW (window->view), GTK_TREE_MODEL (log->filter));
- gtk_tree_view_set_model (GTK_TREE_VIEW (window->view), log->model);
- if (log->days != NULL) {
- for (days=log->days; days != NULL; days = g_slist_next(days)) {
- gtk_tree_view_expand_row (GTK_TREE_VIEW (window->view),
+ GtkTreeModelFilter *filter;
+ g_assert (LOGVIEW_IS_WINDOW (window));
+ logview_show_busy_cursor (window);
+ g_object_get (G_OBJECT (log),
+ "groupable", &groupable,
+ g_assert (GTK_IS_TREE_MODEL (model));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (window->view),
+ GTK_TREE_MODEL (filter));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (window->view),
+ for (idx = days; idx != NULL; idx = g_slist_next(idx)) {
+ gtk_tree_view_expand_row (GTK_TREE_VIEW (window->view),
+ logview_show_normal_cursor (window);
logview_repaint (LogviewWindow *logview)
- g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ /* if log has updated, get new lines and repaint the view */
+ g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (logview->view), NULL);
- logview_update_statusbar (logview);
- logview_set_window_title (logview);
- gtk_tree_view_set_model (GTK_TREE_VIEW (logview->view), NULL);
- if (log->model == NULL) {
- g_timeout_add (200, (GSourceFunc) logview_show_busy_cursor, logview);
- log_create_model (log);
- logview_show_normal_cursor (logview);
- if (log->needs_refresh) {
- log_add_new_log_lines (log);
- log->needs_refresh = FALSE;
- if (gtk_tree_view_get_model (GTK_TREE_VIEW (logview->view)) != log->model)
- logview_set_log_model (logview, log);
- logview_scroll_and_focus_path (logview, log);
+ g_assert (LOGVIEW_IS_LOG (log));
+ g_object_get (G_OBJECT (log),
+ "monitoring", &monitoring,
+ logview_set_window_title (logview);
+ if (monitoring && log_has_been_modified (log)) {
+ log_notify (log, TH_EVENT_UPDATE);
+ logview_update_statusbar (logview);
+ if (gtk_tree_view_get_model (GTK_TREE_VIEW (logview->view)) != model)
+ logview_set_log_model (logview, log);
+ logview_scroll_and_focus_path (logview, log);
index 99e3d40..0136bfa 100644
#ifndef __LOG_REPAINT_H__
#define __LOG_REPAINT_H__
void logview_repaint (LogviewWindow *window);
void selection_changed_cb (GtkTreeSelection *selection, gpointer data);
void row_toggled_cb (GtkTreeView *treeview, GtkTreeIter *iter,
index 572df35..6e8049f 100644
+#define BOLD_LOG_TIME 5000
-static GObjectClass *parent_class;
-GType loglist_get_type (void);
@@ -38,6 +40,18 @@ enum {
+static void loglist_set_property (GObject *object,
+G_DEFINE_TYPE (LogList, loglist, GTK_TYPE_TREE_VIEW)
loglist_find_directory (LogList *list, gchar *dir)
@@ -48,14 +62,17 @@ loglist_find_directory (LogList *list, gchar *dir)
g_assert (LOG_IS_LIST (list));
- model = GTK_TREE_MODEL (list->priv->model);
+ model = GTK_TREE_MODEL (list->prv->model);
if (!gtk_tree_model_get_iter_first (model, &iter))
gtk_tree_model_get (model, &iter, LOG_NAME, &iterdir, -1);
- if (g_ascii_strncasecmp (iterdir, dir, -1) == 0) {
+ val = g_ascii_strncasecmp (iterdir, dir, -1);
path = gtk_tree_model_get_path (model, &iter);
@@ -76,9 +93,10 @@ loglist_find_log (LogList *list, Log *log)
g_assert (LOG_IS_LIST (list));
- g_assert (log != NULL);
+ g_assert (log != NULL);
- model = GTK_TREE_MODEL (list->priv->model);
+ model = GTK_TREE_MODEL (list->prv->model);
if (!gtk_tree_model_get_iter_first (model, &iter))
@@ -101,29 +119,34 @@ loglist_get_log_iter (LogList *list, Log *log, GtkTreeIter *logiter)
GtkTreePath *path = NULL;
path = loglist_find_log (list, log);
- model = GTK_TREE_MODEL (list->priv->model);
+ model = GTK_TREE_MODEL (list->prv->model);
gtk_tree_model_get_iter (model, logiter, path);
gtk_tree_path_free (path);
-loglist_unbold_log (LogList *list, Log *log)
+loglist_unbold (LogList *self)
+ LogviewWindow *logview = LOGVIEW_WINDOW(self->prv->window);
- g_return_if_fail (LOG_IS_LIST (list));
- g_return_if_fail (log != NULL);
+ model = GTK_TREE_MODEL (self->prv->model);
- model = GTK_TREE_MODEL (list->priv->model);
+ loglist_get_log_iter (self, logview_get_active_log (logview),
+ gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
+ LOG_WEIGHT_SET, FALSE, -1);
- loglist_get_log_iter (list, log, &iter);
- gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
- LOG_WEIGHT_SET, FALSE, -1);
+ self->prv->unbold_event = 0;
@@ -131,11 +154,13 @@ loglist_bold_log (LogList *list, Log *log)
+ LogviewWindow *logview = LOGVIEW_WINDOW(list->prv->window);
g_return_if_fail (LOG_IS_LIST (list));
g_return_if_fail (log != NULL);
- model = GTK_TREE_MODEL (list->priv->model);
+ model = GTK_TREE_MODEL (list->prv->model);
loglist_get_log_iter (list, log, &iter);
gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
@@ -143,8 +168,10 @@ loglist_bold_log (LogList *list, Log *log)
LOG_WEIGHT_SET, TRUE, -1);
/* if the log is currently shown, put up a timer to unbold it */
- if (logview_get_active_log (log->window) == log)
- g_timeout_add (5000, log_unbold, log);
+ if (logview_get_active_log (logview) == log)
+ g_timeout_add (BOLD_LOG_TIME,
+ (GSourceFunc) loglist_unbold,
@@ -169,33 +196,36 @@ void
loglist_remove_log (LogList *list, Log *log)
GtkTreeIter iter, parent;
- g_return_if_fail (LOG_IS_LIST (list));
- g_return_if_fail (log != NULL);
+ g_return_if_fail (LOG_IS_LIST (list));
+ g_return_if_fail (log != NULL);
- loglist_get_log_iter (list, log, &iter);
- gtk_tree_model_iter_parent (GTK_TREE_MODEL (list->priv->model), &parent, &iter);
+ g_object_get (G_OBJECT (log), "path", &name, NULL);
+ loglist_get_log_iter (list, log, &iter);
+ gtk_tree_model_iter_parent (GTK_TREE_MODEL (list->prv->model), &parent, &iter);
- if (gtk_tree_store_remove (list->priv->model, &iter)) {
- GtkTreeSelection *selection;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
- gtk_tree_selection_select_iter (selection, &iter);
- if (!gtk_tree_model_iter_has_child (GTK_TREE_MODEL (list->priv->model), &parent)) {
- if (gtk_tree_store_remove (list->priv->model, &parent)) {
- GtkTreeSelection *selection;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
- gtk_tree_selection_select_iter (selection, &parent);
+ if (gtk_tree_store_remove (list->prv->model, &iter)) {
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
+ gtk_tree_selection_select_iter (selection, &iter);
+ if (!gtk_tree_model_iter_has_child (GTK_TREE_MODEL (list->prv->model), &parent)) {
+ if (gtk_tree_store_remove (list->prv->model, &parent)) {
+ GtkTreeSelection *selection;
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
+ gtk_tree_selection_select_iter (selection, &parent);
loglist_add_directory (LogList *list, gchar *dirname, GtkTreeIter *iter)
- gtk_tree_store_append (list->priv->model, iter, NULL);
- gtk_tree_store_set (list->priv->model, iter,
+ gtk_tree_store_append (list->prv->model, iter, NULL);
+ gtk_tree_store_set (list->prv->model, iter,
LOG_NAME, dirname, LOG_POINTER, NULL, -1);
@@ -209,17 +239,16 @@ loglist_add_log (LogList *list, Log *log)
g_return_if_fail (LOG_IS_LIST (list));
g_return_if_fail (log != NULL);
- dirname = log_extract_dirname (log);
+ log_extract_filepath (log, &dirname, &filename);
path = loglist_find_directory (list, dirname);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->model), &iter, path);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (list->prv->model), &iter, path);
gtk_tree_path_free (path);
loglist_add_directory (list, dirname, &iter);
- filename = log_extract_filename (log);
- gtk_tree_store_append (list->priv->model, &child_iter, &iter);
- gtk_tree_store_set (list->priv->model, &child_iter,
+ gtk_tree_store_append (list->prv->model, &child_iter, &iter);
+ gtk_tree_store_set (list->prv->model, &child_iter,
LOG_NAME, filename, LOG_POINTER, log, -1);
if (GTK_WIDGET_VISIBLE (GTK_WIDGET (list)))
@@ -230,121 +259,129 @@ loglist_add_log (LogList *list, Log *log)
-loglist_selection_changed (GtkTreeSelection *selection, LogviewWindow *logview)
+loglist_selection_changed (GtkTreeSelection *selection, LogList *self)
- g_assert (LOGVIEW_IS_WINDOW (logview));
- g_assert (GTK_IS_TREE_SELECTION (selection));
- if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
- logview_select_log (logview, NULL);
- gtk_tree_model_get (model, &iter,
- LOG_WEIGHT_SET, &bold, -1);
- logview_select_log (logview, log);
- g_timeout_add (5000, log_unbold, log);
+ LogviewWindow *logview = LOGVIEW_WINDOW(self->prv->window);
-loglist_connect (LogList *list, LogviewWindow *logview)
- GtkTreeSelection *selection;
+ g_assert (GTK_IS_TREE_SELECTION (selection));
- g_return_if_fail (LOG_IS_LIST (list));
- g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ logview_select_log (logview, NULL);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
- g_signal_connect (G_OBJECT (selection), "changed",
- G_CALLBACK (loglist_selection_changed), logview);
+ gtk_tree_model_get (model, &iter,
+ LOG_WEIGHT_SET, &bold, -1);
+ /* there is a differnt selection before,
+ check if there is a pending loglist_unbold */
+ if (logview_get_active_log (logview) != log) {
+ if (self->prv->unbold_event > 0) {
+ ret = g_source_remove (self->prv->unbold_event);
+ self->prv->unbold_event = 0;
+ logview_select_log (logview, log);
+ self->prv->unbold_event =
+ g_timeout_add (BOLD_LOG_TIME,
+ (GSourceFunc) loglist_unbold,
loglist_init (LogList *list)
- GtkTreeViewColumn *column;
- GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+ GtkTreeSelection *selection;
- list->priv = g_new0 (LogListPriv, 1);
+ list->prv = g_new0 (LogListPrv, 1);
- model = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_BOOLEAN);
- gtk_tree_view_set_model (GTK_TREE_VIEW (list), GTK_TREE_MODEL (model));
- list->priv->model = model;
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE);
- g_object_unref (G_OBJECT (model));
+ model = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_BOOLEAN);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (list), GTK_TREE_MODEL (model));
+ list->prv->model = model;
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (list), FALSE);
+ g_object_unref (G_OBJECT (model));
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (loglist_selection_changed), list);
- cell = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new ();
- gtk_tree_view_column_pack_start (column, cell, TRUE);
- gtk_tree_view_column_set_attributes (column, cell,
- "weight-set", LOG_WEIGHT_SET,
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(list->priv->model), 0, GTK_SORT_ASCENDING);
- gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
- gtk_tree_view_set_search_column (GTK_TREE_VIEW (list), -1);
+ cell = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_pack_start (column, cell, TRUE);
+ gtk_tree_view_column_set_attributes (column, cell,
+ "weight-set", LOG_WEIGHT_SET,
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(list->prv->model), 0, GTK_SORT_ASCENDING);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (list), column);
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (list), -1);
loglist_finalize (GObject *object)
LogList *list = LOG_LIST (object);
- parent_class->finalize (object);
+ (*G_OBJECT_CLASS(loglist_parent_class)->finalize) (object);
loglist_class_init (LogListClass *klass)
GObjectClass *object_class = (GObjectClass *) klass;
- parent_class = g_type_class_peek_parent (klass);
object_class->finalize = loglist_finalize;
+ object_class->set_property = loglist_set_property;
+ pspec = g_param_spec_pointer ("window",
+ "LogviewWindow pointer",
+ "Set LogviewWindow pointer",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class,
+loglist_set_property (GObject *object,
- static GType object_type = 0;
- static const GTypeInfo object_info = {
- NULL, /* base_finalize */
- (GClassInitFunc) loglist_class_init,
- NULL,/* class_finalize */
- (GInstanceInitFunc) loglist_init
- object_type = g_type_register_static (GTK_TYPE_TREE_VIEW, "LogList", &object_info, 0);
+ LogList *self = LOG_LIST (object);
+ self->prv->window = g_value_get_pointer (value);
+ g_assert (LOGVIEW_IS_WINDOW(self->prv->window));
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec);
+loglist_new (gpointer window)
- widget = g_object_new (LOG_LIST_TYPE, NULL);
+ widget = g_object_new (LOG_LIST_TYPE, "window", window, NULL);
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+/* loglist is the left choice panel */
#define LOG_IS_LIST_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), LOG_LIST_TYPE))
#define LOG_LIST_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), LOG_LIST_TYPE, LogListClass))
-typedef struct LogListPriv LogListPriv;
+typedef struct LogListPrv LogListPrv;
- GtkTreeView parent_instance;
+ GtkTreeView parent_instance;
typedef struct LogListClass
@@ -40,12 +43,10 @@ typedef struct LogListClass
GType loglist_get_type (void);
-GtkWidget *loglist_new (void);
-void loglist_connect (LogList *list, LogviewWindow *window);
+GtkWidget *loglist_new (gpointer window);
void loglist_add_log (LogList *list, Log *log);
void loglist_remove_log (LogList *list, Log *log);
void loglist_select_log (LogList *list, Log *log);
void loglist_bold_log (LogList *list, Log *log);
-void loglist_unbold_log (LogList *list, Log *log);
#endif /* __LOG_LIST_H__ */
-/* ----------------------------------------------------------------------
+/* ----------------------------------------------------------------------
- Copyright (C) 1998 Cesar Miquel (miquel@df.uba.ar)
+ Copyright (C) 1998 Cesar Miquel (miquel@df.uba.ar)
- 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 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.
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- ---------------------------------------------------------------------- */
+ ---------------------------------------------------------------------- */
+#define LINES_INIT_ALLOC 128
+#define LINES_STEP_ALLOC_MUTI_FACTOR 2
+#define BOLD_ROWS_TIME 5000
+#define DATA_LOCK(log) g_mutex_lock(log->prv->data_mutex)
+#define DATA_UNLOCK(log) g_mutex_unlock(log->prv->data_mutex)
+#define LOG_IS_VALID(log) g_assert (log); \
+ g_assert (LOGVIEW_IS_LOG (log)); \
+ g_assert (log->prv->dispose_has_run == FALSE)
+static void log_dispose (Log *log);
+static void log_finalize (Log *log);
+static void log_thread_idle (Log *self);
+static guint log_thread_main_loop (Log *self);
+static ThreadEvent log_thread_pop_event (Log *self);
+static void log_create_model (Log *log);
+static void log_thread_fill_content (Log *log);
+static void log_fill_model_with_date (Log *log, GSList *days);
+static void log_fill_model_no_date (Log *log, guint start, guint end);
+static gboolean log_unbold_rows (Log *log);
+static GObjectClass *parent_class = NULL;
+ gboolean dispose_has_run;
+ volatile ThreadEvent th_event;
+ /* content information */
+ guint total_lines; /* current recorded lines in the file */
+ guint alloc_lines; /* capability of max lines in the file */
+ /* isolated calendar */
+ /* isolateed repaint */
+ GtkTreePath *first_bold_row;
+ GtkTreePath *last_bold_row;
+ GtkWidget *view; /* pointer to the only logview treeview */
+ GtkTreeModelFilter *filter;
+ GtkTreePath *visible_first;
+ GnomeVFSMonitorHandle *mon_handle;
+ LogviewPlugin* ext_data[LOG_PF_NUM];
+ GtkTreeIter *date_iter;
+ GtkTreeIter *line_iter;
+ gboolean update_status;
-char *error_main = N_("One file or more could not be opened");
-static LogStats *log_stats_new (char *filename, gboolean show_error);
+log_instance_init (GTypeInstance *instance, gpointer g_class_data)
+ Log* self = (Log*) instance;
+ self->prv = g_new0(LogPrivate, 1);
+ self->prv->dispose_has_run = FALSE;
+ self->prv->thread_lock = g_mutex_new ();
+ g_assert (self->prv->thread_lock);
+ self->prv->data_mutex = g_mutex_new ();
+ g_assert (self->prv->data_mutex);
+ self->prv->event_mutex = g_mutex_new ();
+ g_assert (self->prv->event_mutex);
+ self->prv->event_cond = g_cond_new ();
+ g_assert (self->prv->event_cond);
+ self->prv->th_event = TH_EVENT_EMPTY;
+ self->prv->alloc_lines = LINES_INIT_ALLOC;
+ self->prv->lines = g_malloc0 (LINES_INIT_ALLOC * sizeof (gchar *));
+ g_assert (self->prv->lines);
+ self->prv->older_logs = g_malloc0 (OLD_LOG_NUM * sizeof (Log *));
+ g_assert (self->prv->older_logs);
+ self->prv->lines[0] = NULL;
+ self->prv->line_iter = g_new0 (GtkTreeIter,1);
-file_exist (char *filename, gboolean show_error)
- GnomeVFSHandle *handle;
- char *secondary = NULL;
- result = gnome_vfs_open (&handle, filename, GNOME_VFS_OPEN_READ);
- if (result != GNOME_VFS_OK) {
- case GNOME_VFS_ERROR_ACCESS_DENIED:
- case GNOME_VFS_ERROR_NOT_PERMITTED:
- secondary = g_strdup_printf (_("%s is not user readable. "
- "Either run the program as root or ask the sysadmin to "
- "change the permissions on the file.\n"), filename);
- case GNOME_VFS_ERROR_TOO_BIG:
- secondary = g_strdup_printf (_("%s is too big."), filename);
- secondary = g_strdup_printf (_("%s could not be opened."), filename);
- error_dialog_show (NULL, error_main, secondary);
- gnome_vfs_close (handle);
+log_set_property (GObject *object,
+ Log *self = LOGVIEW_LOG (object);
+ g_free (self->prv->log_path);
+ self->prv->log_path = g_value_dup_string (value);
+ g_assert (self->prv->log_path);
+ g_assert (self->prv->log_path[0] != '\0');
+ LV_INFO ("
log.path: %s",self->prv->log_path);
+ self->prv->protocol = g_value_get_ulong (value);
+ case PROP_CURRENT_VERSION:
+ self->prv->current_version = g_value_get_int (value);
+ self->prv->versions = g_value_get_int (value);
+ case PROP_VISIBLE_FIRST:
+ if (self->prv->visible_first)
+ gtk_tree_path_free (self->prv->visible_first);
+ self->prv->visible_first = g_value_get_pointer (value);
+ case PROP_SELECTED_PATHS: {
+ paths = g_value_get_pointer (value);
+ if (self->prv->selected_paths != paths) {
+ g_list_foreach (self->prv->selected_paths, (GFunc) gtk_tree_path_free, NULL);
+ g_list_free (self->prv->selected_paths);
+ self->prv->selected_paths = paths;
+ /* can be set only once */
+ g_assert (self->prv->view == NULL);
+ self->prv->view = g_value_get_pointer (value);
+ g_assert (GTK_IS_TREE_VIEW(self->prv->view));
+ case PROP_MONITOR_HANDLE:
+ self->prv->mon_handle = g_value_get_pointer (value);
+ self->prv->monitored = g_value_get_boolean (value);
+ self->prv->filter = g_value_get_pointer (value);
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec);
-file_is_zipped (char *filename)
+log_get_property (GObject *object,
+ Log *self = LOGVIEW_LOG (object);
+ g_value_set_static_string (value, self->prv->log_path);
+ g_value_set_ulong (value, self->prv->protocol);
+ g_value_set_pointer (value, self->prv->model);
+ g_value_set_object (value, self->prv->parent_log);
+ g_value_set_pointer (value, self->prv->filter);
+ case PROP_DISPLAY_NAME:
+ g_value_set_string (value, self->prv->display_name);
+ g_value_set_uint (value, self->prv->total_lines);
+ g_value_set_boolean (value, logi_can_monitor(LOGVIEW_IFACE_IO(log_io(self))));
+ g_value_set_boolean (value, self->prv->monitored);
+ ret = self->prv->days != NULL;
+ g_value_set_boolean (value, ret);
+ case PROP_VISIBLE_FIRST:
+ g_value_set_pointer (value, self->prv->visible_first);
+ g_value_set_pointer (value, self->prv->first_bold_row);
+ g_value_set_pointer (value, self->prv->last_bold_row);
+ g_value_set_int (value, self->prv->versions);
+ g_value_set_pointer (value, self->prv->older_logs);
+ case PROP_CURRENT_VERSION:
+ g_value_set_int (value, self->prv->current_version);
+ g_value_set_pointer (value, self->prv->days);
+ g_value_set_pointer (value, self->prv->view);
+ case PROP_SELECTED_PATHS:
+ g_value_set_pointer (value, self->prv->selected_paths);
+ guint64 size = (guint64) logi_get_size (LOGVIEW_IFACE_IO(log_io(self)));
+ g_value_set_uint64 (value, size);
+ time_t time = logi_get_modified_time(LOGVIEW_IFACE_IO(log_io(self)));
+ g_value_set_long (value, time);
+ case PROP_MONITOR_HANDLE:
+ g_value_set_pointer (value, self->prv->mon_handle);
+ /* We don't have any other property... */
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec);
+log_class_init (gpointer g_class, gpointer g_class_data)
+ GObjectClass *object_class;
+ object_class = G_OBJECT_CLASS (g_class);
+ self = LOGVIEW_LOG_CLASS (g_class);
+ parent_class = g_type_class_peek_parent (g_class);
+ object_class->set_property = log_set_property;
+ object_class->get_property = log_get_property;
+ object_class->dispose = (void (*) (GObject*)) log_dispose;
+ object_class->finalize = (void (*) (GObject*)) log_finalize;
+ pspec = g_param_spec_string ("path",
+ "" /* default value */,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_string ("display-name",
+ "Set or get log display name",
+ NULL /* default value */,
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_ulong ("protocol",
+ "Set or get log protocol",
+ UNKNOWN_LOG /* default value */,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_int ("current-version",
+ "Currently displaying log",
+ "Set or get current version",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_int ("versions",
+ "Get log archive numbers",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("archives",
+ "Get elder logs pointer",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_uint64 ("size",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_uint ("total-lines",
+ "Log current read lines",
+ "Get current read lines",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_long ("mtime",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_boolean ("monitorable",
+ "Get or set monitor capable",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_boolean ("monitoring",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_boolean ("groupable",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("model",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("filter",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_object ("parent",
+ "The parent log of the current log",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("days",
+ "The day list of a log",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("view",
+ "Point to the only treeview of the main window",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("visible-first",
+ "Set or get first visible line",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("first-bold-row",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("last-bold-row",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("selected-paths",
+ "Log last selected lines",
+ "Set or get last selected lines",
+ g_object_class_install_property (object_class,
+ pspec = g_param_spec_pointer ("monitor-handle",
+ "GnomeVFSMonitorHandle used for monitoring this log",
+ "Set or get last selected line",
+ g_object_class_install_property (object_class,
- mime_type = gnome_vfs_get_mime_type (filename);
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ NULL, /* base_finalize */
+ log_class_init, /* class_init */
+ NULL, /* class_finalize */
+ log_instance_init /* instance_init */
+ type = g_type_register_static (G_TYPE_OBJECT,
-file_is_log (char *filename, gboolean show_error)
+log_append_garbage (Log *self, gchar *mass)
+ self->prv->need_free = g_slist_append (self->prv->need_free, mass);
- stats = log_stats_new (filename, show_error);
+log_append_lines (Log *self, gchar **lines, gint len)
+ if (self->prv->total_lines + len >= (self->prv->alloc_lines -1)) {
+ self->prv->alloc_lines *= LINES_STEP_ALLOC_MUTI_FACTOR;
+ self->prv->lines = g_realloc (self->prv->lines,
+ self->prv->alloc_lines * sizeof (gchar *));
+ g_assert (self->prv->lines);
+ for (i = 0; i < len; i++) {
+ self->prv->lines[self->prv->total_lines++] = lines[i];
+ self->prv->lines[self->prv->total_lines] = NULL;
+cleanup_binary_chars_in_log (gchar* buffer, gssize read_size)
+ for ( i = 0; i < read_size; i++ ) {
+ if ( buffer[i] == '\0' ) {
+log_find_day (Log *self, const GDate* date)
+ Day *day, *found_day = NULL;
+ for (days = self->prv->days; days!=NULL; days=g_slist_next(days)) {
+ if (g_date_compare (day->date, date) == 0) {
-days_compare (gconstpointer a, gconstpointer b)
+/* return start index of lines */
+log_build_list_index_from_mass (Log *self, const gchar* buffer)
- const Day *day1 = a, *day2 = b;
- return (g_date_compare (day1->date, day2->date));
+ gchar *fore_idx, *rear_idx;
+ guint ret = self->prv->total_lines;
+ gchar *cache[LINES_INIT_ALLOC];
+ log_append_garbage (self, (gchar *) buffer);
+ for (rear_idx = fore_idx = (gchar *) buffer; *fore_idx != '\0'; fore_idx++) {
+ /* do not skip empty lines */
+ while (*fore_idx == '\n') {
+ if (rear_idx != fore_idx) {
+ if (i == LINES_INIT_ALLOC) {
+ log_append_lines (self, cache, i);
+ log_thread_idle (self);
+ rear_idx = fore_idx + 1;
+ log_append_lines (self, cache, i);
+ * @self: a #Log instance.
+ * If read end of line or zero chars or meats error, return NULL.
+ * Returns: the pointer of buffer.
-string_get_date_string (gchar *line)
- gchar **split, *date_string;
- gchar *month=NULL, *day=NULL;
- if (line == NULL || line[0] == 0)
- split = g_strsplit (line, " ", 4);
- while ((day == NULL || month == NULL) && split[i]!=NULL && i<4) {
- if (g_str_equal (split[i], "")) {
+ off_t len, read_size, fp;
+ g_assert (LOGVIEW_IS_IFACE_IO(log_io (self)));
+ g_assert (LOGVIEW_IS_IFACE_VIEW(log_view (self)));
+ fp = logi_tell (log_io(self));
+ logi_seek (log_io(self), 0, SEEK_END);
+ len = logi_tell (log_io(self)) - fp;
+ buffer = g_malloc (len * sizeof(gchar) +1);
+ logi_seek (log_io(self), fp, SEEK_SET);
+ read_size = logi_read (log_io(self), buffer, len);
+ logi_update (log_io(self));
+ buffer [read_size] = '\0';
+ buffer = logi_to_utf8 (log_view (self), buffer, read_size);
+ cleanup_binary_chars_in_log (buffer, read_size);
+ /* read_size == 0 || -1, reading finished or error? */
- /* If the first field begins by a number, the date
- is given in yyyy-mm-dd format */
- if (!g_ascii_isalpha (month[0]))
+log_thread_main_loop (Log *self)
+ /* lock thread, prevent free instance before exist from thread */
+ g_mutex_lock (self->prv->thread_lock);
+ while ((te = log_thread_pop_event (self))) {
+ case TH_EVENT_INIT_READ:
+ self->prv->update_status = FALSE;
+ LV_INFO ("%s begin building log lines...",
+ log_thread_fill_content (self);
+ LV_INFO ("%s finished building log lines,"
+ self->prv->total_lines);
+ self->prv->update_status = TRUE;
+ log_thread_fill_content (self);
+ g_assert_not_reached ();
+ g_mutex_unlock (self->prv->thread_lock);
- date_string = g_strconcat (month, " ", day, NULL);
- date_string = g_strconcat (month, " ", day, NULL);
- Read all dates which have a log entry to create calendar.
- All dates are given with respect to the 1/1/1970
- and are then corrected to the correct year once we
-log_read_dates (gchar **buffer_lines, time_t current)
- int offsetyear = 0, current_year;
- GSList *days = NULL, *days_copy;
- int i, n, rangemin, rangemax;
- if (buffer_lines == NULL)
- n = g_strv_length (buffer_lines);
- tmptm = localtime (¤t);
- current_year = tmptm->tm_year + 1900;
- for (i=0; buffer_lines[i]==NULL; i++);
- /* Start building the list */
- /* Scanning each line to see if the date changed is too slow, so we proceed
- in a recursive fashion */
- date = string_get_date (buffer_lines[i]);
- if ((date==NULL)|| !g_date_valid (date))
- g_date_set_year (date, current_year);
- days = g_slist_append (days, day);
- date_string = string_get_date_string (buffer_lines[i]);
- while (day->last_line < 0) {
- if (g_str_has_prefix (buffer_lines[i], date_string)) {
- if (!g_str_has_prefix (buffer_lines[i+1], date_string)) {
- i = floor ( ((float) i + (float) rangemax)/2.);
- i = floor (((float) rangemin + (float) i)/2.);
- /* We need to find the first line now that has a date
- Logs can have some messages without dates ... */
- while (newdate == NULL && !done) {
- date_string = string_get_date_string (buffer_lines[i]);
- if (date_string == NULL)
- newdate = string_get_date (buffer_lines[i]);
- if (newdate == NULL && i==n-1)
- /* Append a day to the list */
- g_date_set_year (newdate, current_year + offsetyear);
- if (g_date_compare (newdate, date) < 1) {
- offsetyear++; /* newdate is next year */
- g_date_add_years (newdate, 1);
- days = g_slist_append (days, day);
- /* Correct years now. We assume that the last date on the log
- is the date last accessed */
- for (days_copy = days; days_copy != NULL; days_copy = g_slist_next (days_copy)) {
- day = days_copy -> data;
- g_date_subtract_years (day->date, offsetyear);
- /* Sort the days in chronological order */
- days = g_slist_sort (days, days_compare);
- Read the log and get some statistics from it.
- Returns NULL if the file is not a log.
-log_stats_new (char *filename, gboolean show_error)
- GnomeVFSFileInfo *info;
- GnomeVFSHandle *handle;
- /* Read first line and check that it is text */
- result = gnome_vfs_open (&handle, filename, GNOME_VFS_OPEN_READ);
- if (result != GNOME_VFS_OK) {
- info = gnome_vfs_file_info_new ();
- result = gnome_vfs_get_file_info_from_handle (handle, info, GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
- if (result != GNOME_VFS_OK || info->type != GNOME_VFS_FILE_TYPE_REGULAR) {
- gnome_vfs_file_info_unref (info);
- gnome_vfs_close (handle);
- result = gnome_vfs_read (handle, buff, sizeof(buff), &size);
- gnome_vfs_close (handle);
- if (result != GNOME_VFS_OK) {
- gnome_vfs_file_info_unref (info);
- found_space = g_strstr_len (buff, 1024, " ");
- if (found_space == NULL) {
- gnome_vfs_file_info_unref (info);
- stats = g_new (LogStats, 1);
- stats->file_time = info->mtime;
- stats->file_size = info->size;
- gnome_vfs_file_info_unref (info);
-log_open (char *filename, gboolean show_error)
- char *buffer, *zipped_name= NULL, *error_message;
- gboolean opened = TRUE;
- stats = log_stats_new (filename, show_error);
- if (file_is_zipped (filename)) {
- zipped_name = g_strdup_printf ("%s#gzip:", filename);
- stats = log_stats_new (filename, show_error);
- error_message = g_strdup_printf (_("%s is not a log file."), filename);
- error_message = g_strdup (_("Not enough memory."));
- log->name = g_strdup (filename);
- log->name = zipped_name;
- log->display_name = g_strdup (filename);
- result = gnome_vfs_read_entire_file (log->name, &size, &buffer);
- if (result != GNOME_VFS_OK) {
- error_message = g_strdup_printf (_("%s cannot be opened."), log->name);
- if (g_get_charset (NULL) == FALSE) {
- buffer2 = locale_to_utf8 (buffer);
- log->lines = g_strsplit (buffer, "\n", -1);
- log->total_lines = g_strv_length (log->lines);
- log->displayed_lines = log->total_lines;
- log->first_time = TRUE;
- log->bold_rows_list = NULL;
- /* A log without dates will return NULL */
- log->days = log_read_dates (log->lines, log->stats->file_time);
- /* Check for older versions of the log */
- log->current_version = 0;
- log->parent_log = NULL;
- older_name = g_strdup_printf ("%s.%d", log->name, i);
- log->older_logs[i] = log_open (older_name, FALSE);
- if (log->older_logs[i] != NULL) {
- log->older_logs[i]->parent_log = log;
- log->older_logs[i]->current_version = i;
- if (error_message && show_error) {
- error_dialog_show (NULL, error_main, error_message);
- g_free (error_message);
+ /* this function should only be ran once */
+ g_assert (self->prv->model == NULL);
+ log_create_model (self);
+ LV_INFO ("[[Log thread run]] %s", self->prv->log_path);
+ if (g_thread_create ((GThreadFunc) log_thread_main_loop, self, TRUE, NULL))
+ LV_INFO ("create thread failed", NULL);
-log_add_lines (Log *log, gchar *buffer)
- char *old_buffer, *new_buffer;
+ if (self->prv->dispose_has_run) {
+ /* If dispose did already run, return. */
+ self->prv->dispose_has_run = TRUE;
+ G_OBJECT_CLASS (parent_class)->dispose (G_OBJECT (self));
- g_assert (log != NULL);
- g_assert (buffer != NULL);
+log_finalize (Log *self)
+ LV_INFO ("[[ log remove ]] %s", self->prv->log_path);
+ log_notify (self, TH_EVENT_EXIT);
+ /* make sure thread existed */
+ g_mutex_lock (self->prv->thread_lock);
+ g_mutex_unlock (self->prv->thread_lock);
+ g_mutex_free (self->prv->thread_lock);
+ self->prv->thread_lock = NULL;
+ g_assert (LOGVIEW_IS_LOG (self));
+ g_cond_free (self->prv->event_cond);
+ self->prv->event_cond = NULL;
+ g_mutex_free (self->prv->event_mutex);
+ self->prv->event_mutex = NULL;
+ g_mutex_free (self->prv->data_mutex);
+ self->prv->data_mutex = NULL;
+ /* Close archive logs if there's some */
+ for (i = 0; i < self->prv->versions; i++)
+ if (self->prv->older_logs[i])
+ g_object_unref (self->prv->older_logs[i]);
+ g_free (self->prv->older_logs);
+ if (self->prv->mon_handle != NULL) {
+ gnome_vfs_monitor_cancel (self->prv->mon_handle);
+ self->prv->mon_handle = NULL;
+ if (self->prv->model) {
+ gtk_tree_store_clear (GTK_TREE_STORE (self->prv->model));
+ g_object_unref (self->prv->model);
+ if (self->prv->days != NULL) {
+ for (days = self->prv->days; days != NULL; days = g_slist_next (days)) {
+ g_date_free (day->date);
+ gtk_tree_path_free (day->path);
+ g_slist_free (self->prv->days);
+ self->prv->days = NULL;
+ if (self->prv->date_iter)
+ gtk_tree_iter_free (self->prv->date_iter);
+ if (self->prv->line_iter)
+ gtk_tree_iter_free (self->prv->line_iter);
+ if (self->prv->visible_first)
+ gtk_tree_path_free (self->prv->visible_first);
+ if (self->prv->first_bold_row)
+ gtk_tree_path_free (self->prv->first_bold_row);
+ if (self->prv->last_bold_row)
+ gtk_tree_path_free (self->prv->last_bold_row);
+ for (i = 0; i < LOG_PF_NUM; i++) {
+ if (self->prv->ext_data[i] != NULL) {
+ g_object_unref (G_OBJECT (self->prv->ext_data[i]));
+ for (idx = self->prv->need_free; idx; idx = g_slist_next(idx)) {
+ gchar *mass = (gchar *)idx->data;
+ g_free (self->prv->lines);
+ self->prv->lines = NULL;
+ if (self->prv->display_name)
+ g_free (self->prv->display_name);
+ if (self->prv->log_path)
+ g_free (self->prv->log_path);
+ parent_class->finalize (G_OBJECT (self));
- old_buffer = g_strjoinv ("\n", log->lines);
- new_buffer = g_strconcat (old_buffer, "\n", buffer, NULL);
- g_strfreev (log->lines);
- log->lines = g_strsplit (new_buffer, "\n", -1);
+log_extract_filepath (Log* self, gchar** dirname, gchar** filename)
+ g_assert (LOGVIEW_IS_IFACE_IO(log_io(self)));
- log->total_lines = g_strv_length (log->lines);
+ logi_extract_filepath(LOGVIEW_IFACE_IO(log_io(self)), dirname, filename);
-void log_stats_reload (Log *log)
+log_has_been_modified (Log *self)
- log->stats = log_stats_new (log->name, TRUE);
+ g_assert (LOGVIEW_IS_IFACE_IO(log_io(self)));
+ return logi_has_updated(LOGVIEW_IFACE_IO(log_io(self)));
-/* log_read_new_lines */
+log_test_func (Log *self, PluginFunc pf)
+ return self->prv->ext_data[pf] != NULL;
-log_read_new_lines (Log *log)
+log_set_func (Log *self, PluginFunc pf, LogviewPlugin *plugin)
- GnomeVFSFileSize newfilesize, read;
- g_return_val_if_fail (log!=NULL, FALSE);
- result = gnome_vfs_seek (log->mon_file_handle, GNOME_VFS_SEEK_END, 0L);
- result = gnome_vfs_tell (log->mon_file_handle, &newfilesize);
- size = log->mon_offset;
- buffer = g_malloc (newsize - size);
+ g_assert (plugin != NULL);
- result = gnome_vfs_seek (log->mon_file_handle, GNOME_VFS_SEEK_START, size);
- if (result != GNOME_VFS_OK)
+ self->prv->ext_data[pf] = plugin;
- result = gnome_vfs_read (log->mon_file_handle, buffer, newsize-size, &read);
- if (result != GNOME_VFS_OK)
+log_set_child (Log *self, gint index, Log *child)
+ g_assert (index >=0 && index < OLD_LOG_NUM);
+ g_assert (child && LOGVIEW_IS_LOG (child));
+ g_assert (self->prv->older_logs[index] == NULL);
+ self->prv->older_logs[index] = child;
+ child->prv->parent_log = self;
- buffer [newsize-size-1] = 0;
- log->mon_offset = newsize;
- log_add_lines (log, buffer);
- log_stats_reload (log);
+log_get_child (Log *self, gint index)
+ g_assert (index >=0 && index < OLD_LOG_NUM);
+ return self->prv->older_logs[index];
- log_unbold is called by a g_timeout
- set in loglist_bold_log
+log_notify (Log *self, ThreadEvent te)
+ g_mutex_lock (self->prv->event_mutex);
+ self->prv->th_event |= te;
+ g_cond_signal (self->prv->event_cond);
+ g_mutex_unlock (self->prv->event_mutex);
-log_unbold (gpointer data)
+log_thread_pop_event (Log *self)
- LogviewWindow *logview;
+ g_mutex_lock (self->prv->event_mutex);
+ while (self->prv->th_event == TH_EVENT_EMPTY)
+ g_cond_wait (self->prv->event_cond, self->prv->event_mutex);
+ if (self->prv->th_event & TH_EVENT_EXIT)
+ else if (self->prv->th_event & TH_EVENT_INIT_READ)
+ te = TH_EVENT_INIT_READ;
+ else if (self->prv->th_event & TH_EVENT_UPDATE)
+ g_assert_not_reached ();
+ self->prv->th_event ^= te;
+ g_mutex_unlock (self->prv->event_mutex);
- g_return_val_if_fail (log != NULL, FALSE);
+log_thread_idle (Log *self)
+ g_assert (LOGVIEW_IS_LOG (self));
+ g_mutex_lock (self->prv->event_mutex);
+ if (self->prv->th_event & TH_EVENT_EXIT) {
+ g_mutex_unlock (self->prv->event_mutex);
+ g_mutex_unlock (self->prv->thread_lock);
+ g_mutex_unlock (self->prv->event_mutex);
+log_create_model (Log *self)
+ self->prv->model = GTK_TREE_MODEL(
+ gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER,
+ G_TYPE_INT, G_TYPE_BOOLEAN)
- /* If the log to unbold is not displayed, still wait */
- if (logview_get_active_log (logview) != log)
+log_thread_fill_content (Log *self)
+ GtkTreePath *path = NULL;
+ if (self->prv->update_status) {
+ if (log_has_been_modified (self) == FALSE)
+ if ((buffer = log_read (self)) == NULL)
+ g_assert (buffer && buffer[0] != '\0');
+ start = log_build_list_index_from_mass (self, buffer);
+ g_assert (start <= self->prv->total_lines);
+ days = logi_group_lines (log_view (self),
+ (const gchar **) (self->prv->lines + start));
+ end = self->prv->total_lines;
+ log_fill_model_with_date (self, days);
+ path = gtk_tree_model_get_path (self->prv->model,
+ self->prv->days = g_slist_concat (self->prv->days, days);
+ log_write_lines_range (self, self->prv->lines, start, end);
+ path = gtk_tree_model_get_path (self->prv->model,
+ if (self->prv->update_status) {
+ /* Remember the last bold lines in the model to
+ if (self->prv->last_bold_row)
+ gtk_tree_path_free (self->prv->last_bold_row);
+ self->prv->last_bold_row =
+ gtk_tree_model_get_path (self->prv->model,
+ g_timeout_add (BOLD_ROWS_TIME,
+ (GSourceFunc) log_unbold_rows,
+ /* initial, remember the first visible line
+ self->prv->selected_paths =
+ g_list_append (self->prv->selected_paths,
+ gtk_tree_path_copy (path));
+ if (self->prv->visible_first)
+ gtk_tree_path_free (self->prv->visible_first);
+ self->prv->visible_first = gtk_tree_path_copy (path);
+ gtk_tree_path_free (path);
+log_fill_model_with_date (Log *self, GSList *days)
+ for (iter = days; iter; iter = g_slist_next (iter)) {
+ day = (Day *)iter->data;
+ log_write_day (self, day);
+ day->path = gtk_tree_model_get_path (self->prv->model, self->prv->date_iter);
+ log_write_lines_range (self, self->prv->lines,
- list = logview_get_loglist (logview);
- loglist_unbold_log (list, log);
+log_write_day (Log *self, Day *day)
+ gchar *old_date_str = NULL;
+ gchar *new_date_str = NULL;
+ g_assert (self->prv->model);
+ g_assert (g_date_valid (date));
+ new_date_str = date_to_string (date); /* convert to utf8 */
+ g_assert (new_date_str);
+ if (self->prv->date_iter == NULL) {
+ self->prv->date_iter = g_new0 (GtkTreeIter,1);
+ goto log_write_date_first_run;
+ gtk_tree_model_get (self->prv->model,
+ MESSAGE, &old_date_str,
+ old_date_len = (gint) g_utf8_strlen (old_date_str, -1);
+ new_date_len = (gint) g_utf8_strlen (new_date_str, -1);
+ if ((old_date_len != new_date_len)
+ || (old_date_len >= new_date_len ?
+ g_ascii_strncasecmp (old_date_str, new_date_str, new_date_len)
+ : g_ascii_strncasecmp (old_date_str, new_date_str, old_date_len)) != 0) {
+log_write_date_first_run:
+ gtk_tree_store_append (GTK_TREE_STORE (self->prv->model),
+ gtk_tree_store_set (GTK_TREE_STORE (self->prv->model),
+ log_thread_idle (self);
- g_return_if_fail (log);
- /* Close archive logs if there's some */
- for (i = 0; i < log->versions; i++)
- log_close (log->older_logs[i]);
- /* Close file - this should not be needed */
- if (log->mon_file_handle != NULL) {
- gnome_vfs_close (log->mon_file_handle);
- log->mon_file_handle = NULL;
- g_object_unref (log->model);
- g_strfreev (log->lines);
- if (log->days != NULL) {
- for (days = log->days; days != NULL; days = g_slist_next (days)) {
- g_date_free (day->date);
- gtk_tree_path_free (day->path);
- g_slist_free (log->days);
- if (log->visible_first)
- gtk_tree_path_free (log->visible_first);
+log_write_date (Log *self, GDate *date)
+ gchar *old_date_str = NULL;
+ gchar *new_date_str = NULL;
+ g_assert (self->prv->model);
+ g_assert (g_date_valid (date));
+ new_date_str = date_to_string (date); /* convert to utf8 */
+ g_assert (new_date_str);
+ if (self->prv->date_iter == NULL) {
+ self->prv->date_iter = g_new0 (GtkTreeIter,1);
+ goto log_write_date_first_run;
+ gtk_tree_model_get (self->prv->model,
+ MESSAGE, &old_date_str,
+ old_date_len = (gint) g_utf8_strlen (old_date_str, -1);
+ new_date_len = (gint) g_utf8_strlen (new_date_str, -1);
+ if ((old_date_len != new_date_len)
+ || (old_date_len >= new_date_len ?
+ g_ascii_strncasecmp (old_date_str, new_date_str, new_date_len)
+ : g_ascii_strncasecmp (old_date_str, new_date_str, old_date_len)) != 0) {
+log_write_date_first_run:
+ gtk_tree_store_append (GTK_TREE_STORE (self->prv->model),
+ gtk_tree_store_set (GTK_TREE_STORE (self->prv->model),
+ log_thread_idle (self);
-log_extract_filename (Log *log)
+log_write_lines_range (Log *self, gchar **lines, gint start, gint end)
+ g_assert (end > start);
+ n = (end-start)/WRITE_LINES;
+ for (i = 0; i < n; i ++) {
+ lines + start + i*WRITE_LINES,
+ log_write_lines (self, lines + start + n*WRITE_LINES,
+ (end-start)%WRITE_LINES);
- uri = gnome_vfs_uri_new (log->name);
- filename = gnome_vfs_uri_extract_short_name (uri);
- gnome_vfs_uri_unref (uri);
+log_write_lines (Log *self, gchar **lines, gint num)
+ for (i = 0; i < num; i ++)
+ log_write_line (self, lines[i]);
+ log_thread_idle (self);
+log_write_line (Log *self, gchar *line)
+ g_assert (self->prv->model);
+ g_assert (self->prv->line_iter);
+ gtk_tree_store_append (GTK_TREE_STORE (self->prv->model),
+ if (!self->prv->update_status) {
+ gtk_tree_store_set (GTK_TREE_STORE (self->prv->model),
+ gtk_tree_store_set (GTK_TREE_STORE (self->prv->model),
+ LOG_LINE_WEIGHT, PANGO_WEIGHT_BOLD,
+ LOG_LINE_WEIGHT_SET, TRUE,
+ /* Remember the first bold lines in the model to unset them later */
+ if (self->prv->first_bold_row == NULL)
+ self->prv->first_bold_row = gtk_tree_model_get_path (self->prv->model, self->prv->line_iter);
+ log_thread_idle (self);
-log_extract_dirname (Log *log)
+log_unbold_rows (Log *self)
- uri = gnome_vfs_uri_new (log->name);
- dirname = gnome_vfs_uri_extract_dirname (uri);
- gnome_vfs_uri_unref (uri);
+ g_assert (self->prv->view);
+ if (self->prv->model !=
+ gtk_tree_view_get_model (GTK_TREE_VIEW(self->prv->view))) {
+ if (self->prv->first_bold_row != NULL &&
+ self->prv->last_bold_row != NULL) {
+ for (path = self->prv->first_bold_row;
+ gtk_tree_path_compare (path, self->prv->last_bold_row)<=0;
+ gtk_tree_path_next (path)) {
+ gtk_tree_model_get_iter (self->prv->model, &iter, path);
+ gtk_tree_store_set (GTK_TREE_STORE (self->prv->model), &iter,
+ LOG_LINE_WEIGHT, PANGO_WEIGHT_NORMAL,
+ LOG_LINE_WEIGHT_SET, TRUE,
+ gtk_tree_path_free (self->prv->first_bold_row);
+ gtk_tree_path_free (self->prv->last_bold_row);
+ self->prv->first_bold_row = NULL;
+ self->prv->last_bold_row = NULL;
+void log_lock (Log *self)
+void log_unlock (Log *self)
index 891869a..20106f5 100644
- long first_line, last_line; /* First and last line for this day in the log */
- GnomeVFSFileSize file_size;
+/* call by log_repaint */
+Day * log_find_day (Log *self, const GDate* date);
-typedef struct TreePathRange
+/* log utilities base on the plugin interfaces */
+void log_extract_filepath (Log* self, gchar** dirname, gchar** filename);
+gboolean log_has_been_modified (Log* self);
+gboolean log_run (Log* self);
-typedef struct _log Log;
- gint selected_line_first;
- gint selected_line_last;
- gint total_lines; /* no of lines in the file */
- gint displayed_lines; /* no of lines displayed now */
- GnomeVFSFileSize mon_offset;
- GnomeVFSMonitorHandle *mon_handle;
- GnomeVFSHandle *mon_file_handle;
- gboolean needs_refresh;
- GtkTreeModelFilter *filter;
- TreePathRange selected_range;
- GtkTreePath *visible_first;
- /* older_logs[0] should not be used */
-gboolean file_is_log (char *filename, gboolean show_error);
-Log *log_open (char *filename, gboolean show_error);
-gboolean log_read_new_lines (Log *log);
-gboolean log_unbold (gpointer data);
-void log_close (Log * log);
-gchar *log_extract_filename (Log *log);
-gchar *log_extract_dirname (Log *log);
#endif /* __LOGRTNS_H__ */
+static LogviewLevelFlags debug = LOGVIEW_INFO;
+lv_debug (LogviewLevelFlags level,
+ g_return_if_fail (file && function && line >= 0);
+ g_fprintf (logf, "\"%s\" %s:%d\n", file, function, line);
+lv_debug_message (LogviewLevelFlags level,
+ const gchar *format, ...)
+ g_return_if_fail (file && function && line >= 0);
+ if (debug & LOGVIEW_VERBOSE) {
+ g_fprintf (logf, "\"%s\" %s:%d ", file, function, line);
+ g_vfprintf (logf, format, ap);
+ g_fprintf (logf, "\n");
+ gchar *f = g_build_path (G_DIR_SEPARATOR_S, (gchar*)g_get_home_dir (),
+ LOGVIEW_USER_PATH_SUFFIX, NULL);
+ logf = g_fopen (f, "wb");
+ if (g_getenv ("LOGVIEW_DEBUG") != NULL) {
+ debug |= LOGVIEW_ERR | LOGVIEW_VERBOSE;
+ if (g_getenv ("LOGVIEW_VERBOSE") != NULL) {
+ debug |= LOGVIEW_VERBOSE;
+logview_debug_destroy ()
+#ifndef __LOGVIEW_DEBUG_H__
+#define __LOGVIEW_DEBUG_H__
+ * @LOGVIEW_INFO: Normal information will be displayed in this level.
+ * @LOGVIEW_VERBOSE: Like %LOGVIEW_INFO, more information like file name,
+ * function name and line number will be displayed in this level.
+ * @LOGVIEW_ERR: Cover all above levels, displays verbose information
+ * Used to specify the level of the log of gnome-system-log.
+ LOGVIEW_VERBOSE = 1 << 1,
+void logview_debug_init ();
+void logview_debug_destroy ();
+void lv_debug (LogviewLevelFlags level,
+ const gchar *function);
+void lv_debug_message (LogviewLevelFlags level,
+ const gchar *format, ...);
+ * Dump out information in the %LOGVIEW_ERR level.
+ lv_debug (LOGVIEW_ERR, __FILE__, __LINE__, FUNC)
+ * @FORMAT: a formatted string.
+ * Dump out information in the %LOGVIEW_VERBOSE and %LOGVIEW_INFO level.
+#define LV_INFO(FORMAT, ...) \
+ lv_debug_message (LOGVIEW_INFO, __FILE__, __LINE__, FUNC, "[II] " FORMAT, __VA_ARGS__)
+ * @FORMAT: a formatted string.
+ * Like LV_INFO(), dump out warnning information.
+#define LV_INFO_WW(FORMAT, ...) \
+ lv_debug_message (LOGVIEW_INFO, __FILE__, __LINE__, FUNC, "[WW] " FORMAT, __VA_ARGS__)
+ * @FORMAT: a formatted string.
+ * Like LV_INFO(), dump out error information.
+#define LV_INFO_EE(FORMAT, ...) \
+ lv_debug_message (LOGVIEW_INFO, __FILE__, __LINE__, FUNC, "[EE] " FORMAT, __VA_ARGS__)
+ * @FORMAT: a formatted string.
+ * Dump out information in the %LOGVIEW_ERR level.
+#define LV_ERR(FORMAT, ...) \
+ lv_debug_message (LOGVIEW_ERR, __FILE__, __LINE__, FUNC, FORMAT, __VA_ARGS__)
index c70ff16..8c6477b 100644
struct LogviewFindBarPriv
@@ -55,9 +56,15 @@ logview_findbar_clear (GtkWidget *widget, gpointer data)
LogviewFindBar *findbar = LOGVIEW_FINDBAR (data);
LogviewWindow *logview = LOGVIEW_WINDOW (findbar->priv->logview);
+ GtkTreeModelFilter *filter;
Log *log = logview->curlog;
- if (log==NULL || log->filter == NULL)
+ g_object_get (G_OBJECT (log),
gtk_entry_set_text (GTK_ENTRY (findbar->priv->entry), "");
@@ -70,21 +77,28 @@ logview_findbar_entry_timeout (gpointer data)
LogviewFindBar *findbar = LOGVIEW_FINDBAR (data);
LogviewWindow *logview = LOGVIEW_WINDOW (findbar->priv->logview);
Log *log = logview->curlog;
+ GtkTreeModelFilter *filter;
+ g_object_get (G_OBJECT (log),
cursor = gdk_cursor_new (GDK_WATCH);
gdk_window_set_cursor (GTK_WIDGET (logview)->window, cursor);
gdk_cursor_unref (cursor);
gdk_display_flush (gtk_widget_get_display (GTK_WIDGET (logview)));
- if (log->filter == NULL) {
- log->filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (log->model, NULL));
- gtk_tree_model_filter_set_visible_func (log->filter, iter_is_visible, findbar, NULL);
- gtk_tree_view_set_model (GTK_TREE_VIEW (logview->view), GTK_TREE_MODEL (log->filter));
+ filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
+ gtk_tree_model_filter_set_visible_func (filter, iter_is_visible, findbar, NULL);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (logview->view), GTK_TREE_MODEL (filter));
+ g_object_set (G_OBJECT (log), "filter", filter, NULL);
- gtk_tree_model_filter_refilter (log->filter);
+ gtk_tree_model_filter_refilter (filter);
gtk_tree_view_expand_all (GTK_TREE_VIEW (logview->view));
@@ -103,13 +117,19 @@ logview_findbar_entry_changed_cb (GtkEditable *editable,
LogviewFindBar *findbar = LOGVIEW_FINDBAR (data);
LogviewWindow *logview = LOGVIEW_WINDOW (findbar->priv->logview);
Log *log = logview->curlog;
+ GtkTreeModelFilter *filter;
search_string = g_strdup (gtk_entry_get_text (GTK_ENTRY (findbar->priv->entry)));
+ g_object_get (G_OBJECT (log),
- if (strlen (search_string) == 0 && log->filter != NULL) {
- g_object_unref (log->filter);
+ if (strlen (search_string) == 0 && filter != NULL) {
+ g_object_unref (filter);
+ g_object_set (G_OBJECT (log),
logview_repaint (logview);
@@ -143,7 +163,7 @@ logview_findbar_connect (LogviewFindBar *findbar, LogviewWindow *logview)
logview_findbar_init (LogviewFindBar *findbar)
- GtkWidget *label, *button;
findbar->priv = g_new0 (LogviewFindBarPriv, 1);
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+logview_iface_base_init (gpointer gclass)
+ static gboolean initialized = FALSE;
+logview_iface_class_init (gpointer g_class, gpointer g_class_data)
+ LogviewIFaceCollector *self = (LogviewIFaceCollector *)g_class;
+ self->config_log = NULL;
+ self->config_log_from_path = NULL;
+ self->config_log = NULL;
+logview_iface_collector_get_type (void)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (LogviewIFaceCollector),
+ logview_iface_base_init, /* base_init */
+ NULL, /* base_finalize */
+ logview_iface_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL /* instance_init */
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ g_intern_static_string ("LogviewIFaceCollectorType"),
+ g_type_interface_add_prerequisite (type, LOGVIEW_TYPE_IFACE);
+ * @self: a #LogviewICollector instance.
+ * Gnome System Log get logs by invoking this routine.
+ * Returns: a single list, each element is a string represents a log name.
+logi_get_logs (LogviewICollector *self)
+ return LOGVIEW_GET_COLLECTOR_INTERFACE (self)->get_logs(self);
+ * logi_config_log_from_path:
+ * @self: a #LogviewICollector instance.
+ * @log_name: log name which is obtained from logi_get_logs().
+ * Gnome System Log tries to config a log instance by passing the log name to this routine.
+ * Returns: On successful completion, returns a #Log instance; else returns NULL.
+logi_config_log_from_path (LogviewICollector *self, const gchar *log_name)
+ return LOGVIEW_GET_COLLECTOR_INTERFACE (self)->config_log_from_path (self, log_name);
+ * @self: a #LogviewICollector instance.
+ * @log: a #Log instance.
+ * Gnome System Log tries to config a log instance by passing the @log to this routine.
+ * Returns: On successful completion, returns TRUE; else returns FALSE.
+logi_config_log (LogviewICollector *self, Log *log)
+ return LOGVIEW_GET_COLLECTOR_INTERFACE (self)->config_log (self, log);
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#ifndef __LOGVIEW_IFACE_COLLECTOR_H__
+#define __LOGVIEW_IFACE_COLLECTOR_H__
+#define LOGVIEW_TYPE_IFACE_COLLECTOR \
+ (logview_iface_collector_get_type ())
+#define LOGVIEW_IFACE_COLLECTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), LOGVIEW_TYPE_IFACE_COLLECTOR, \
+#define LOGVIEW_IS_IFACE_COLLECTOR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), LOGVIEW_TYPE_IFACE_COLLECTOR))
+#define LOGVIEW_GET_COLLECTOR_INTERFACE(obj) \
+ (G_TYPE_INSTANCE_GET_INTERFACE((obj), LOGVIEW_TYPE_IFACE_COLLECTOR, \
+ LogviewIFaceCollector))
+typedef struct _LogviewICollector LogviewICollector; /* dummy object */
+typedef struct _LogviewIFaceCollector LogviewIFaceCollector;
+struct _LogviewIFaceCollector {
+ /* Generate a new list of log names, need be freed */
+ GSList* (*get_logs) (LogviewICollector *self);
+ /* Create a log instance from path name, returns NULL if fails. */
+ Log* (*config_log_from_path) (LogviewICollector *self,
+ const gchar *log_name);
+ /* configure a log instance */
+ gboolean (*config_log) (LogviewICollector *self, Log *log);
+extern GType logview_iface_collector_get_type (void) G_GNUC_CONST;
+/* for logview application internal usage */
+extern GSList* logi_get_logs (LogviewICollector *self);
+extern Log* logi_config_log_from_path (LogviewICollector *self,
+ const gchar *log_name);
+extern gboolean logi_config_log (LogviewICollector *self, Log *log);
+#endif /* __LOGVIEW_IFACE_COLLECTOR_H__ */
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+logview_iface_base_init (gpointer gclass)
+ static gboolean initialized = FALSE;
+logview_iface_class_init (gpointer g_class, gpointer g_class_data)
+ LogviewIFaceIO *self = (LogviewIFaceIO *)g_class;
+ self->can_monitor = NULL;
+ self->extract_filepath = NULL;
+ self->has_updated = NULL;
+ self->get_modified_time = NULL;
+logview_iface_io_get_type (void)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (LogviewIFaceIO),
+ logview_iface_base_init, /* base_init */
+ NULL, /* base_finalize */
+ logview_iface_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL /* instance_init */
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ g_intern_static_string ("LogviewIFaceIOType"),
+ g_type_interface_add_prerequisite (type, LOGVIEW_TYPE_IFACE);
+ * @self: a #LogviewIIO instance.
+ * Check whether @self can be monitored.
+ * Returns: Return TRUE, if it can.
+logi_can_monitor (LogviewIIO *self)
+ LogviewIFaceIO *iface = LOGVIEW_GET_IO_INTERFACE (self);
+ return iface->can_monitor(self);
+ * @self: a #LogviewIIO instance.
+ * Check if @self has changed since last reading happens.
+ * Returns: Return TRUE, if it can.
+logi_has_updated (LogviewIIO *self)
+ return LOGVIEW_GET_IO_INTERFACE (self)->has_updated(self);
+ * @self: a #LogviewIIO instance.
+ * Update @self to a new state, do not report True
+ * if call logi_has_updated() any more except a new change is made to @self.
+logi_update (LogviewIIO *self)
+ LOGVIEW_GET_IO_INTERFACE (self)->update(self);
+ * @self: a #LogviewIIO instance.
+ * @size: the length of the @buffer.
+ * read, seek, tell are similiar to Standard C read, fseek, ftell.
+ * whence := SEEK_SET | SEEK_CUR | SEEK_END
+ * returns -1 if met error.
+ * but no errno currently.
+ * Returns: Upon successful completion, logi_read() returns the size of
+ * successfully read. If @size is equal to 0, logi_read() returns 0 and
+ * the contents of the @buffer remain unchanged. Otherwise, if a read error
+logi_read (LogviewIIO *self, void* buffer, size_t size)
+ return LOGVIEW_GET_IO_INTERFACE (self)->read(self, buffer, size);
+ * @self: a #LogviewIIO instance.
+ * @whence: like fseek, accept SEEK_SET | SEEK_CUR | SEEK_END.
+ * read, seek, tell are similiar to Standard C read, fseek, ftell.
+ * but no errno currently.
+ * Returns: -1 if met error.
+logi_seek (LogviewIIO *self, off_t offset, int whence)
+ return LOGVIEW_GET_IO_INTERFACE (self)->seek(self, offset, whence);
+ * @self: a #LogviewIIO instance.
+ * read, seek, tell are similiar to Standard C read, fseek, ftell.
+ * but no errno currently.
+ * Returns: On successful completion, returns the current offset
+ * opposite to the log head; returns -1 if met error.
+logi_tell (LogviewIIO *self)
+ return LOGVIEW_GET_IO_INTERFACE (self)->tell(self);
+ * @self: a #LogviewIIO instance.
+ * Depends on logi_update(), report the size in one state of @self.
+ * Returns: On successful completion, returns the current size of @self,
+logi_get_size (LogviewIIO* self)
+ return LOGVIEW_GET_IO_INTERFACE (self)->get_size(self);
+ * logi_get_modified_time:
+ * @self: a #LogviewIIO instance.
+ * Depends on logi_update(), report the modified time in one state of @self.
+ * Returns: On successful completion, returns the current size of @self,
+logi_get_modified_time (LogviewIIO* self)
+ return LOGVIEW_GET_IO_INTERFACE (self)->get_modified_time(self);
+ * logi_extract_filepath:
+ * @self: a #LogviewIIO instance.
+ * @dirname: returns a pointer points to the new alloc buffer
+ * contains the path name of @self.
+ * If passes NULL, the plugin should ignore this argument.
+ * @filename: returns a pointer points to the new alloc buffer
+ * contains the file name of @self.
+ * If passes NULL, the plugin should ignore this argument.
+ * Extract the path name and the file name from $self, which will be displayed on
+ * Gnome System Log left tree pane.
+logi_extract_filepath (LogviewIIO *self, gchar** dirname, gchar** filename)
+ LOGVIEW_GET_IO_INTERFACE (self)->extract_filepath(self, dirname, filename);
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#ifndef __LOGVIEW_IFACE_IO_H__
+#define __LOGVIEW_IFACE_IO_H__
+#define LOGVIEW_TYPE_IFACE_IO \
+ (logview_iface_io_get_type ())
+#define LOGVIEW_IFACE_IO(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOGVIEW_TYPE_IFACE_IO, \
+#define LOGVIEW_IS_IFACE_IO(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOGVIEW_TYPE_IFACE_IO))
+#define LOGVIEW_GET_IO_INTERFACE(obj) \
+ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), LOGVIEW_TYPE_IFACE_IO, \
+typedef struct _LogviewIIO LogviewIIO; /* dummy object */
+typedef struct _LogviewIFaceIO LogviewIFaceIO;
+struct _LogviewIFaceIO {
+ gboolean (*can_monitor) (LogviewIIO *self);
+ void (*extract_filepath) (LogviewIIO *self,
+ gchar** dirname, gchar** filename);
+ gboolean (*has_updated) (LogviewIIO *self);
+ void (*update) (LogviewIIO *self);
+ size_t (*read) (LogviewIIO *self, void* buffer, size_t size);
+ off_t (*seek) (LogviewIIO *self, off_t offset, int whence);
+ off_t (*tell) (LogviewIIO *self);
+ off_t (*get_size) (LogviewIIO* self);
+ time_t (*get_modified_time) (LogviewIIO* self);
+extern GType logview_iface_io_get_type (void) G_GNUC_CONST;
+/* for logview application internal usage */
+extern gboolean logi_can_monitor (LogviewIIO *self);
+extern void logi_extract_filepath (LogviewIIO *self,
+ gchar** dirname, gchar** filename);
+extern gboolean logi_has_updated (LogviewIIO *self);
+extern void logi_update (LogviewIIO *self);
+extern size_t logi_read (LogviewIIO *self, void* buffer, size_t size);
+extern off_t logi_seek (LogviewIIO *self, off_t offset, int whence);
+extern off_t logi_tell (LogviewIIO *self);
+extern off_t logi_get_size (LogviewIIO* self);
+extern time_t logi_get_modified_time (LogviewIIO* self);
+#endif /* __LOGVIEW_IFACE_H__ */
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+logview_iface_base_init (gpointer gclass)
+ static gboolean initialized = FALSE;
+logview_iface_class_init (gpointer g_class, gpointer g_class_data)
+ LogviewIFaceView *self = (LogviewIFaceView *)g_class;
+ self->group_lines = NULL;
+logview_iface_view_get_type (void)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (LogviewIFaceView),
+ logview_iface_base_init, /* base_init */
+ NULL, /* base_finalize */
+ logview_iface_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL /* instance_init */
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ g_intern_static_string ("LogviewIFaceViewType"),
+ g_type_interface_add_prerequisite (type, LOGVIEW_TYPE_IFACE);
+ * @self: a #LogviewIView instance.
+ * @lines: an array of strings, terminates in NULL.
+ * Passes an array of strings to logi_group_lines(),
+ * the plugin should try to group these strings by date.
+ * Returns: a single list with each element is a #Day object.
+logi_group_lines (LogviewIView *self, const gchar **lines)
+ return LOGVIEW_GET_VIEW_INTERFACE (self)->group_lines(self, lines);
+ * @self: a #LogviewIView instance.
+ * @size: the length of @str.
+ * Gnome System Log will call this routine before displays the string on the screen.
+ * Returns: a converted string, which will be freed by Gnome System Log.
+logi_to_utf8 (LogviewIView *self, gchar *str, gssize size)
+ LogviewIFaceView *iface = LOGVIEW_GET_VIEW_INTERFACE (self);
+ return iface->to_utf8 (self, str, size);
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#ifndef __LOGVIEW_IFACE_VIEW_H__
+#define __LOGVIEW_IFACE_VIEW_H__
+#define LOGVIEW_TYPE_IFACE_VIEW \
+ (logview_iface_view_get_type ())
+#define LOGVIEW_IFACE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), LOGVIEW_TYPE_IFACE_VIEW, \
+#define LOGVIEW_IS_IFACE_VIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), LOGVIEW_TYPE_IFACE_VIEW))
+#define LOGVIEW_GET_VIEW_INTERFACE(obj) \
+ (G_TYPE_INSTANCE_GET_INTERFACE((obj), LOGVIEW_TYPE_IFACE_VIEW, \
+typedef struct _LogviewIView LogviewIView;
+typedef struct _LogviewIFaceView LogviewIFaceView;
+struct _LogviewIFaceView {
+ Create a list, each element is a group entry,
+ each group entry has a log list, do not free mass.
+ returns NULL if failed.
+ GSList* (*group_lines) (LogviewIView *self, const gchar **lines);
+ If possible, convert a string to utf8, free the original
+ string, return the new one.
+ gchar* (*to_utf8) (LogviewIView *self, gchar *str, gssize size);
+extern GType logview_iface_view_get_type (void) G_GNUC_CONST;
+/* for logview application internal usage */
+extern GSList* logi_group_lines (LogviewIView *self, const gchar **lines);
+extern gchar* logi_to_utf8 (LogviewIView *self, gchar *str, gssize size);
+#endif /* __LOGVIEW_IFACE_VIEW_H__ */
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+logview_iface_base_init (gpointer gclass)
+ static gboolean initialized = FALSE;
+logview_iface_class_init (gpointer g_class, gpointer g_class_data)
+ LogviewInterface *self = (LogviewInterface *)g_class;
+ self->can_handle = NULL;
+logview_iface_get_type (void)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (LogviewInterface),
+ logview_iface_base_init, /* base_init */
+ NULL, /* base_finalize */
+ logview_iface_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL /* instance_init */
+ type = g_type_register_static (G_TYPE_INTERFACE,
+ g_intern_static_string ("LogviewInterfaceType"),
+ * @self: a #LogviewIFace instance.
+ * @log: a #Log instance.
+ * Check whether the @log can be handled.
+ * Returns: If this interface is not overwritten,
+ * it default returns TRUE means the @log can be recognized.
+logi_can_handle (LogviewIFace *self, struct _Log* log)
+ LogviewInterface *iface = LOGVIEW_GET_INTERFACE (self);
+ return (iface)->can_handle(self, log);
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#ifndef __LOGVIEW_IFACE_H__
+#define __LOGVIEW_IFACE_H__
+#define LOGVIEW_TYPE_IFACE \
+ (logview_iface_get_type ())
+#define LOGVIEW_IFACE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), LOGVIEW_TYPE_IFACE, \
+#define LOGVIEW_IS_IFACE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), LOGVIEW_TYPE_IFACE))
+#define LOGVIEW_GET_INTERFACE(obj) \
+ (G_TYPE_INSTANCE_GET_INTERFACE((obj), LOGVIEW_TYPE_IFACE, \
+typedef struct _LogviewIFace LogviewIFace; /* dummy object */
+typedef struct _LogviewInterface LogviewInterface;
+struct _LogviewInterface {
+ gboolean (*can_handle) (LogviewIFace *self, struct _Log* log);
+GType logview_iface_get_type (void);
+/* for logview application internal usage */
+gboolean logi_can_handle (LogviewIFace *self, struct _Log* log);
+#endif /* __LOGVIEW_IFACE_H__ */
+/* ----------------------------------------------------------------------
+ Copyright (C) 1998 Cesar Miquel (miquel@df.uba.ar)
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ---------------------------------------------------------------------- */
+#ifndef __LOGVIEW_LOG_H__
+#define __LOGVIEW_LOG_H__
+#define LOGVIEW_TYPE_LOG (log_get_type ())
+#define LOGVIEW_LOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LOGVIEW_TYPE_LOG, Log))
+#define LOGVIEW_LOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), LOGVIEW_TYPE_LOG, LogClass))
+#define LOGVIEW_IS_LOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), LOGVIEW_TYPE_LOG))
+#define LOGVIEW_IS_LOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), LOGVIEW_TYPE_LOG))
+#define LOGVIEW_LOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), LOGVIEW_TYPE_LOG, LogClass))
+typedef struct _Log Log;
+typedef struct _LogClass LogClass;
+typedef struct _LogPrivate LogPrivate;
+ * @UNKNOWN_LOG: represents the log can't be recognized.
+ * But still has the opportunity to be handled by other plugins.
+ * @BAD_LOG: represents the log is not a log or a bad log.
+ * If in one time a log is marked with this, it's permanently
+ * ignored and removed from the log name list.
+ * @PLAIN_LOG: a ASCII log.
+ * @GZIP_LOG: a zipped or gzipped log.
+ * @PIPE_LOG: a log can be open by other command.
+ * @USER_DEFINED_LOG: a plugin can define a log protocol for itself,
+ *
e.g. %USER_DEFINED_LOG + 1.
+ TH_EVENT_INIT_READ = 1<<1,
+ TH_EVENT_UPDATE = 1<<2,
+ * @date: a date, without time value.
+ * @first_line: First line for this day in the log.
+ * @last_line: Last line for this day in the log.
+ * @expand: Collapse all the logs in this @date if %FALSE, else expand all.
+ * @path: Gtk tree path of the day item display in main view of the log.
+ * A structure used for grouping and recording the logs by date.
+ long first_line, last_line;
+ * @log: a #Log instance.
+ * Returns: the %PF_LOG_IO type plugin.
+#define log_io(log) (LOGVIEW_IFACE_IO (log->prv->ext_data [PF_LOG_IO]))
+ * @log: a #Log instance.
+ * Returns: the %PF_LOG_VIEW type plugin.
+#define log_view(log) (LOGVIEW_IFACE_VIEW (log->prv->ext_data [PF_LOG_VIEW]))
+ * @self: a #Log instance.
+ * Returns: a constant string which should not be free.
+ * @self: a #Log instance.
+ * Get the #LogProtocol value of self's.
+ * Returns: the #LogProtocol value.
+ * @self: a #Log instance.
+ * @protocol: a #LogProtocol value.
+ * Set the #LogProtocol value of self's.
+ * @log: a #Log instance.
+ * Determining whether @log is a #Log instance.
+ * Returns: TRUE if it is.
+ * @self: a #Log instance.
+ * @index: the child log id. it should be no less than zero and less #OLD_LOG_NUM
+ * @child: a #Log instance.
+ * Access child log instances.
+void log_set_child (Log *self, gint index, Log *child);
+ * @self: a #Log instance.
+ * @index: the child log id. it should be no less than zero and less #OLD_LOG_NUM
+ * Access child log instances.
+ * Returns: the child #Log instance.
+Log* log_get_child (Log *self, gint index);
+ * @self: a #Log instance.
+ * @pf: a #PluginFunc index.
+ * Returns: if a #pf type plugin is assigned to #self, returns TRUE.
+gboolean log_test_func (Log *self, PluginFunc pf);
+ * @self: a #Log instance.
+ * @pf: a #PluginFunc index.
+ * @plugin: a #LogviewPlugin instance.
+ * Assign a #pf type plugin to #self.
+void log_set_func (Log *self, PluginFunc pf, LogviewPlugin *plugin);
+void log_notify (Log *self, ThreadEvent te);
+gchar *log_read (Log *self);
+void log_write_line (Log *self, gchar *line);
+void log_write_lines (Log *self, gchar **lines, gint num);
+void log_write_lines_range (Log *self, gchar **lines, gint start, gint end);
+void log_write_date (Log *self, GDate *date);
+void log_write_day (Log *self, Day *day);
+extern GType log_get_type (void) G_GNUC_CONST;
+#endif /* __LOGVIEW_LOG_H__ */
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+/* default routines for implement the plugin interfaces */
+static gboolean logview_module_load (LogviewModule* self);
+static void logview_module_unload (LogviewModule* self);
+static void logview_module_class_init (gpointer g_class, gpointer g_class_data);
+static void logview_module_instance_init (GTypeInstance *instance, gpointer g_class);
+static GObjectClass *parent_class = NULL;
+struct _LogviewModulePrivate {
+ LogviewPluginInfo *info;
+module_finalize (LogviewModule* self)
+ parent_class->finalize (G_OBJECT (self));
+logview_module_class_init (gpointer g_class, gpointer g_class_data)
+ GObjectClass *object_class;
+ GTypeModuleClass *self;
+ object_class = G_OBJECT_CLASS (g_class);
+ self = G_TYPE_MODULE_CLASS (g_class);
+ parent_class = g_type_class_peek_parent (g_class);
+ object_class->finalize = (void (*)(GObject*)) module_finalize;
+ self->load = (gboolean (*)(GTypeModule*)) logview_module_load;
+ self->unload = (void (*)(GTypeModule*)) logview_module_unload;
+logview_module_instance_init (GTypeInstance *instance, gpointer g_class)
+ LogviewModule *self = LOGVIEW_MODULE (instance);
+ self->prv = g_new0 (LogviewModulePrivate, 1);
+logview_module_get_type (void)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (LogviewModuleClass),
+ NULL, /* base_finalize */
+ logview_module_class_init, /* class_init */
+ NULL, /* class_finalize */
+ sizeof (LogviewModule),
+ logview_module_instance_init /* instance_init */
+ type = g_type_register_static (G_TYPE_TYPE_MODULE, "LogviewModuleType", &info, 0);
+logview_new_module (const gchar* module_path)
+ LogviewModule* new_module = NULL;
+ g_assert (module_path != NULL);
+ new_module = g_object_new (LOGVIEW_TYPE_MODULE, NULL);
+ g_type_module_set_name (G_TYPE_MODULE (new_module), module_path);
+logview_module_new_plugin (const LogviewModule* self)
+ g_assert (self->prv->type != 0);
+ plugin = g_object_new (self->prv->type, NULL);
+ g_assert (LOGVIEW_IS_PLUGIN(plugin));
+ return LOGVIEW_PLUGIN (plugin);
+logview_module_load (LogviewModule* self)
+ GType (*register_logview_plugin)(GTypeModule*);
+ LogviewPluginInfo *(*logview_plugin_info)();
+ self->prv->handle = g_module_open (logview_module_name (self), G_MODULE_BIND_LOCAL);
+ if (self->prv->handle !=NULL) {
+ hit = g_module_symbol (self->prv->handle, "register_logview_plugin", (gpointer*)(®ister_logview_plugin));
+ g_return_val_if_fail (hit != FALSE, FALSE);
+ hit = g_module_symbol (self->prv->handle, "logview_plugin_info", (gpointer*)(&logview_plugin_info));
+ g_return_val_if_fail (hit != FALSE, FALSE);
+ self->prv->type = (*register_logview_plugin) ((GTypeModule*) self);
+ self->prv->info = (*logview_plugin_info) ();
+ g_return_val_if_fail (self->prv->type != 0, FALSE);
+ g_return_val_if_fail (self->prv->info != NULL, FALSE);
+ LV_ERR ("logview_module_load error: %s", g_module_error());
+logview_module_unload (LogviewModule* self)
+ g_module_close (self->prv->handle);
+ self->prv->handle = NULL;
+ self->prv->info = NULL;
+logview_module_name (LogviewModule *self)
+ g_assert (G_IS_TYPE_MODULE (self));
+ return G_TYPE_MODULE (self)->name;
+logview_module_type (LogviewModule *self)
+ return self->prv->type;
+logview_module_priority (LogviewModule *self)
+ return self->prv->info->prio;
+logview_module_desc (LogviewModule *self)
+ return self->prv->info->desc;
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#ifndef __LOGVIEW_MODULE_H__
+#define __LOGVIEW_MODULE_H__
+#define LOGVIEW_TYPE_MODULE (logview_module_get_type ())
+#define LOGVIEW_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOGVIEW_TYPE_MODULE, LogviewModule))
+#define LOGVIEW_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LOGVIEW_TYPE_MODULE, LogviewModuleClass))
+#define LOGVIEW_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOGVIEW_TYPE_MODULE))
+#define LOGVIEW_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LOGVIEW_TYPE_MODULE))
+#define LOGVIEW_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LOGVIEW_TYPE_MODULE, LogviewModuleClass))
+typedef struct _LogviewModule LogviewModule;
+typedef struct _LogviewModuleClass LogviewModuleClass;
+typedef struct _LogviewModulePrivate LogviewModulePrivate;
+ LogviewModulePrivate *prv;
+struct _LogviewModuleClass {
+ GTypeModuleClass parent;
+/* For the core application which should implemete the level to call plugins */
+GType logview_module_get_type (void);
+/* return the name of the module, should not be freed */
+const gchar* logview_module_name (LogviewModule *self);
+GType logview_module_type (LogviewModule *self);
+PluginPrio logview_module_priority (LogviewModule *self);
+const gchar* logview_module_desc (LogviewModule *self);
+/* return a new module */
+LogviewModule* logview_new_module (const gchar* module_path);
+/* return a new plugin */
+LogviewPlugin* logview_module_new_plugin (const LogviewModule* self);
+#endif /* __LOGVIEW_MODULE_H__ */
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+static void logview_plugin_list_init (LogviewPluginList *plugin_list);
+#define GLADE_HOOKUP_OBJECT(component,widget,name) \
+ g_object_set_data_full (G_OBJECT (component), name, \
+ gtk_widget_ref (widget), (GDestroyNotify) gtk_widget_unref)
+#define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
+ g_object_set_data (G_OBJECT (component), name, widget)
+logview_plugin_list_sync_cb (const LogviewModule *module, gpointer data)
+ gchar *name, *desc, *path;
+ LogviewPluginList *self = (LogviewPluginList*)data;
+ path = logview_module_name (module);
+ pri = logview_module_priority (module);
+ desc = logview_module_desc (module);
+ name = log_extract_filename (path);
+ gtk_tree_store_append (self->list, &iter, NULL);
+ gtk_tree_store_set (self->list, &iter,
+logview_plugin_list_sync (LogviewPluginList *self)
+ gtk_widget_hide_all (self->scrolledwindow);
+ gtk_widget_hide_all (self->label);
+ gtk_tree_store_clear (self->list);
+ if (pluginmgr_plugin_amount () > 0) {
+ pluginmgr_modules_iterate (logview_plugin_list_sync_cb, self);
+ gtk_widget_show_all (self->scrolledwindow);
+ gtk_widget_show_all (self->label);
+logview_plugin_list_show (LogviewPluginList *self, GtkWidget *window)
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ gtk_widget_show_all (self->dialog);
+ logview_plugin_list_sync (self);
+logview_plugin_list_cmp (GtkTreeModel *model,
+ gint col_id = GPOINTER_TO_INT(user_data);
+ gtk_tree_model_get (model, a, (gint)user_data, &stra, -1);
+ gtk_tree_model_get (model, b, (gint)user_data, &strb, -1);
+ ret = g_ascii_strcasecmp (stra, strb);
+ gtk_tree_model_get (model, a, (gint)user_data, &ia, -1);
+ gtk_tree_model_get (model, b, (gint)user_data, &ib, -1);
+ g_assert_not_reached ();
+logview_plugin_list_init (LogviewPluginList *self)
+ GtkWidget *dialog_vbox3;
+ GtkWidget *dialog_action_area3;
+ GtkWidget *exist_button;
+ GtkTreeViewColumn *name_col, *pri_col, *path_col, *desc_col;
+ GtkCellRenderer *text_renderer;
+ self->list = gtk_tree_store_new (N_COLS,
+ text_renderer = gtk_cell_renderer_text_new ();
+ view = g_object_new (GTK_TYPE_TREE_VIEW,
+ "headers-clickable", TRUE,
+ name_col = gtk_tree_view_column_new_with_attributes (_("Plugin Name"),
+ gtk_tree_view_column_set_sort_column_id (name_col, NAME_COL);
+ g_object_set (name_col,
+ "sort-indicator", TRUE,
+ pri_col = gtk_tree_view_column_new_with_attributes (_("Priority"),
+ gtk_tree_view_column_set_sort_column_id (pri_col, PRI_COL);
+ "sort-indicator", TRUE,
+ desc_col = gtk_tree_view_column_new_with_attributes (_("Description"),
+ g_object_set (desc_col,
+ path_col = gtk_tree_view_column_new_with_attributes (_("Path"),
+ g_object_set (path_col,
+ "sort-indicator", TRUE,
+ gtk_tree_view_column_set_sort_column_id (path_col, PATH_COL);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(self->list),
+ (GtkTreeIterCompareFunc) logview_plugin_list_cmp,
+ GINT_TO_POINTER(NAME_COL),
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(self->list),
+ (GtkTreeIterCompareFunc) logview_plugin_list_cmp,
+ GINT_TO_POINTER(PATH_COL),
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE(self->list),
+ (GtkTreeIterCompareFunc) logview_plugin_list_cmp,
+ GINT_TO_POINTER(PRI_COL),
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(self->list), NAME_COL, GTK_SORT_ASCENDING);
+ gtk_tree_view_append_column (view, name_col);
+ gtk_tree_view_append_column (view, pri_col);
+ gtk_tree_view_append_column (view, desc_col);
+ gtk_tree_view_append_column (view, path_col);
+ self->dialog = gtk_dialog_new ();
+ gtk_dialog_set_has_separator (GTK_DIALOG (self->dialog), FALSE);
+ gtk_widget_set_size_request (self->dialog, 800, 400);
+ gtk_window_set_destroy_with_parent (GTK_WINDOW (self->dialog), TRUE);
+ gtk_window_set_title (GTK_WINDOW (self->dialog), _("Log Viewer Plugins"));
+ gtk_window_set_position (GTK_WINDOW (self->dialog),
+ GTK_WIN_POS_CENTER_ON_PARENT);
+ gtk_window_set_modal (GTK_WINDOW (self->dialog), TRUE);
+ gtk_window_set_resizable (GTK_WINDOW (self->dialog), TRUE);
+ gtk_window_set_type_hint (GTK_WINDOW (self->dialog),
+ GDK_WINDOW_TYPE_HINT_DIALOG);
+ gtk_window_set_skip_taskbar_hint (GTK_WINDOW (self->dialog), TRUE);
+ dialog_vbox3 = GTK_DIALOG (self->dialog)->vbox;
+ self->label = gtk_label_new (_("No plugins installed!"));
+ gtk_widget_show (self->label);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox3), self->label, TRUE, TRUE, 0);
+ self->scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+ gtk_box_pack_start (GTK_BOX (dialog_vbox3), self->scrolledwindow,
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->scrolledwindow),
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (self->scrolledwindow),
+ gtk_container_add (GTK_CONTAINER (self->scrolledwindow), view);
+ dialog_action_area3 = GTK_DIALOG (self->dialog)->action_area;
+ gtk_container_set_border_width (GTK_CONTAINER (self->scrolledwindow), 12);
+ gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area3),
+ exist_button = gtk_button_new_from_stock ("gtk-close");
+ gtk_dialog_add_action_widget (GTK_DIALOG (self->dialog),
+ exist_button, GTK_RESPONSE_CLOSE);
+ GTK_WIDGET_SET_FLAGS (exist_button, GTK_CAN_DEFAULT);
+ /* Store pointers to all widgets, for use by lookup_widget(). */
+ GLADE_HOOKUP_OBJECT_NO_REF (self->dialog, dialog_vbox3, "dialog_vbox3");
+ GLADE_HOOKUP_OBJECT (self->dialog, self->scrolledwindow, "scrolledwindow");
+ GLADE_HOOKUP_OBJECT (self->dialog, view, "treeview1");
+ GLADE_HOOKUP_OBJECT_NO_REF (self->dialog, dialog_action_area3, "dialog_action_area3");
+ GLADE_HOOKUP_OBJECT (self->dialog, exist_button, "exist_button");
+ GLADE_HOOKUP_OBJECT (self->dialog, self->label, "label1");
+ g_signal_connect_swapped (exist_button, "clicked",
+ G_CALLBACK(gtk_widget_hide_all),
+ g_signal_connect_swapped (self->dialog, "delete-event",
+ G_CALLBACK(gtk_widget_hide_on_delete),
+logview_plugin_list_new (void)
+ LogviewPluginList * list;
+ list = g_new0 (LogviewPluginList, 1);
+ logview_plugin_list_init (list);
+logview_plugin_list_delete (LogviewPluginList * list)
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#ifndef __LOGVIEW_PLUGIN_LIST_H__
+#define __LOGVIEW_PLUGIN_LIST_H__
+typedef struct _LogviewPluginList LogviewPluginList;
+struct _LogviewPluginList {
+ GtkWidget *scrolledwindow;
+void logview_plugin_list_show (LogviewPluginList *self, GtkWidget *window);
+LogviewPluginList *logview_plugin_list_new (void);
+void logview_plugin_list_delete (LogviewPluginList *);
+#endif /* __LOGVIEW_PLUGIN_LIST_H__ */
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#define LOGVIEW_TYPE_PLUGINMGR (logview_pluginmgr_get_type ())
+#define LOGVIEW_PLUGINMGR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LOGVIEW_TYPE_PLUGINMGR, LogviewPluginMgr))
+#define LOGVIEW_PLUGINMGR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), LOGVIEW_TYPE_PLUGINMGR, LogviewPluginMgrClass))
+#define LOGVIEW_IS_PLUGINMGR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), LOGVIEW_TYPE_PLUGINMGR))
+#define LOGVIEW_IS_PLUGINMGR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), LOGVIEW_TYPE_PLUGINMGR))
+#define LOGVIEW_PLUGINMGR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), LOGVIEW_TYPE_PLUGINMGR, LogviewPluginMgrClass))
+static GType logview_pluginmgr_get_type (void);
+static void pluginmgr_class_init (gpointer g_class, gpointer g_class_data);
+static void pluginmgr_instance_init (GTypeInstance *instance, gpointer g_class);
+static gboolean load_module(LogviewPluginMgr *self, const gchar* module_path);
+static void unload_module (LogviewPluginMgr *self, LogviewModule* plugin_info);
+static gboolean load_modules (LogviewPluginMgr *self);
+static void unload_modules (LogviewPluginMgr *self);
+static gboolean register_module (LogviewPluginMgr *self, LogviewModule* plugin_info);
+static gboolean is_plugin_file (const gchar* filepath);
+static Log* pluginmgr_new_log (Log *log);
+/*-------------------------------------------------------------------------------*/
+static gint module_prio_cmpfunc (gconstpointer a, gconstpointer b, gpointer user_data);
+static gint module_cmpfunc (gconstpointer a, gconstpointer b);
+static GObjectClass *parent_class = NULL;
+static LogviewPluginMgr *pluginmgr_instance = NULL;
+struct _LogviewPluginMgrPrivate {
+ GType typehash[MGR_PF_NUM];
+ GSList *modules[MGR_PF_NUM];
+ GSList *plugin_full_paths;
+logview_pluginmgr_get_type (void)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (LogviewPluginMgrClass),
+ NULL, /* base_finalize */
+ pluginmgr_class_init, /* class_init */
+ NULL, /* class_finalize */
+ sizeof (LogviewPluginMgr),
+ pluginmgr_instance_init /* instance_init */
+ type = g_type_register_static (G_TYPE_OBJECT,
+ "LogviewPluginMgrType",
+pluginmgr_instance_init (GTypeInstance *instance, gpointer g_class)
+ LogviewPluginMgr *self = LOGVIEW_PLUGINMGR (instance);
+ self->prv = g_new0 (LogviewPluginMgrPrivate,1);
+ self->prv->typehash[PF_LOG_IO] = LOGVIEW_TYPE_IFACE_IO;
+ self->prv->typehash[PF_LOG_VIEW] = LOGVIEW_TYPE_IFACE_VIEW;
+ self->prv->typehash[PF_LOG_COLLECTOR] = LOGVIEW_TYPE_IFACE_COLLECTOR;
+pluginmgr_finalize (LogviewPluginMgr *self)
+ LOGVIEW_PLUGINMGR_GET_CLASS (self)->unload_modules (self);
+ if (self->prv->plugin_full_paths) {
+ for (idx = self->prv->plugin_full_paths; idx; idx = g_slist_next(idx)) {
+ gchar *path = (gchar *)idx->data;
+ g_slist_free (self->prv->plugin_full_paths);
+ parent_class->finalize (G_OBJECT (self));
+load_modules (LogviewPluginMgr *self)
+ LogviewPluginMgrClass* klass;
+ if (!g_module_supported())
+ klass = LOGVIEW_PLUGINMGR_GET_CLASS(self);
+ plugin_paths = get_plugin_paths();
+ g_return_val_if_fail (plugin_paths != NULL, FALSE);
+ for (idx = plugin_paths; idx; idx = idx->next) {
+ gchar* plugin_full_path;
+ gchar* search_path = idx->data;
+ dir = g_dir_open (search_path, 0, NULL);
+ while ((plugin_full_path = (gchar *) g_dir_read_name (dir)) != NULL) {
+ plugin_full_path = g_build_filename (search_path, plugin_full_path, NULL);
+ if (klass->load_module (self, plugin_full_path)) {
+ LV_INFO ("module %s loaded successfully",
+ g_free (plugin_full_path);
+/* load all modules in the paths */
+load_module (LogviewPluginMgr *self, const gchar* module_path)
+ LogviewModule* module = NULL;
+ if (!is_plugin_file (module_path)) {
+ module = logview_new_module (module_path);
+ g_assert (module != NULL);
+ if (!g_type_module_use ((GTypeModule*) module)) {
+ LV_INFO ("module %s loaded failed: %s",
+ logview_module_name (module), g_module_error ());
+ g_object_unref (module);
+ if (register_module (self, module))
+ g_type_module_unuse ((GTypeModule*) module);
+/* destroy all modules in the paths
+ * must be called after destroy all plugin instances
+unload_modules(LogviewPluginMgr *self)
+ for (idx = self->prv->all_modules; idx != NULL; idx = idx->next) {
+ LogviewModule *module = LOGVIEW_MODULE (idx->data);
+ g_assert (module != NULL);
+ LV_INFO ("unload|module: %s", logview_module_name (module));
+ g_type_module_unuse ((GTypeModule*) module);
+ g_slist_free (self->prv->all_modules);
+ self->prv->all_modules = NULL;
+ for (i = 0; i < MGR_PF_NUM; i++) {
+ if (self->prv->modules[i]) {
+ g_slist_free (self->prv->modules[i]);
+ self->prv->modules[i] = NULL;
+register_module (LogviewPluginMgr *self, LogviewModule* module)
+ GType mt = logview_module_type (module);
+ for (i = 0; i < MGR_PF_NUM; i++) {
+ if (g_type_is_a (mt, self->prv->typehash[i])) {
+ LV_INFO ("module %s, derived from type %s",
+ logview_module_name (module),
+ g_type_name (self->prv->typehash[i]));
+ if (g_slist_find_custom (self->prv->modules[i],
+ module, module_cmpfunc) == NULL) {
+ self->prv->modules[i] =
+ g_slist_insert_sorted_with_data (
+ module, module_prio_cmpfunc, NULL);
+ self->prv->all_modules = g_slist_append (self->prv->all_modules, module);
+unload_module (LogviewPluginMgr *self, LogviewModule* module)
+ GType mt = logview_module_type (module);
+ for (i = 0; i < MGR_PF_NUM; i++) {
+ if (g_type_is_a (mt, self->prv->typehash[i])) {
+ idx = g_slist_find (self->prv->modules[i], module);
+ g_assert (idx != NULL);
+ self->prv->modules[i] =
+ g_slist_delete_link (self->prv->modules[i], idx);
+ idx = g_slist_find (self->prv->all_modules, module);
+ g_assert (idx != NULL);
+ self->prv->all_modules = g_slist_delete_link (self->prv->all_modules, idx);
+ g_type_module_unuse ((GTypeModule*) module);
+module_cmpfunc (gconstpointer a, gconstpointer b)
+ return g_ascii_strcasecmp (logview_module_name (LOGVIEW_MODULE(a)),
+ logview_module_name (LOGVIEW_MODULE(b)));
+module_prio_cmpfunc (gconstpointer a, gconstpointer b, gpointer user_data)
+ PluginPrio ap = logview_module_priority (LOGVIEW_MODULE (a));
+ PluginPrio bp = logview_module_priority (LOGVIEW_MODULE (b));
+ /* from high priory to low */
+ return ap > bp ? -1 : (ap == bp ? 0 : 1);
+is_plugin_file (const gchar* filepath)
+ for (i = 0; suffix[i] != NULL; i++) {
+ g_sprintf (ext, ".%s", suffix[i]);
+ if (g_str_has_suffix (filepath, ext)) {
+ if (g_access (filepath, R_OK) == 0) {
+iterate (LogviewPluginMgr *self, ModuleHandleCB cb, gpointer data)
+ for (idx = self->prv->all_modules; idx; idx = g_slist_next(idx)) {
+ cb (LOGVIEW_MODULE (idx->data), data);
+pluginmgr_class_init (gpointer g_class, gpointer g_class_data)
+ GObjectClass *object_class;
+ LogviewPluginMgrClass *self = LOGVIEW_PLUGINMGR_CLASS (g_class);
+ object_class = G_OBJECT_CLASS (g_class);
+ parent_class = g_type_class_peek_parent (g_class);
+ object_class->finalize = (void(*)(GObject*)) pluginmgr_finalize;
+ self->load_module = load_module;
+ self->unload_module = unload_module;
+ self->load_modules = load_modules;
+ self->unload_modules = unload_modules;
+ self->iterate = iterate;
+pluginmgr_get_all_logs ()
+ GSList *all_logs = NULL;
+ for (idx = pluginmgr_instance->prv->modules[PF_LOG_COLLECTOR];
+ idx != NULL; idx = idx->next) {
+ g_assert (LOGVIEW_IS_MODULE (idx->data));
+ plugin = logview_module_new_plugin (LOGVIEW_MODULE (idx->data));
+ g_assert (LOGVIEW_IS_IFACE_COLLECTOR (plugin));
+ logs = logi_get_logs (LOGVIEW_IFACE_COLLECTOR (plugin));
+ g_object_unref (plugin);
+ for (i = logs; i; i = g_slist_next(i)) {
+ if (g_slist_find_custom (all_logs, i->data,
+ (GCompareFunc) g_ascii_strcasecmp)== NULL) {
+ all_logs = g_slist_append (all_logs, i->data);
+ LV_INFO ("all logs: %s", i->data);
+pluginmgr_handle_derived_log (const Log* parent, PluginFunc pf, LogviewModule *module)
+ g_object_get (G_OBJECT (parent),
+ "archives", &older_logs,
+ for (i=0; i<OLD_LOG_NUM; i++) {
+ plugin = logview_module_new_plugin (module);
+ if (logi_can_handle (LOGVIEW_IFACE (plugin),
+ if (logview_plugin_init (plugin)) {
+ log_set_func (older_logs[i],pf,plugin);
+/* try each plugin to find one which can handle the log */
+pluginmgr_probe_plugin (const Log* log, PluginFunc pf)
+ /* do not check dependency right now */
+ if (pluginmgr_instance->prv->modules[pf] != NULL) {
+ for (idx = pluginmgr_instance->prv->modules[pf]; idx != NULL; idx=idx->next) {
+ module = LOGVIEW_MODULE (idx->data);
+ LV_ERR ("probing module %s", logview_module_name (module));
+ plugin = logview_module_new_plugin (module);
+ g_return_val_if_fail (plugin != NULL, NULL);
+ g_return_val_if_fail (LOGVIEW_IS_PLUGIN (plugin), NULL);
+ g_return_val_if_fail (LOGVIEW_IS_IFACE (plugin), NULL);
+ if (logi_can_handle (LOGVIEW_IFACE (plugin), (struct _Log *) log)) {
+ if (logview_plugin_init (plugin)) {
+ pluginmgr_handle_derived_log (log, pf, module);
+ g_object_unref (plugin);
+gboolean pluginmgr_load_modules ()
+ return LOGVIEW_PLUGINMGR_GET_CLASS (pluginmgr_instance)->load_modules (pluginmgr_instance);
+void pluginmgr_unload_modules ()
+ LOGVIEW_PLUGINMGR_GET_CLASS (pluginmgr_instance)->unload_modules (pluginmgr_instance);
+pluginmgr_new_log_from_path (const gchar* log_path)
+ log_error_init (log_path);
+ for (idx = pluginmgr_instance->prv->modules[PF_LOG_COLLECTOR];
+ idx != NULL; idx = idx->next) {
+ g_assert (LOGVIEW_IS_MODULE (idx->data));
+ plugin = logview_module_new_plugin (LOGVIEW_MODULE (idx->data));
+ g_assert (LOGVIEW_IS_IFACE_COLLECTOR (plugin));
+ if (logi_can_handle (LOGVIEW_IFACE (plugin), log)) {
+ log = logi_config_log_from_path (
+ LOGVIEW_IFACE_COLLECTOR (plugin), log_path);
+ g_object_unref (plugin);
+ return pluginmgr_new_log (log);
+pluginmgr_new_log (Log *log)
+ g_object_get (G_OBJECT (log),
+ "archives", &older_logs,
+ if (! log_test_func (log, PF_LOG_IO)) {
+ plugin = pluginmgr_probe_plugin (log, PF_LOG_IO);
+ log_set_func (log,PF_LOG_IO,plugin);
+ for (i = PF_LOG_IO + 1; i < LOG_PF_NUM; i++) {
+ if (! log_test_func (log, i)) {
+ plugin = pluginmgr_probe_plugin (log, i);
+ log_set_func (log,i,plugin);
+ /* Check for older versions of the log */
+ for (i=0; i<OLD_LOG_NUM; i++) {
+ LOGVIEW_IS_LOG(older_logs[i]))
+ pluginmgr_new_log (older_logs[i]);
+ g_assert (LOGVIEW_IS_LOG (log));
+ log_notify (log, TH_EVENT_INIT_READ);
+ if (pluginmgr_instance != NULL) {
+ g_object_unref (pluginmgr_instance);
+ pluginmgr_instance = NULL;
+ if (pluginmgr_instance == NULL) {
+ pluginmgr_instance = g_object_new (LOGVIEW_TYPE_PLUGINMGR, NULL);
+pluginmgr_modules_iterate (ModuleHandleCB cb, gpointer data)
+ LOGVIEW_PLUGINMGR_GET_CLASS (pluginmgr_instance)->iterate (pluginmgr_instance,
+pluginmgr_plugin_amount ()
+ for (i = 0, n = 0; i < MGR_PF_NUM; i++) {
+ n += g_slist_length (pluginmgr_instance->prv->modules[i]);
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#ifndef __LOGVIEW_PLUGINMGR_H__
+#define __LOGVIEW_PLUGINMGR_H__
+typedef struct _LogviewPluginMgr LogviewPluginMgr;
+typedef struct _LogviewPluginMgrClass LogviewPluginMgrClass;
+typedef struct _LogviewPluginMgrPrivate LogviewPluginMgrPrivate;
+typedef void (*ModuleHandleCB) (const LogviewModule *module, gpointer data);
+struct _LogviewPluginMgr {
+ LogviewPluginMgrPrivate *prv;
+struct _LogviewPluginMgrClass {
+ /* handle one module */
+ gboolean (*load_module) (LogviewPluginMgr *self, const gchar *module_path);
+ void (*unload_module) (LogviewPluginMgr *self, LogviewModule *module);
+ /* handle all module in paths */
+ gboolean (*load_modules)(LogviewPluginMgr *self);
+ void (*unload_modules)(LogviewPluginMgr *self);
+ /* collect all the path names in Plugin paths.
+ return a list, do not try to free it.
+ GSList* (*compose_search_plugin_paths)(LogviewPluginMgr *self);
+ void (*iterate)(LogviewPluginMgr *self, ModuleHandleCB cb, gpointer data);
+/* For the core application which should implemete the level to call plugins */
+//void logview_plugins_detect (const gchar* plugin_patchs);
+extern void pluginmgr_init ();
+extern void pluginmgr_destroy ();
+extern gboolean pluginmgr_load_modules ();
+extern void pluginmgr_unload_modules ();
+extern gint pluginmgr_plugin_amount();
+extern GSList* pluginmgr_get_all_logs ();
+extern Log* pluginmgr_new_log_from_path (const gchar* log_path);
+extern void pluginmgr_modules_iterate (ModuleHandleCB cb, gpointer data);
+/* routines provided for internal usage */
+#endif /* __LOGVIEW_PLUGINMGR_H__ */
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+static GObjectClass *parent_class = NULL;
+static void logview_plugin_finalize (GObject *object);
+logview_plugin_instance_init (LogviewPlugin *self, gpointer g_class_data)
+logview_plugin_class_init (gpointer g_class, gpointer g_class_data)
+ GObjectClass *object_class;
+ LogviewPluginClass *self;
+ object_class = G_OBJECT_CLASS (g_class);
+ self = LOGVIEW_PLUGIN_CLASS (g_class);
+ parent_class = g_type_class_peek_parent (g_class);
+ self->plugin_init = NULL;
+ self->plugin_destroy = NULL;
+ object_class->finalize = logview_plugin_finalize;
+logview_plugin_get_type (void)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (LogviewPluginClass),
+ NULL, /* base_finalize */
+ logview_plugin_class_init, /* class_init */
+ NULL, /* class_finalize */
+ sizeof (LogviewPlugin),
+ (GInstanceInitFunc) logview_plugin_instance_init /* instance_init */
+ type = g_type_register_static (G_TYPE_OBJECT,
+logview_plugin_finalize (GObject *object)
+ if (LOGVIEW_PLUGIN_GET_CLASS (object)->plugin_destroy)
+ LOGVIEW_PLUGIN_GET_CLASS (object)->plugin_destroy (LOGVIEW_PLUGIN (object));
+ parent_class->finalize (object);
+ * @self: a #LogviewPlugin instance.
+ * plugin_init default returns TRUE if it is not overriden.
+ * If it returns FALSE, the plugin will be skipped.
+ * This method will be called by manager after interface can_handle
+ * is called. The plugin should be initialized at this time.
+ * If returns TRUE, this plugin will be assigned to log.
+ * Returns: Upon a successful completion or it is not be overloaded, returns TRUE.
+logview_plugin_init (LogviewPlugin* self)
+ if (LOGVIEW_PLUGIN_GET_CLASS(self)->plugin_init)
+ return LOGVIEW_PLUGIN_GET_CLASS(self)->plugin_init (self);
+ * logview_plugin_destroy:
+ * @self: a #LogviewPlugin instance.
+ * Log instance will automatically destroy all plugins it has.
+ * This method will be automatically called when it's unrefed.
+logview_plugin_destroy (LogviewPlugin* self)
+ if (LOGVIEW_PLUGIN_GET_CLASS(self)->plugin_destroy)
+ LOGVIEW_PLUGIN_GET_CLASS(self)->plugin_destroy (self);
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#ifndef __LOGVIEW_PLUGIN_H__
+#define __LOGVIEW_PLUGIN_H__
+#define LOGVIEW_TYPE_PLUGIN (logview_plugin_get_type ())
+#define LOGVIEW_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LOGVIEW_TYPE_PLUGIN, LogviewPlugin))
+#define LOGVIEW_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), LOGVIEW_TYPE_PLUGIN, LogviewPluginClass))
+#define LOGVIEW_IS_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), LOGVIEW_TYPE_PLUGIN))
+#define LOGVIEW_IS_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), LOGVIEW_TYPE_PLUGIN))
+#define LOGVIEW_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), LOGVIEW_TYPE_PLUGIN, LogviewPluginClass))
+typedef struct _LogviewPluginInfo LogviewPluginInfo;
+typedef struct _LogviewPlugin LogviewPlugin;
+typedef struct _LogviewPluginClass LogviewPluginClass;
+ * @PLUG_PRIO_BASE: the base priority. if a plugin is explicited defined
+ * a priority by redefine #PLUGIN_PRIO, it will be assigned to %PLUG_PRIO_USER.
+ * @PLUG_PRIO_USER: the base line of priority which user should use,
+ *
e.g. %PLUG_PRIO_USER + 1
+ * A plugin with a high priority will be used first.
+#define LOG_PF_NUM PF_LOG_COLLECTOR
+#define MGR_PF_NUM PF_LOG_NUM
+struct _LogviewPluginInfo {
+struct _LogviewPluginClass {
+ gboolean (*plugin_init) (LogviewPlugin* self);
+ void (*plugin_destroy) (LogviewPlugin* self);
+GType logview_plugin_get_type (void);
+gboolean logview_plugin_init (LogviewPlugin* self);
+void logview_plugin_destroy (LogviewPlugin* self);
+ * Define plugin priority, can be redefined by users.
+ * PLUGIN_PRIO should be defined great or equal to PLUG_PRIO_USER,
+ * so that your plugin can be probed first.
+ *
e.g. %PLUG_PRIO_USER + 1
+#define PLUGIN_PRIO PLUG_PRIO_USER
+ * A brief description for the plugin is needed
+ * for displaying the plugin information in GUI.
+ *
e.g. PLUGIN_DESC "For ..."
+#define PLUGIN_DESC "Unknown plugin."
+ * @PluginTypeFunc: a function reports the #GType of the plugin.
+ * A macro exports some useful functions. Therefor core application
+ * can get some useful information to load the plugin.
+#define LOGVIEW_INIT_PLUGIN(PluginTypeFunc) \
+G_MODULE_EXPORT LogviewPluginInfo* logview_plugin_info (void); \
+G_MODULE_EXPORT LogviewPluginInfo* logview_plugin_info (void) \
+ static LogviewPluginInfo __plugin_info; \
+ return &__plugin_info; \
+G_MODULE_EXPORT GType register_logview_plugin (GTypeModule* module); \
+G_MODULE_EXPORT GType register_logview_plugin (GTypeModule* module) \
+ return PluginTypeFunc (module); \
+#endif /* __LOGVIEW_PLUGIN_H__ */
index d1bdbaa..91ce390 100644
/* ----------------------------------------------------------------------
- Copyright (C) 1998 Cesar Miquel (miquel@df.uba.ar)
+Copyright (C) 1998 Cesar Miquel (miquel@df.uba.ar)
- 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 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.
+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., 675 Mass Ave, Cambridge, MA 02139, USA.
+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., 675 Mass Ave, Cambridge, MA 02139, USA.
- ---------------------------------------------------------------------- */
+---------------------------------------------------------------------- */
#define APP_NAME _("System Log Viewer")
static GObjectClass *parent_class;
@@ -76,8 +78,7 @@ static void logview_help (GtkAction *action, GtkWidget *parent_window);
static void logview_copy (GtkAction *action, LogviewWindow *logview);
static void logview_select_all (GtkAction *action, LogviewWindow *logview);
static Log *logview_find_log_from_name (LogviewWindow *logview, gchar *name);
-static void logview_window_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec);
+static void logview_plugin_dialog_show (GtkAction *action, LogviewWindow *logview);
@@ -115,14 +116,16 @@ static GtkActionEntry entries[] = {
G_CALLBACK (logview_help) },
{ "AboutAction", GTK_STOCK_ABOUT, N_("_About"), NULL, N_("Show the about dialog for the log viewer"),
G_CALLBACK (logview_about) },
+ { "PluginList", NULL, N_("_Plugins"), NULL, N_("Show the information of the loaded plugins"),
+ G_CALLBACK (logview_plugin_dialog_show) },
static GtkToggleActionEntry toggle_entries[] = {
- { "ShowStatusBar", NULL, N_("_Statusbar"), NULL, N_("Show Status Bar"),
- G_CALLBACK (logview_toggle_statusbar), TRUE },
+ { "ShowStatusBar", NULL, N_("_Statusbar"), NULL, N_("Show Status Bar"),
+ G_CALLBACK (logview_toggle_statusbar), TRUE },
{ "ShowSidebar", NULL, N_("Side _Pane"), "F9", N_("Show Side Pane"),
- G_CALLBACK (logview_toggle_sidebar), TRUE },
+ G_CALLBACK (logview_toggle_sidebar), TRUE },
{ "MonitorLogs", NULL, N_("_Monitor"), "<control>M", N_("Monitor Current Log"),
G_CALLBACK (logview_toggle_monitor), TRUE },
{"ShowCalendar", NULL, N_("Ca_lendar"), "<control>L", N_("Show Calendar Log"),
@@ -130,202 +133,240 @@ static GtkToggleActionEntry toggle_entries[] = {
static const char *ui_description =
- " <menubar name='LogviewMenu'>"
- " <menu action='FileMenu'>"
- " <menuitem action='OpenLog'/>"
- " <menuitem action='CloseLog'/>"
- " <menuitem action='Quit'/>"
- " <menu action='EditMenu'>"
- " <menuitem action='Copy'/>"
- " <menuitem action='SelectAll'/>"
- " <menu action='ViewMenu'>"
- " <menuitem action='MonitorLogs'/>"
- " <menuitem action='ShowStatusBar'/>"
- " <menuitem action='ShowSidebar'/>"
- " <menuitem action='ShowCalendar'/>"
- " <menuitem action='Search'/>"
- " <menuitem action='CollapseAll'/>"
- " <menuitem action='ViewZoomIn'/>"
- " <menuitem action='ViewZoomOut'/>"
- " <menuitem action='ViewZoom100'/>"
- " <menu action='HelpMenu'>"
- " <menuitem action='HelpContents'/>"
- " <menuitem action='AboutAction'/>"
+" <menubar name='LogviewMenu'>"
+" <menu action='FileMenu'>"
+" <menuitem action='OpenLog'/>"
+" <menuitem action='CloseLog'/>"
+" <menuitem action='Quit'/>"
+" <menu action='EditMenu'>"
+" <menuitem action='Copy'/>"
+" <menuitem action='SelectAll'/>"
+" <menu action='ViewMenu'>"
+" <menuitem action='MonitorLogs'/>"
+" <menuitem action='ShowStatusBar'/>"
+" <menuitem action='ShowSidebar'/>"
+" <menuitem action='ShowCalendar'/>"
+" <menuitem action='Search'/>"
+" <menuitem action='CollapseAll'/>"
+" <menuitem action='ViewZoomIn'/>"
+" <menuitem action='ViewZoomOut'/>"
+" <menuitem action='ViewZoom100'/>"
+" <menuitem action='PluginList'/>"
+" <menu action='HelpMenu'>"
+" <menuitem action='HelpContents'/>"
+" <menuitem action='AboutAction'/>"
logview_get_active_log (LogviewWindow *logview)
- g_return_val_if_fail (LOGVIEW_IS_WINDOW (logview), NULL);
- return logview->curlog;
+ g_return_val_if_fail (LOGVIEW_IS_WINDOW (logview), NULL);
+ return logview->curlog;
logview_get_loglist (LogviewWindow *logview)
- g_return_val_if_fail (LOGVIEW_IS_WINDOW (logview), NULL);
- return LOG_LIST (logview->loglist);
+ g_return_val_if_fail (LOGVIEW_IS_WINDOW (logview), NULL);
+ return LOG_LIST (logview->loglist);
logview_count_logs (LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
- return g_slist_length (logview->logs);
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ return g_slist_length (logview->logs);
logview_store_visible_range (LogviewWindow *logview)
- GtkTreePath *first, *last;
- Log *log = logview->curlog;
+ GtkTreePath *first = NULL;
+ Log *log = logview->curlog;
- if (log->visible_first)
- gtk_tree_path_free (log->visible_first);
+ if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (logview->view),
+ g_object_set (G_OBJECT (log), "visible-first", first, NULL);
- if (gtk_tree_view_get_visible_range (GTK_TREE_VIEW (logview->view),
- log->visible_first = first;
+logview_update_other_components (LogviewWindow *logview)
+ logview_set_window_title (logview);
+ logview_menus_set_state (logview);
+ logview_calendar_set_state (logview);
+ logview_repaint (logview);
+ logview_update_findbar_visibility (logview);
logview_select_log (LogviewWindow *logview, Log *log)
- g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ if (!GTK_WIDGET_VISIBLE (GTK_WIDGET (logview->view)))
- logview_store_visible_range (logview);
- logview_menus_set_state (logview);
- logview_calendar_set_state (logview);
- logview_repaint (logview);
- logview_update_findbar_visibility (logview);
- logview_update_version_bar (logview);
- logview_save_prefs (logview);
- gtk_widget_grab_focus (logview->view);
+ logview_store_visible_range (logview);
+ update version bar first, because the user may choose a child log
+ of logview->curlog, so to avoid update other components multi times
+ give the update responsibility to the change signal of version bar.
+ Note that if choose a log path, then blank out all the Gui.
+ logview_update_version_bar (logview);
+ if (logview->curlog == NULL) {
+ logview_update_other_components (logview);
+ gtk_widget_grab_focus (logview->view);
logview_add_log_from_name (LogviewWindow *logview, gchar *file)
- g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
- g_return_if_fail (file);
+ g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ g_return_if_fail (file);
- log = log_open (file, TRUE);
- logview_add_log (logview, log);
+ log = pluginmgr_new_log_from_path (file);
+ logview_add_log (logview, log);
+ error_dialog_show (NULL, _("Add log error."), log_error());
logview_add_logs_from_names (LogviewWindow *logview, GSList *lognames, gchar *selected)
- Log *log, *curlog = NULL;
+ Log *log, *curlog = NULL;
- g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
- for (list = lognames; list != NULL; list = g_slist_next (list)) {
- log = log_open (list->data, FALSE);
- logview_add_log (logview, log);
- if (selected!=NULL && g_strncasecmp (log->name, selected, -1)==0)
+ g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ /* remove log_open, open by pluginmgr_get_all_logs or loglist? */
+ for (list = lognames; list != NULL; list = g_slist_next (list)) {
+ log = pluginmgr_new_log_from_path ((gchar*)list->data);
+ logview_add_log (logview, log);
+ g_object_get (G_OBJECT (log), "path", &log_name, NULL);
+ (g_strncasecmp (log_name, selected, -1) == 0))
+ error_dialog_show (NULL, _("Add log error."), log_error());
- loglist_select_log (LOG_LIST (logview->loglist), curlog);
+ loglist_select_log (LOG_LIST (logview->loglist), curlog);
- gtk_tree_view_expand_all (GTK_TREE_VIEW (logview->loglist));
+ gtk_tree_view_expand_all (GTK_TREE_VIEW (logview->loglist));
logview_menus_set_state (LogviewWindow *logview)
- gboolean calendar_active = FALSE, monitor_active = FALSE;
- g_assert (LOGVIEW_IS_WINDOW (logview));
- monitor_active = (log->display_name == NULL);
- calendar_active = (log->days != NULL);
+ gboolean calendar_active = FALSE, monitor_active = FALSE;
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_LOG (log));
+ g_object_get (G_OBJECT (log),
+ "monitorable", &monitorable,
+ "monitoring", &monitoring,
+ "groupable", &groupable,
+ monitor_active = monitorable;
+ calendar_active = groupable;
+ logview_menu_item_toggle_set_active (logview,
logview_set_window_title (LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
- if (log->name != NULL) {
- if (log->display_name != NULL)
- logname = log->display_name;
- window_title = g_strdup_printf (_("%s (monitored) - %s"), logname, APP_NAME);
- window_title = g_strdup_printf ("%s - %s", logname, APP_NAME);
- window_title = g_strdup_printf (APP_NAME);
- gtk_window_set_title (GTK_WINDOW (logview), window_title);
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_object_get (G_OBJECT (log),
+ "display-name", &logname,
+ "monitoring", &monitoring,
+ g_object_get (G_OBJECT (log),
+ window_title = g_strdup_printf (_("%s (monitored) - %s"), logname, APP_NAME);
+ window_title = g_strdup_printf (_("%s - %s"), logname, APP_NAME);
+ window_title = g_strdup_printf (APP_NAME);
+ gtk_window_set_title (GTK_WINDOW (logview), window_title);
logview_show_main_content (LogviewWindow *logview)
- g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
- gtk_widget_show (logview->calendar);
- gtk_widget_show (logview->loglist);
- gtk_widget_show (logview->sidebar);
- gtk_widget_show (logview->view);
- gtk_widget_show (logview->hpaned);
- gtk_widget_show (logview->statusbar);
+ g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ gtk_widget_show (logview->calendar);
+ gtk_widget_show (logview->loglist);
+ gtk_widget_show (logview->sidebar);
+ gtk_widget_show (logview->view);
+ gtk_widget_show (logview->hpaned);
+ gtk_widget_show (logview->statusbar);
@@ -334,12 +375,18 @@ static void
logview_update_findbar_visibility (LogviewWindow *logview)
Log *log = logview->curlog;
- gtk_widget_hide (logview->find_bar);
+ GtkTreeModelFilter *filter;
+ gtk_widget_hide (logview->find_bar);
+ g_object_get (G_OBJECT (log),
- if (log->filter != NULL)
gtk_widget_show (logview->find_bar);
gtk_widget_hide (logview->find_bar);
@@ -348,208 +395,279 @@ logview_update_findbar_visibility (LogviewWindow *logview)
logview_save_prefs (LogviewWindow *logview)
- g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
- if (GTK_WIDGET_VISIBLE (GTK_WIDGET (logview->loglist))) {
- for (list = logview->logs; list != NULL; list = g_slist_next (list)) {
- prefs_store_log (log->name);
+ if (GTK_WIDGET_VISIBLE (GTK_WIDGET (logview->loglist))) {
+ for (list = logview->logs; list != NULL; list = g_slist_next (list)) {
+ g_assert (LOGVIEW_IS_LOG (list->data));
+ log = LOGVIEW_LOG (list->data);
+ g_object_get (G_OBJECT (log), "path", &name, NULL);
+ prefs_store_log (name);
- if (logview->curlog->parent_log)
- prefs_store_active_log (logview->curlog->parent_log->name);
- prefs_store_active_log (logview->curlog->name);
+ gchar *log_name, *parent_name;
+ log_name = parent_name = NULL;
+ g_assert (LOGVIEW_IS_LOG (logview->curlog));
+ g_object_get (G_OBJECT (logview->curlog),
+ g_assert (LOGVIEW_IS_LOG (parent));
+ g_object_get (G_OBJECT (parent),
+ prefs_store_active_log (parent_name);
+ prefs_store_active_log (log_name);
+ prefs_store_fontsize (logview->fontsize);
- prefs_store_fontsize (logview->fontsize);
logview_destroy (GObject *object, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
- if (logview->curlog->monitored)
- monitor_stop (logview->curlog);
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_object_get (G_OBJECT (logview->curlog), "monitoring", &monitoring, NULL);
+ monitor_stop (logview->curlog);
- logview_save_prefs (logview);
+ logview_save_prefs (logview);
+ logview_select_log (logview, NULL);
+ for (idx = logview->logs; idx != NULL; idx = idx->next) {
+ g_assert (LOGVIEW_IS_LOG (idx->data));
+ log = LOGVIEW_LOG (idx->data);
+ g_object_get (G_OBJECT (log), "monitoring", &monitoring, NULL);
+ g_slist_foreach (logview->logs, (GFunc) g_object_unref, NULL);
+ g_slist_free (logview->logs);
- if (gtk_main_level() > 0)
+ if (gtk_main_level() > 0)
+ logview_debug_destroy ();
logview_add_log (LogviewWindow *logview, Log *log)
- g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
- g_return_if_fail (log);
+ g_return_if_fail (LOGVIEW_IS_WINDOW (logview));
+ g_return_if_fail (log);
- logview->logs = g_slist_append (logview->logs, log);
- loglist_add_log (LOG_LIST(logview->loglist), log);
+ logview->logs = g_slist_append (logview->logs, log);
+ loglist_add_log (LOG_LIST(logview->loglist), log);
+ g_object_set (G_OBJECT (log), "view", logview->view, NULL);
+ logview_select_log (logview, log);
logview_find_log_from_name (LogviewWindow *logview, gchar *name)
- if (logview == NULL || name == NULL)
- for (list = logview->logs; list != NULL; list = g_slist_next (list)) {
- if (g_ascii_strncasecmp (log->name, name, 255) == 0) {
+ if (logview == NULL || name == NULL)
+ for (list = logview->logs; list != NULL; list = g_slist_next (list)) {
+ g_object_get (G_OBJECT (log), "path", &log_name, NULL);
+ if (g_ascii_strncasecmp (log_name , name, 255) == 0) {
logview_version_selector_changed (GtkComboBox *version_selector, gpointer user_data)
LogviewWindow *logview = user_data;
- Log *log = logview->curlog;
+ int selected, archive_id, current_version, versions;
+ gchar *archive_n = NULL;
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ if (logview->curlog == NULL)
+ g_assert (LOGVIEW_IS_LOG (logview->curlog));
+ /* first, get the parent log */
+ g_object_get (G_OBJECT (logview->curlog),
+ g_object_get (G_OBJECT (log),
+ "current-version", ¤t_version,
selected = gtk_combo_box_get_active (version_selector);
- if (selected == log->current_version)
+ /* return if already selected and
+ recorded pointer is equal to the current log or child log */
+ archive_n = gtk_combo_box_get_active_text (version_selector);
+ sscanf (archive_n, "%*s%d", &archive_id);
/* select a new version */
- logview_select_log (logview, log->parent_log);
+ g_object_set (G_OBJECT (log),
+ "current-version", selected,
- new = log->parent_log->older_logs[selected];
- new = log->older_logs[selected];
- logview_select_log (logview, new);
+ logview->curlog = old_logs[archive_id];
+ /* must update the gui due to currently log is switched */
+ logview_update_other_components (logview);
logview_close_log (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
- if (logview->curlog == NULL)
+ if (logview->curlog == NULL)
- if (logview->curlog->monitored) {
- gtk_action_activate (action);
+ g_object_get (G_OBJECT (logview->curlog), "monitoring", &monitoring, NULL);
+ gtk_action_activate (action);
- gtk_widget_hide (logview->find_bar);
+ gtk_widget_hide (logview->find_bar);
- logview->curlog = NULL;
+ /* loglist can only remove parent log */
+ g_object_get (G_OBJECT (logview->curlog), "parent", &log, NULL);
+ logview->curlog = NULL;
- logview->logs = g_slist_remove (logview->logs, log);
- loglist_remove_log (LOG_LIST (logview->loglist), log);
+ logview->logs = g_slist_remove (logview->logs, log);
+ loglist_remove_log (LOG_LIST (logview->loglist), log);
logview_file_selected_cb (GtkWidget *chooser, gint response, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
- gtk_widget_hide (GTK_WIDGET (chooser));
- if (response != GTK_RESPONSE_OK)
- f = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
- /* Check if the log is not already opened */
- for (list = logview->logs; list != NULL; list = g_slist_next (list)) {
- if (g_ascii_strncasecmp (log->name, f, 255) == 0) {
- loglist_select_log (LOG_LIST (logview->loglist), log);
- if ((tl = log_open (f, TRUE)) != NULL)
- logview_add_log (logview, tl);
+ gtk_widget_hide (GTK_WIDGET (chooser));
+ if (response != GTK_RESPONSE_OK)
+ f = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+ /* Check if the log is not already opened */
+ for (list = logview->logs; list != NULL; list = g_slist_next (list)) {
+ g_object_get (G_OBJECT (log), "path", &log_name, NULL);
+ if (g_ascii_strncasecmp (log_name, f, 255) == 0) {
+ loglist_select_log (LOG_LIST (logview->loglist), log);
+ if ((tl = pluginmgr_new_log_from_path (f)) != NULL)
+ logview_add_log (logview, tl);
+ error_dialog_show (NULL, _("Add log error."), log_error());
logview_open_log (GtkAction *action, LogviewWindow *logview)
- static GtkWidget *chooser = NULL;
+ static GtkWidget *chooser = NULL;
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
- chooser = gtk_file_chooser_dialog_new (_("Open Log"),
- GTK_FILE_CHOOSER_ACTION_OPEN,
- GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- GTK_STOCK_OPEN, GTK_RESPONSE_OK,
- gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
- gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
- g_signal_connect (G_OBJECT (chooser), "response",
- G_CALLBACK (logview_file_selected_cb), logview);
- g_signal_connect (G_OBJECT (chooser), "destroy",
- G_CALLBACK (gtk_widget_destroyed), &chooser);
- if (prefs_get_active_log () != NULL)
- gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser),
- prefs_get_active_log ());
- gtk_window_present (GTK_WINDOW (chooser));
+ chooser = gtk_file_chooser_dialog_new (_("Open Log"),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_OK,
+ gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_OK);
+ gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
+ g_signal_connect (G_OBJECT (chooser), "response",
+ G_CALLBACK (logview_file_selected_cb), logview);
+ g_signal_connect (G_OBJECT (chooser), "destroy",
+ G_CALLBACK (gtk_widget_destroyed), &chooser);
+ if (prefs_get_active_log () != NULL)
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser),
+ prefs_get_active_log ());
+ gtk_window_present (GTK_WINDOW (chooser));
logview_toggle_statusbar (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
- if (GTK_WIDGET_VISIBLE (logview->statusbar))
- gtk_widget_hide (logview->statusbar);
- gtk_widget_show (logview->statusbar);
+ if (GTK_WIDGET_VISIBLE (logview->statusbar))
+ gtk_widget_hide (logview->statusbar);
+ gtk_widget_show (logview->statusbar);
logview_toggle_sidebar (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
if (GTK_WIDGET_VISIBLE (logview->sidebar))
gtk_widget_hide (logview->sidebar);
@@ -560,7 +678,7 @@ logview_toggle_sidebar (GtkAction *action, LogviewWindow *logview)
logview_toggle_calendar (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
if (GTK_WIDGET_VISIBLE (logview->calendar))
gtk_widget_hide (logview->calendar);
@@ -576,37 +694,46 @@ logview_toggle_calendar (GtkAction *action, LogviewWindow *logview)
logview_collapse_rows (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
- gtk_tree_view_collapse_all (GTK_TREE_VIEW (logview->view));
+ gtk_tree_view_collapse_all (GTK_TREE_VIEW (logview->view));
logview_toggle_monitor (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
- if ((log == NULL) || (log->display_name))
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_object_get (G_OBJECT (log),
+ "display-name", &display_name,
+ "monitoring", &monitoring,
+ if ((log == NULL) || display_name) {
- if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) &&
+ if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) &&
- if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))==FALSE &&
+ if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))==FALSE &&
- logview_set_window_title (logview);
- logview_menus_set_state (logview);
+ logview_set_window_title (logview);
+ logview_menus_set_state (logview);
#define DEFAULT_LOGVIEW_FONT "Monospace 10"
@@ -635,7 +762,7 @@ logview_set_fontsize (LogviewWindow *logview)
PangoFontDescription *fontdesc;
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
context = gtk_widget_get_pango_context (logview->view);
fontdesc = pango_context_get_font_description (context);
@@ -647,7 +774,7 @@ logview_set_fontsize (LogviewWindow *logview)
logview_bigger_text (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
logview->fontsize = MIN (logview->fontsize + 1, 24);
logview_set_fontsize (logview);
@@ -656,7 +783,7 @@ logview_bigger_text (GtkAction *action, LogviewWindow *logview)
logview_smaller_text (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
logview->fontsize = MAX (logview->fontsize-1, 6);
logview_set_fontsize (logview);
@@ -665,7 +792,7 @@ logview_smaller_text (GtkAction *action, LogviewWindow *logview)
logview_normal_text (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
logview->fontsize = logview->original_fontsize;
logview_set_fontsize (logview);
@@ -674,47 +801,56 @@ logview_normal_text (GtkAction *action, LogviewWindow *logview)
logview_search (GtkAction *action, LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
- gtk_widget_show_all (logview->find_bar);
- logview_findbar_grab_focus (LOGVIEW_FINDBAR (logview->find_bar));
+ gtk_widget_show_all (logview->find_bar);
+ logview_findbar_grab_focus (LOGVIEW_FINDBAR (logview->find_bar));
logview_copy (GtkAction *action, LogviewWindow *logview)
- GtkClipboard *clipboard;
- g_assert (LOGVIEW_IS_WINDOW (logview));
- l1 = log->selected_line_first;
- l2 = log->selected_line_last;
- if (l1 == -1 || l2 == -1)
- lines = g_new0(gchar *, (nline + 1));
- for (i=0; i<=nline; i++) {
- line = log->lines[l1+i];
- lines[i] = g_strdup (line);
- text = g_strjoinv ("\n", lines);
- clipboard = gtk_widget_get_clipboard (GTK_WIDGET (logview->view),
- GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text (clipboard, text, -1);
+ GtkTreePath *selected_path;
+ GtkClipboard *clipboard;
+ GList *selected_paths, *idx;
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_LOG (log));
+ g_object_get (G_OBJECT (log),
+ "selected-paths", &selected_paths,
+ if (selected_paths == NULL)
+ nline = g_list_length (selected_paths);
+ lines = g_new0(gchar *, (nline + 1));
+ for (i = 0, idx = selected_paths; idx != NULL; idx = g_list_next (idx), i++) {
+ selected_path = idx->data;
+ gtk_tree_model_get_iter (model, &iter, selected_path);
+ gtk_tree_model_get (model,
+ text = g_strjoinv ("\n", lines);
+ clipboard = gtk_widget_get_clipboard (GTK_WIDGET (logview->view),
+ GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text (clipboard, text, -1);
@@ -722,7 +858,7 @@ logview_select_all (GtkAction *action, LogviewWindow *logview)
GtkTreeSelection *selection;
- g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (logview->view));
gtk_tree_selection_select_all (selection);
@@ -731,12 +867,12 @@ logview_select_all (GtkAction *action, LogviewWindow *logview)
logview_menu_item_toggle_set_active (LogviewWindow *logview, char *path, gboolean state)
- GtkToggleAction *action;
+ GtkToggleAction *action;
- action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (logview->ui_manager, path));
- gtk_toggle_action_set_active (action, state);
+ action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (logview->ui_manager, path));
+ gtk_toggle_action_set_active (action, state);
@@ -753,22 +889,26 @@ logview_menu_item_set_state (LogviewWindow *logview, char *path, gboolean state)
logview_calendar_set_state (LogviewWindow *logview)
- g_assert (LOGVIEW_IS_WINDOW (logview));
- if (logview->curlog->days != NULL)
- calendar_init_data (CALENDAR (logview->calendar), logview);
- gtk_widget_set_sensitive (logview->calendar, (logview->curlog->days != NULL));
- gtk_widget_set_sensitive (logview->calendar, FALSE);
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ g_object_get (G_OBJECT (logview->curlog),
+ "groupable", &groupable,
+ calendar_init_data (CALENDAR (logview->calendar), logview);
+ gtk_widget_set_sensitive (logview->calendar, groupable);
+ gtk_widget_set_sensitive (logview->calendar, FALSE);
logview_help (GtkAction *action, GtkWidget *parent_window)
- gnome_help_display_desktop_on_screen (NULL, "gnome-system-log", "gnome-system-log", NULL,
- gtk_widget_get_screen (GTK_WIDGET(parent_window)), &error);
+ gnome_help_display_desktop_on_screen (NULL, "gnome-system-log", "gnome-system-log", NULL,
+ gtk_widget_get_screen (GTK_WIDGET(parent_window)), &error);
error_dialog_show (GTK_WIDGET(parent_window), _("There was an error displaying help."), error->message);
@@ -777,188 +917,175 @@ logview_help (GtkAction *action, GtkWidget *parent_window)
window_size_changed_cb (GtkWidget *widget, GdkEventConfigure *event,
- LogviewWindow *logview = LOGVIEW_WINDOW (data);
+ LogviewWindow *logview = LOGVIEW_WINDOW (data);
- g_assert (LOGVIEW_IS_WINDOW (logview));
- prefs_store_window_size (GTK_WIDGET(logview));
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ prefs_store_window_size (GTK_WIDGET(logview));
logview_window_finalize (GObject *object)
- LogviewWindow *logview = LOGVIEW_WINDOW(object);
+ LogviewWindow *logview = LOGVIEW_WINDOW(object);
+ logview_plugin_list_delete (logview->plugin_list);
- g_object_unref (logview->ui_manager);
- parent_class->finalize (object);
+ g_object_unref (logview->ui_manager);
+ parent_class->finalize (object);
logview_init (LogviewWindow *logview)
- GtkTreeStore *tree_store;
- GtkTreeSelection *selection;
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
- GtkActionGroup *action_group;
- GtkAccelGroup *accel_group;
- GtkWidget *loglist_scrolled, *scrolled;
- PangoFontDescription *fontdesc;
- gchar *monospace_font_name;
- gtk_window_set_default_size (GTK_WINDOW (logview), prefs_get_width (), prefs_get_height ());
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (logview), vbox);
- action_group = gtk_action_group_new ("LogviewMenuActions");
- gtk_action_group_set_translation_domain (action_group, NULL);
- gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), logview);
- gtk_action_group_add_toggle_actions(action_group, toggle_entries, G_N_ELEMENTS (toggle_entries), logview);
- logview->ui_manager = gtk_ui_manager_new ();
- gtk_ui_manager_insert_action_group (logview->ui_manager, action_group, 0);
+ GtkTreeSelection *selection;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+ GtkActionGroup *action_group;
+ GtkAccelGroup *accel_group;
+ GtkWidget *loglist_scrolled, *scrolled;
+ PangoFontDescription *fontdesc;
+ gchar *monospace_font_name;
+ gtk_window_set_default_size (GTK_WINDOW (logview), prefs_get_width (), prefs_get_height ());
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (logview), vbox);
+ action_group = gtk_action_group_new ("LogviewMenuActions");
+ gtk_action_group_set_translation_domain (action_group, NULL);
+ gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), logview);
+ gtk_action_group_add_toggle_actions(action_group, toggle_entries, G_N_ELEMENTS (toggle_entries), logview);
+ logview->ui_manager = gtk_ui_manager_new ();
+ gtk_ui_manager_insert_action_group (logview->ui_manager, action_group, 0);
- accel_group = gtk_ui_manager_get_accel_group (logview->ui_manager);
- gtk_window_add_accel_group (GTK_WINDOW (logview), accel_group);
+ accel_group = gtk_ui_manager_get_accel_group (logview->ui_manager);
+ gtk_window_add_accel_group (GTK_WINDOW (logview), accel_group);
- if (!gtk_ui_manager_add_ui_from_string (logview->ui_manager, ui_description, -1, &error)) {
- logview->ui_manager = NULL;
+ if (!gtk_ui_manager_add_ui_from_string (logview->ui_manager, ui_description, -1, &error)) {
+ logview->ui_manager = NULL;
- menubar = gtk_ui_manager_get_widget (logview->ui_manager, "/LogviewMenu");
- gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
+ menubar = gtk_ui_manager_get_widget (logview->ui_manager, "/LogviewMenu");
+ gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
- hpaned = gtk_hpaned_new ();
- gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
+ hpaned = gtk_hpaned_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
- /* First pane : sidebar (list of logs + calendar) */
- logview->sidebar = gtk_vbox_new (FALSE, 0);
- logview->calendar = calendar_new ();
- calendar_connect (CALENDAR (logview->calendar), logview);
- gtk_box_pack_end (GTK_BOX (logview->sidebar), GTK_WIDGET(logview->calendar), FALSE, FALSE, 0);
+ /* First pane : sidebar (list of logs + calendar) */
+ logview->sidebar = gtk_vbox_new (FALSE, 0);
- loglist_scrolled = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (loglist_scrolled),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (loglist_scrolled),
- logview->loglist = loglist_new ();
- gtk_container_add (GTK_CONTAINER (loglist_scrolled), logview->loglist);
- gtk_box_pack_start (GTK_BOX (logview->sidebar), loglist_scrolled, TRUE, TRUE, 0);
- gtk_paned_pack1 (GTK_PANED (hpaned), logview->sidebar, FALSE, FALSE);
- loglist_connect (LOG_LIST(logview->loglist), logview);
- /* Second pane : log */
- main_view = gtk_vbox_new (FALSE, 0);
- gtk_paned_pack2 (GTK_PANED (hpaned), GTK_WIDGET (main_view), TRUE, TRUE);
- /* Scrolled window for the main view */
- scrolled = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
- gtk_box_pack_start (GTK_BOX(main_view), scrolled, TRUE, TRUE, 0);
- logview->view = gtk_tree_view_new ();
- gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (logview->view), FALSE);
- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (logview->view), FALSE);
- /* Use the desktop monospace font */
- monospace_font_name = prefs_get_monospace ();
- logview_set_font (logview, monospace_font_name);
- g_free (monospace_font_name);
- renderer = gtk_cell_renderer_text_new ();
- column = gtk_tree_view_column_new ();
- gtk_tree_view_column_pack_start (column, renderer, TRUE);
- gtk_tree_view_column_set_attributes (column, renderer,
- "weight", LOG_LINE_WEIGHT,
- "weight-set", LOG_LINE_WEIGHT_SET,
- //gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
- gtk_tree_view_append_column (GTK_TREE_VIEW (logview->view), column);
- logview->version_bar = gtk_hbox_new (FALSE, 0);
- gtk_container_set_border_width (GTK_CONTAINER (logview->version_bar), 3);
- logview->version_selector = gtk_combo_box_new_text ();
- g_signal_connect (G_OBJECT (logview->version_selector), "changed",
- G_CALLBACK (logview_version_selector_changed), logview);
- label = gtk_label_new (_("Version: "));
+ logview->calendar = calendar_new ();
+ calendar_connect (CALENDAR (logview->calendar), logview);
+ gtk_box_pack_end (GTK_BOX (logview->sidebar), GTK_WIDGET(logview->calendar), FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX(logview->version_bar), logview->version_selector, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX(logview->version_bar), label, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX(main_view), logview->version_bar, FALSE, FALSE, 0);
+ loglist_scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (loglist_scrolled),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (loglist_scrolled),
+ logview->loglist = loglist_new ((gpointer)logview);
+ gtk_container_add (GTK_CONTAINER (loglist_scrolled), logview->loglist);
+ gtk_box_pack_start (GTK_BOX (logview->sidebar), loglist_scrolled, TRUE, TRUE, 0);
+ gtk_paned_pack1 (GTK_PANED (hpaned), logview->sidebar, FALSE, FALSE);
+ /* Second pane : log */
+ main_view = gtk_vbox_new (FALSE, 0);
+ gtk_paned_pack2 (GTK_PANED (hpaned), GTK_WIDGET (main_view), TRUE, TRUE);
+ /* Scrolled window for the main view */
+ scrolled = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
+ gtk_box_pack_start (GTK_BOX(main_view), scrolled, TRUE, TRUE, 0);
+ logview->view = gtk_tree_view_new ();
+ gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (logview->view), FALSE);
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (logview->view), FALSE);
+ /* Use the desktop monospace font */
+ monospace_font_name = prefs_get_monospace ();
+ logview_set_font (logview, monospace_font_name);
+ g_free (monospace_font_name);
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_pack_start (column, renderer, TRUE);
+ gtk_tree_view_column_set_attributes (column, renderer,
+ "weight", LOG_LINE_WEIGHT1,
+ "weight-set", LOG_LINE_WEIGHT_SET1,
+ gtk_tree_view_append_column (GTK_TREE_VIEW (logview->view), column);
+ logview->version_bar = gtk_hbox_new (FALSE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (logview->version_bar), 3);
+ logview->version_selector = gtk_combo_box_new_text ();
+ g_signal_connect (G_OBJECT (logview->version_selector), "changed",
+ G_CALLBACK (logview_version_selector_changed), logview);
+ label = gtk_label_new (_("Version: "));
- logview->find_bar = logview_findbar_new ();
- gtk_box_pack_end (GTK_BOX (main_view), logview->find_bar, FALSE, FALSE, 0);
- logview_findbar_connect (LOGVIEW_FINDBAR (logview->find_bar), logview);
- /* Remember the original font size */
- context = gtk_widget_get_pango_context (logview->view);
- fontdesc = pango_context_get_font_description (context);
- logview->original_fontsize = pango_font_description_get_size (fontdesc) / PANGO_SCALE;
- logview->fontsize = logview->original_fontsize;
- gtk_container_add (GTK_CONTAINER (scrolled), GTK_WIDGET (logview->view));
- gtk_widget_show_all (scrolled);
+ gtk_box_pack_end (GTK_BOX(logview->version_bar), logview->version_selector, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX(logview->version_bar), label, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX(main_view), logview->version_bar, FALSE, FALSE, 0);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (logview->view));
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
- /* Add signal handlers */
- g_signal_connect (G_OBJECT (selection), "changed",
- G_CALLBACK (selection_changed_cb), logview);
- g_signal_connect (G_OBJECT (logview->view), "row-expanded",
- G_CALLBACK (row_toggled_cb), logview);
- g_signal_connect (G_OBJECT (logview->view), "row-collapsed",
- G_CALLBACK (row_toggled_cb), logview);
- g_signal_connect (G_OBJECT (logview), "configure_event",
- G_CALLBACK (window_size_changed_cb), logview);
- /* Status area at bottom */
- logview->statusbar = gtk_statusbar_new ();
- gtk_box_pack_start (GTK_BOX (vbox), logview->statusbar, FALSE, FALSE, 0);
- gtk_widget_show (menubar);
- gtk_widget_show (loglist_scrolled);
- gtk_widget_show (main_view);
- gtk_widget_show (vbox);
- logview->hpaned = hpaned;
+ logview->find_bar = logview_findbar_new ();
+ gtk_box_pack_end (GTK_BOX (main_view), logview->find_bar, FALSE, FALSE, 0);
+ logview_findbar_connect (LOGVIEW_FINDBAR (logview->find_bar), logview);
-logview_window_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec)
- LogviewWindow *logview = LOGVIEW_WINDOW (object);
- g_value_set_pointer (value, logview->curlog->days);
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ /* Remember the original font size */
+ context = gtk_widget_get_pango_context (logview->view);
+ fontdesc = pango_context_get_font_description (context);
+ logview->original_fontsize = pango_font_description_get_size (fontdesc) / PANGO_SCALE;
+ logview->fontsize = logview->original_fontsize;
+ gtk_container_add (GTK_CONTAINER (scrolled), GTK_WIDGET (logview->view));
+ gtk_widget_show_all (scrolled);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (logview->view));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+ /* Add signal handlers */
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (selection_changed_cb), logview);
+ g_signal_connect (G_OBJECT (logview->view), "row-expanded",
+ G_CALLBACK (row_toggled_cb), logview);
+ g_signal_connect (G_OBJECT (logview->view), "row-collapsed",
+ G_CALLBACK (row_toggled_cb), logview);
+ g_signal_connect (G_OBJECT (logview), "configure_event",
+ G_CALLBACK (window_size_changed_cb), logview);
+ /* Status area at bottom */
+ logview->statusbar = gtk_statusbar_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), logview->statusbar, FALSE, FALSE, 0);
+ gtk_widget_show (menubar);
+ gtk_widget_show (loglist_scrolled);
+ gtk_widget_show (main_view);
+ gtk_widget_show (vbox);
+ logview->hpaned = hpaned;
+ logview->plugin_list = logview_plugin_list_new ();
+ /* set logview pointer */
+ monitor_set_window ((gpointer)logview);
@@ -967,14 +1094,7 @@ logview_window_class_init (LogviewWindowClass *klass)
GObjectClass *object_class = (GObjectClass *) klass;
object_class->finalize = logview_window_finalize;
- object_class->get_property = logview_window_get_property;
parent_class = g_type_class_peek_parent (klass);
- g_object_class_install_property (object_class, PROP_DAYS,
- g_param_spec_pointer ("days",
- _("Pointer towards a GSList of days for the current log."),
@@ -1004,21 +1124,28 @@ logview_window_get_type (void)
- LogviewWindow *logview;
+ LogviewWindow *logview;
- window = g_object_new (LOGVIEW_TYPE_WINDOW, NULL);
- logview = LOGVIEW_WINDOW (window);
- if (logview->ui_manager == NULL)
+ window = g_object_new (LOGVIEW_TYPE_WINDOW, NULL);
+ logview = LOGVIEW_WINDOW (window);
+ if (logview->ui_manager == NULL)
- gtk_ui_manager_set_add_tearoffs (logview->ui_manager,
- prefs_get_have_tearoff ());
+ gtk_ui_manager_set_add_tearoffs (logview->ui_manager,
+ prefs_get_have_tearoff ());
- g_signal_connect (GTK_OBJECT (window), "destroy",
- G_CALLBACK (logview_destroy), logview);
+ g_signal_connect (GTK_OBJECT (window), "destroy",
+ G_CALLBACK (logview_destroy), logview);
+logview_plugin_dialog_show (GtkAction *action, LogviewWindow *logview)
+ g_assert (LOGVIEW_IS_WINDOW (logview));
+ logview_plugin_list_show (logview->plugin_list, GTK_WIDGET (logview));
index dacfa2e..1e826d6 100644
@@ -39,19 +40,20 @@ typedef struct _LogviewWindowClass LogviewWindowClass;
GtkWindow parent_instance;
GtkUIManager *ui_manager;
GtkWidget *version_selector;
+ LogviewPluginList *plugin_list;
int original_fontsize, fontsize;
index 37242b8..05e17af 100644
static gboolean show_version = FALSE;
@@ -86,7 +88,6 @@ save_session_cb (GnomeClient *gnome_client,
g_assert (LOGVIEW_IS_WINDOW (logview));
@@ -98,12 +99,11 @@ save_session_cb (GnomeClient *gnome_client,
argv = g_new0 (gchar *, numlogs + 2);
argv[i++] = g_get_prgname();
- for (logs = logview->logs; logs != NULL; logs = logs->next) {
+ for (i = 1, logs = logview->logs; logs != NULL; logs = logs->next) {
Log *log = (Log *) logs->data;
- argv[i++] = g_strdup (log->name);
+ g_object_get (G_OBJECT (log), "path", &argv[i++], NULL);
main (int argc, char *argv[])
GnomeClient *gnome_client;
@@ -129,10 +128,6 @@ main (int argc, char *argv[])
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
- error_dialog_queue (TRUE);
context = logview_init_options ();
program = gnome_program_init ("gnome-system-log", VERSION,
@@ -140,20 +135,42 @@ main (int argc, char *argv[])
GNOME_PARAM_APP_DATADIR, DATADIR,
GNOME_PARAM_GOPTION_CONTEXT, context,
g_set_application_name (_("Log Viewer"));
logview_show_version_and_quit ();
+ error_dialog_queue (TRUE);
+ if (! g_thread_supported ())
+ if (!create_home_dir ()) {
+ g_printf (_("Fatal error! Can't open $HOME/%s.\n"),
+ if (!pluginmgr_load_modules ()) {
+ error_dialog_show (NULL,
+ _("Unable to load modules."),
/* Open regular logs and add each log passed as a parameter */
logview = LOGVIEW_WINDOW (logview_window_new ());
_("Unable to create user interface."),
@@ -174,7 +191,7 @@ main (int argc, char *argv[])
- for (i = 1; i < argc; i++)
+ for (i = 1; i < argc; i++)
logview_add_log_from_name (logview, argv[i]);
@@ -191,6 +208,10 @@ main (int argc, char *argv[])
+ logview_debug_destroy ();
index 09db2c7..57cf343 100644
---------------------------------------------------------------------- */
+#define _XOPEN_SOURCE 500
+#define LOGVIEW_DATA_PLUGIN_PATH LOGVIEWPLUGINDIR
+#define LOGVIEW_USER_PLUGIN_PATH_SUFFIX LOGVIEW_HOME_SUFFIX"/plugins"
+char *error_main = N_("One file or more could not be opened");
static gboolean queue_err_messages = FALSE;
static GSList *msg_queue_main = NULL, *msg_queue_sec = NULL;
@@ -44,7 +65,7 @@ const char *month[12] =
N_("November"), N_("December")};
-error_dialog_run (GtkWidget *window, const char *main, char *secondary)
+error_dialog_run (GtkWidget *window, const char *main, const char *secondary)
dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (window),
@@ -60,13 +81,13 @@ error_dialog_run (GtkWidget *window, const char *main, char *secondary)
-error_dialog_show (GtkWidget *window, char *main, char *secondary)
+error_dialog_show (GtkWidget *window, const char *main, const char *secondary)
- if (queue_err_messages) {
- msg_queue_main = g_slist_append (msg_queue_main, g_strdup (main));
- msg_queue_sec = g_slist_append (msg_queue_sec, g_strdup (secondary));
- error_dialog_run (window, main, secondary);
+ if (queue_err_messages) {
+ msg_queue_main = g_slist_append (msg_queue_main, g_strdup (main));
+ msg_queue_sec = g_slist_append (msg_queue_sec, g_strdup (secondary));
+ error_dialog_run (window, main, secondary);
@@ -116,63 +137,599 @@ error_dialog_show_queued (void)
+error_system_string (void)
+ return strerror (errno);
locale_to_utf8 (const char *in)
- if (g_utf8_validate (in, -1, NULL))
- out = g_locale_to_utf8 (in, -1, NULL, NULL, NULL);
+ if (g_utf8_validate (in, -1, NULL))
+ out = g_locale_to_utf8 (in, -1, NULL, NULL, NULL);
string_get_date (char *line)
- if (line == NULL || line[0] == 0)
- cp = strptime (line, "%b %d", &tp);
- cp = strptime (line, "%F", &tp);
+ char *tm_locale = NULL;
+ if (line == NULL || line[0] == '\0')
+ if (tm_locale != NULL) {
+ tm_locale = setlocale (LC_TIME, NULL);
+ setlocale (LC_TIME, "C");
+ if ((cp = strptime (line, "%b %d", &tp)) == NULL)
+ if ((cp = strptime (line, "%a %b %d", &tp)) == NULL)
+ if ((cp = strptime (line, "%F", &tp)) == NULL) {
+ setlocale (LC_TIME, tm_locale);
+ if (tm_locale != NULL) {
+ setlocale (LC_TIME, tm_locale);
-date_get_string (GDate *date)
+date_to_string (GDate *date)
- if (date == NULL || !g_date_valid (date)) {
- utf8 = g_strdup(_("Invalid date"));
+ if (date == NULL || !g_date_valid (date)) {
+ utf8 = g_strdup(_("Invalid date"));
- /* Translators: Only date format, time will be bogus */
- if (g_date_strftime (buf, sizeof (buf), _("%x"), date) == 0) {
- int m = g_date_get_month (date);
- int d = g_date_get_day (date);
- /* If we fail just use the US format */
- utf8 = g_strdup_printf ("%s %d", _(month[(int) m-1]), d);
- utf8 = locale_to_utf8 (buf);
+ /* Translators: Only date format, time will be bogus */
+ if (g_date_strftime (buf, sizeof (buf), _("%x"), date) == 0) {
+ int m = g_date_get_month (date);
+ int d = g_date_get_day (date);
+ /* If we fail just use the US format */
+ utf8 = g_strdup_printf ("%s %d", _(month[(int) m-1]), d);
+ utf8 = locale_to_utf8 (buf);
+try_to_open (const gchar *filename, gboolean show_error)
+ GnomeVFSHandle *handle;
+ char *secondary = NULL;
+ result = gnome_vfs_open (&handle, filename, GNOME_VFS_OPEN_READ);
+ if (result != GNOME_VFS_OK) {
+ case GNOME_VFS_ERROR_ACCESS_DENIED:
+ case GNOME_VFS_ERROR_NOT_PERMITTED:
+ secondary = g_strdup_printf (_("%s is not user readable. "
+ "Either run the program as root or ask the sysadmin to "
+ "change the permissions on the file.\n"), filename);
+ case GNOME_VFS_ERROR_TOO_BIG:
+ secondary = g_strdup_printf (_("%s is too big."), filename);
+ secondary = g_strdup_printf (_("%s could not be opened."), filename);
+ error_dialog_show (NULL, error_main, secondary);
+ gnome_vfs_close (handle);
+log_extract_dirname (const gchar *logname)
+ uri = gnome_vfs_uri_new (logname);
+ dirname = gnome_vfs_uri_extract_dirname (uri);
+ gnome_vfs_uri_unref (uri);
+log_extract_filename (const gchar *logname)
+ uri = gnome_vfs_uri_new (logname);
+ filename = gnome_vfs_uri_extract_short_name (uri);
+ gnome_vfs_uri_unref (uri);
+extract_filepath (const gchar *logname, gchar** dirname, gchar** filename)
+ uri = gnome_vfs_uri_new (logname);
+ if (dirname != NULL) *dirname = gnome_vfs_uri_extract_dirname (uri);
+ if (filename != NULL) *filename = gnome_vfs_uri_extract_short_name (uri);
+ gnome_vfs_uri_unref (uri);
+get_date_string (gchar *line)
+ gchar **split, *date_string;
+ gchar *month=NULL, *day=NULL;
+ if (line == NULL || line[0] == 0)
+ split = g_strsplit (line, " ", 4);
+ while ((day == NULL || month == NULL) && split[i]!=NULL && i<4) {
+ if (g_str_equal (split[i], "")) {
+ /* If the first field begins by a number, the date
+ is given in yyyy-mm-dd format */
+ if (!g_ascii_isalpha (month[0]))
+ date_string = g_strconcat (month, " ", day, NULL);
+ date_string = g_strconcat (month, " ", day, NULL);
+file_protocol (const char *filename)
+ g_assert (filename[0] != '\0');
+ if (local_file_exist (filename)) {
+ char *mime_type = gnome_vfs_get_mime_type (filename);
+ LV_INFO ("[protocol] %s detected mime: %s",
+ mime_type != NULL ? mime_type : "(nil)");
+ if (mime_type == NULL) {
+ protocol = UNKNOWN_LOG;
+ } else if (g_str_has_prefix (mime_type, "text/")) {
+ } else if (g_str_has_prefix (mime_type, "x-directory/") ||
+ protocol = UNKNOWN_LOG;
+ protocol = UNKNOWN_LOG;
+ LV_INFO ("[protocol] %s assigned protocol: %d", filename, protocol);
+local_file_can_executed (const gchar *filename)
+ if (stat (filename, &buf) == 0) {
+local_file_exist (const gchar *filename)
+ if (stat (filename, &buf) == 0) {
+ static gchar cpu_arch[BUFSIZ] = {0};
+ /* get system ARCH for Solaris*/
+ if (sysinfo(SI_ARCHITECTURE, cpu_arch, sizeof (cpu_arch)) == -1) {
+ LV_INFO_EE ("get sysinfo failed: %s", error_system_string ());
+ if (uname(&buf) == -1) {
+ LV_INFO_EE ("get sysinfo failed: %s", error_system_string ());
+ LV_ERR ("ARCH = %s", cpu_arch);
+ static GSList *plugin_paths = NULL;
+ gchar* user_plugin_path = NULL;
+ /* get user plugin path */
+ user_plugin_path = g_build_path (G_DIR_SEPARATOR_S,
+ (gchar*)g_get_home_dir (),
+ LOGVIEW_USER_PLUGIN_PATH_SUFFIX,
+ if (stat (user_plugin_path, &buf) == 0) {
+ plugin_paths = g_slist_append (plugin_paths,
+ g_free (user_plugin_path);
+ else if (errno == ENOENT &&
+ g_mkdir_with_parents (user_plugin_path, get_umask()) == 0) {
+ plugin_paths = g_slist_append (plugin_paths,
+ LV_ERR ("err|create user plugin path: %s", user_plugin_path);
+ g_free (user_plugin_path);
+ /* get default plugin path */
+ if (stat (LOGVIEW_DATA_PLUGIN_PATH, &buf) == 0) {
+ plugin_paths = g_slist_append(plugin_paths,
+ (gpointer*)g_strdup (LOGVIEW_DATA_PLUGIN_PATH));
+ * Alternative popen due to the security issue
+} pf_node; /* pair of pipe and file description */
+static GSList *pf_list = NULL;
+pf_insert (int fd, pid_t pid)
+ pf_node *node = g_new0 (pf_node, 1);
+ pf_list = g_slist_prepend (pf_list, node);
+ for (idx = pf_list; idx; idx=g_slist_next (idx)) {
+ if (((pf_node *)idx->data)->fd == fd) {
+ pid = ((pf_node *)idx->data)->pid;
+ pf_list = g_slist_delete_link (pf_list, idx);
+static GStaticMutex pipe_mutex = G_STATIC_MUTEX_INIT;
+#define PIPE_MUTEX_LOCK() (g_static_mutex_lock (&pipe_mutex))
+#define PIPE_MUTEX_UNLOCK() (g_static_mutex_unlock (&pipe_mutex))
+ * @argv: directly pass to execve, so should be NULL terminated.
+ * @envp: directly pass to execve.
+ * RETURNS: the pointer of the file stream structure.
+_security_popen (const char *path, char *const argv[], char *const envp[])
+ if (path == NULL || argv == NULL)
+ if ((iop = fdopen (p[0], "r")) == NULL) {
+ if ((pid = vfork()) == 0) {
+ if (p[1] != STDOUT_FILENO) {
+ if (dup2 (p[1], STDOUT_FILENO) == -1){
+ for (idx = pf_list; idx; idx = g_slist_next (idx)) {
+ close (((pf_node *)idx->data)->fd);
+ g_slist_free (pf_list);
+ error = execve (path, argv, envp);
+security_pclose (FILE *fp)
+ pid = pf_delete (fileno (fp));
+ while (waitpid(pid, &status, 0) < 0) {
+ * @command: the command need be executed.
+ * @mode: for compatible usage in Linux, this function will call popen().
+ * In Solaris, it's useless.
+ * RETURNS: the pointer of the file stream structure.
+security_popen (const char *command, const char *mode)
+ static const char *shellenv = "SHELL";
+ static const char *pfsh_path = "
/bin/pfsh";
+ static const char *pfsh = "pfsh";
+ static const char *pfcsh = "pfcsh";
+ static const char *pfksh = "pfksh";
+ static const char *sh_opt = "-c";
+ shpath = (char*) pfsh_path;
+ argve[0] = (char *) shell;
+ argve[1] = (char *) sh_opt;
+ argve[2] = (char *) command;
+ return _security_popen (shpath, (char* const*)argve, res_path);
+ return popen (command, mode);
+static gchar *err_msg = NULL;
+log_error_init (const gchar *log_path)
+ err_msg = g_strdup_printf ("%s :\n", log_path);
+log_error_append (const gchar *msg)
+ tmp = g_strdup_printf ("%s\t%s\n", err_msg, msg);
+log_error_appendv (const gchar *format, ...)
+ err= g_strdup_vprintf (format, ap);
+ tmp = g_strdup_printf ("%s\t%s\n", err_msg, err);
+ static gint current_umask=0;
+ if (current_umask == 0) {
+ current_umask = umode ^ 0777;
+ gchar* logview_home = NULL;
+ /* get user plugin path */
+ logview_home = g_build_path (G_DIR_SEPARATOR_S,
+ (gchar*)g_get_home_dir (),
+ if (stat (logview_home, &buf) == 0) {
+ } else if (errno == ENOENT &&
+ g_mkdir_with_parents (logview_home, get_umask()) == 0) {
index c0eb5ee..37d4e01 100644
-void error_dialog_show (GtkWidget *window, char *main, char *secondary);
+#define LOGVIEW_HOME_SUFFIX ".gnome2/gnome-system-log"
+void error_dialog_show (GtkWidget *window, const char *main, const char *secondary);
void error_dialog_queue (gboolean do_queue);
void error_dialog_show_queued (void);
+char* error_system_string (void);
char *locale_to_utf8 (const char *in);
GDate *string_get_date (char *line);
int string_get_month (const char *str);
-char *date_get_string (GDate *date);
+char *date_to_string (GDate *date);
+gboolean file_is_log (char *filename, gboolean show_error);
+gchar *log_extract_dirname (const gchar *logname);
+gchar *log_extract_filename (const gchar *logname);
+void extract_filepath (const gchar *logname, gchar** dirname, gchar** filename);
+LogProtocol file_protocol (const char *filename);
+gboolean try_to_open (const gchar *filename, gboolean show_error);
+gboolean local_file_exist (const gchar *filename);
+gboolean local_file_can_executed (const gchar *filename);
+gchar * get_date_string (gchar *line);
+gchar * processor_arch (void);
+G_CONST_RETURN GSList* get_plugin_paths();
+FILE* security_popen (const char *cmd, const char *mode);
+int security_pclose (FILE *fp);
+G_CONST_RETURN gchar *log_error (void);
+void log_error_append (const gchar *msg);
+void log_error_init (const gchar *log_path);
+gboolean create_home_dir (void);
#endif /* __LOG_MISC_H__ */
-/* ----------------------------------------------------------------------
+/* ----------------------------------------------------------------------
- Copyright (C) 1998 Cesar Miquel (miquel@df.uba.ar)
+Copyright (C) 1998 Cesar Miquel (miquel@df.uba.ar)
- 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 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.
+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., 675 Mass Ave, Cambridge, MA 02139, USA.
+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., 675 Mass Ave, Cambridge, MA 02139, USA.
- ---------------------------------------------------------------------- */
+---------------------------------------------------------------------- */
+#define CHECK_FILE_PERIOD 10000
+static gpointer window = NULL;
- g_return_if_fail (log);
- if (log->mon_handle != NULL) {
- gnome_vfs_monitor_cancel (log->mon_handle);
- log->mon_handle = NULL;
- gnome_vfs_close (log->mon_file_handle);
- log->mon_file_handle = NULL;
- log->monitored = FALSE;
+ GnomeVFSMonitorHandle *mon_handle;
+ g_assert (LOGVIEW_IS_LOG (log));
+ g_object_get (G_OBJECT (log),
+ "monitor-handle", &mon_handle, NULL);
+ if (mon_handle != NULL) {
+ gnome_vfs_monitor_cancel (mon_handle);
+ g_object_set (G_OBJECT (log),
+ "monitor-handle", NULL, NULL);
+ g_object_set (G_OBJECT (log),
+ "monitoring", FALSE, NULL);
monitor_callback (GnomeVFSMonitorHandle *handle, const gchar *monitor_uri,
- const gchar *info_uri, GnomeVFSMonitorEventType event_type,
+ const gchar *info_uri, GnomeVFSMonitorEventType event_type,
+ LogviewWindow *logview = LOGVIEW_WINDOW(window);
+ g_assert (LOGVIEW_IS_LOG (log));
+ loglist_bold_log (LOG_LIST (logview->loglist), log);
+ if (logview->curlog == log)
+ logview_repaint (logview);
+/* ----------------------------------------------------------------------
+NAME: monitor_log_was_modified
+DESCRIPTION: Returns true if modified flag in log changed. It also
+changes the modified flag. This function is called in unexpected time,
+so the passed in log must be referenced. And only unreferenced when timer
+---------------------------------------------------------------------- */
+monitor_log_was_modified (Log *log)
- LogviewWindow *logview;
- logview = LOGVIEW_WINDOW (log->window);
- loglist_bold_log (LOG_LIST (logview->loglist), log);
- log->needs_refresh = TRUE;
- if (logview->curlog == log)
- logview_repaint (logview);
+ g_assert (LOGVIEW_IS_LOG (log));
+ g_object_get (G_OBJECT (log), "monitoring", &monitoring, NULL);
+ if (log_has_been_modified (log)) {
+ monitor_callback(NULL, NULL, NULL, 0, log);
- gchar *main = NULL, *second = NULL;
- g_return_if_fail (log);
- result = gnome_vfs_open (&(log->mon_file_handle), log->name,
- result = gnome_vfs_seek (log->mon_file_handle, GNOME_VFS_SEEK_END, 0L);
- result = gnome_vfs_tell (log->mon_file_handle, &size);
- log->mon_offset = size;
- result = gnome_vfs_monitor_add (&(log->mon_handle), log->name,
- GNOME_VFS_MONITOR_FILE, monitor_callback,
- if (result != GNOME_VFS_OK) {
- main = g_strdup (_("This file cannot be monitored."));
- case GNOME_VFS_ERROR_NOT_SUPPORTED :
- second = g_strdup (_("File monitoring is not supported on this file system.\n"));
- second = g_strdup (_("Gnome-VFS Error.\n"));
- error_dialog_show (NULL, main, second);
- gnome_vfs_close (log->mon_file_handle);
+ gchar *first = NULL, *second = NULL;
+ GnomeVFSMonitorHandle *mon_handle;
+ g_assert (LOGVIEW_IS_LOG (log));
+ g_object_get (G_OBJECT (log),
+ "monitorable", &monitorable,
+ "monitor-handle", &mon_handle,
+ result = gnome_vfs_monitor_add (&mon_handle, name,
+ GNOME_VFS_MONITOR_FILE,
+ monitor_callback, log);
+ if (result != GNOME_VFS_OK) {
+ if (result == GNOME_VFS_ERROR_NOT_SUPPORTED) {
+ g_timeout_add (CHECK_FILE_PERIOD,
+ (GSourceFunc) monitor_log_was_modified,
+ if (mon_handle != NULL) {
+ g_object_set (G_OBJECT (log),
+ "monitor-handle", mon_handle, NULL);
+ g_object_set (G_OBJECT (log),
+ "monitoring", TRUE, NULL);
+ first = g_strdup (_("Gnome-VFS error."));
+ second = g_strdup_printf ("%s, (%d): %s",
+ gnome_vfs_result_to_string (result));
+ error_dialog_show (NULL, first, second);
+monitor_set_window (gpointer win)
+ g_assert (window == NULL);
index 30f9360..76fd3a0 100644
#ifndef __LOG_MONITOR_H__
#define __LOG_MONITOR_H__
+void monitor_set_window (gpointer win);
void monitor_start (Log *log);
void monitor_stop (Log *log);
+ $(PLUGIN_LIBTOOL_FLAGS) $(GNOME_UTILS_LIBS) $(GMODULE_LIBS)
+libgrablogs_la_LDFLAGS = \
+ $(PLUGIN_LIBTOOL_FLAGS) $(GNOME_UTILS_LIBS) $(GMODULE_LIBS)
+libplainlog_la_LDFLAGS = \
+ $(PLUGIN_LIBTOOL_FLAGS) $(GNOME_UTILS_LIBS) $(GMODULE_LIBS)
+libpipelog_la_LDFLAGS = \
+ $(PLUGIN_LIBTOOL_FLAGS) $(GNOME_UTILS_LIBS) $(GMODULE_LIBS)
+libbaseview_la_LDFLAGS = \
+ $(PLUGIN_LIBTOOL_FLAGS) $(GNOME_UTILS_LIBS) $(GMODULE_LIBS)
+additionaldir = $(plugindir)
+# This part allows people to build their own plugins in here.
+ $(LIBTOOL) --mode=compile $(CC) -DHAVE_CONFIG_H -I$(top_srcdir) $(AM_CPPFLAGS) $(CFLAGS) -c $< -o tmp$@.lo $(GNOME_UTILS_CFLAGS)
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o libtmp$@.la -rpath $(plugindir) tmp$@.lo $(LIBS) $(LDFLAGS) -module -avoid-version $(GNOME_UTILS_LIBS)
+ @rm -f tmp$@.lo tmp$@.o libtmp$@.la
+ @cp .libs/libtmp$@.so* $@
+ @rm -f .libs/libtmp$@.*
+ -DDATADIR=\"$(datadir)\" \
+ -I$(top_builddir)/logview \
+ -I$(top_srcdir)/logview \
+ $(GNOME_UTILS_CFLAGS) \
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#define PLUGIN_BASEVIEW(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), PLUGIN_TYPE_BASEVIEW, Baseview))
+#define PLUGIN_BASEVIEW_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), PLUGIN_TYPE_BASEVIEW, BaseviewClass))
+#define BASEVIEW_IS_PLUGIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PLUGIN_TYPE_BASEVIEW))
+#define BASEVIEW_IS_PLUGIN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), PLUGIN_TYPE_BASEVIEW))
+#define PLUGIN_BASEVIEW_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), PLUGIN_TYPE_BASEVIEW, BaseviewClass))
+#define PLUGIN_PRIO PLUG_PRIO_BASE
+#define PLUGIN_DESC "Group by date and try to convert to UTF-8"
+typedef struct _Baseview Baseview;
+typedef struct _BaseviewClass BaseviewClass;
+ LogviewPluginClass parent;
+static void iface_init (gpointer g_iface, gpointer iface_data);
+static void view_init (gpointer g_iface, gpointer iface_data);
+baseview_class_init (gpointer g_class, gpointer g_class_data)
+baseview_instance_init (GTypeInstance *instance, gpointer g_class_data)
+baseview_get_type (GTypeModule* module)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (BaseviewClass),
+ NULL, /* base_finalize */
+ baseview_class_init, /* class_init */
+ NULL, /* class_finalize */
+ baseview_instance_init /* instance_init */
+ static const GInterfaceInfo iface_info = {
+ iface_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ static const GInterfaceInfo view_info = {
+ view_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ type = g_type_module_register_type (module,
+ g_type_module_add_interface (module, type, LOGVIEW_TYPE_IFACE,
+ g_type_module_add_interface (module, type, LOGVIEW_TYPE_IFACE_VIEW,
+can_handle(Baseview *self, Log *log)
+days_compare (gconstpointer a, gconstpointer b)
+ const Day *day1 = a, *day2 = b;
+ return (g_date_compare (day1->date, day2->date));
+ Read all dates which have a log entry to create calendar.
+ All dates are given with respect to the 1/1/1970
+ and are then corrected to the correct year once we
+baseview_read_dates (LogviewIView *self, gchar **buffer_lines, time_t current)
+ int offsetyear = 0, current_year;
+ GSList *days = NULL, *days_copy;
+ int i, n, rangemin, rangemax;
+ if (buffer_lines == NULL)
+ n = g_strv_length (buffer_lines);
+ for (i=0; buffer_lines[i] == NULL && i < n; i++);
+ tmptm = localtime (¤t);
+ current_year = tmptm->tm_year + 1900;
+ /* Start building the list */
+ /* Scanning each line to see if the date changed is too slow,
+ so we proceed in a recursive fashion */
+ date = string_get_date (buffer_lines[i]);
+ if ((date==NULL)|| !g_date_valid (date)) {
+ g_date_set_year (date, current_year);
+ days = g_slist_append (days, day);
+ date_string = get_date_string (buffer_lines[i]);
+ while (day->last_line < 0) {
+ if (g_str_has_prefix (buffer_lines[i], date_string)) {
+ if (!g_str_has_prefix (buffer_lines[i+1], date_string)) {
+ i = (int) ( ((float) i + (float) rangemax)/2.);
+ i = (int) (((float) rangemin + (float) i)/2.);
+ /* We need to find the first line now that has a date
+ Logs can have some messages without dates ... */
+ while (newdate == NULL && !done && i < n) {
+ date_string = get_date_string (buffer_lines[i]);
+ if (date_string == NULL)
+ g_assert (newdate == NULL);
+ newdate = string_get_date (buffer_lines[i]);
+ if (newdate == NULL && i==n-1)
+ /* Append a day to the list */
+ g_date_set_year (newdate, current_year + offsetyear);
+ if (g_date_compare (newdate, date) < 1) {
+ offsetyear++; /* newdate is next year */
+ g_date_add_years (newdate, 1);
+ days = g_slist_append (days, day);
+ /* Correct years now. We assume that the last date on the log
+ is the date last accessed */
+ for (days_copy = days; days_copy != NULL; days_copy = g_slist_next (days_copy)) {
+ day = days_copy -> data;
+ g_date_subtract_years (day->date, offsetyear);
+ /* Sort the days in chronological order */
+ days = g_slist_sort (days, days_compare);
+group_lines (LogviewIView *self, const gchar **lines)
+ return baseview_read_dates (self, (gchar **)lines, time (NULL));
+iface_init (gpointer g_iface, gpointer iface_data)
+ LogviewInterface *iface = (LogviewInterface*)g_iface;
+ iface->can_handle = (gboolean (*) (LogviewIFace*, Log*)) can_handle;
+to_utf8 (LogviewIView *self, gchar *str)
+ if (g_utf8_validate (str, -1, NULL))
+ if ((out = g_locale_to_utf8 (str, -1, NULL, NULL, NULL)) != NULL)
+view_init (gpointer g_iface, gpointer iface_data)
+ LogviewIFaceView *self = (LogviewIFaceView*)g_iface;
+ self->group_lines = (GSList* (*) (LogviewIView*, const gchar**)) group_lines;
+ self->to_utf8 = (gchar* (*) (LogviewIView*, gchar*, gssize)) to_utf8;
+LOGVIEW_INIT_PLUGIN (baseview_get_type)
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#define PLUGIN_GRABLOGS(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), PLUGIN_TYPE_GRABLOGS, PluginGrabLogs))
+#define PLUGIN_GRABLOGS_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), PLUGIN_TYPE_GRABLOGS, PluginGrabLogsClass))
+#define GRABLOGS_IS_PLUGIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PLUGIN_TYPE_GRABLOGS))
+#define GRABLOGS_IS_PLUGIN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), PLUGIN_TYPE_GRABLOGS))
+#define PLUGIN_GRABLOGS_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), PLUGIN_TYPE_GRABLOGS, PluginGrabLogsClass))
+#define PLUGIN_PRIO PLUG_PRIO_BASE
+#define PLUGIN_DESC "For colloct log files from shell commands"
+#define CAT_CMD "[commands]"
+#define CAT_LOG "[logs]"
+#define CAT_CONF "[configs]"
+typedef GSList* (*Parse_All) (FILE*);
+typedef GSList* (*Parse_Line) (FILE*, Parse_All);
+typedef struct _PluginGrabLogs PluginGrabLogs;
+typedef struct _PluginGrabLogsClass PluginGrabLogsClass;
+struct _PluginGrabLogs {
+struct _PluginGrabLogsClass {
+ LogviewPluginClass parent;
+static void iface_init (gpointer g_iface, gpointer iface_data);
+static void collector_init (gpointer g_iface, gpointer iface_data);
+static struct sigaction old_sa;
+grablogs_class_init (gpointer g_class, gpointer g_class_data)
+grablogs_instance_init (GTypeInstance *instance, gpointer g_class_data)
+grablogs_get_type (GTypeModule* module)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (PluginGrabLogsClass),
+ NULL, /* base_finalize */
+ grablogs_class_init, /* class_init */
+ NULL, /* class_finalize */
+ sizeof (PluginGrabLogs),
+ grablogs_instance_init /* instance_init */
+ static const GInterfaceInfo iface_info = {
+ iface_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ static const GInterfaceInfo collector_info = {
+ collector_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ type = g_type_module_register_type (module,
+ g_type_module_add_interface (module, type, LOGVIEW_TYPE_IFACE,
+ g_type_module_add_interface (module, type, LOGVIEW_TYPE_IFACE_COLLECTOR,
+get_logs (const gchar* logcfg, Parse_All cp)
+ GSList* loglist = NULL;
+ int (*lclose) (FILE*) = NULL;
+ * lines in [command] will be run in popen
+ if (category && g_ascii_strcasecmp(g_strstrip(category),
+ LV_INFO ("[grablogs-PIPE-open] %s", logcfg);
+ handle = security_popen (logcfg, "r");
+ lclose = security_pclose;
+ else if (local_file_exist (logcfg)
+ && local_file_can_executed (logcfg)) {
+ LV_INFO ("[grablogs-FILE-open] %s", logcfg);
+ handle = fopen (logcfg, "r");
+ LV_INFO ("[grablogs-open] %s", logcfg);
+ if (lclose (handle) == -1)
+ LV_INFO ("[grablogs-close] %s", logcfg);
+ LV_INFO_EE ("[grablogs handles]: \"%s\", msg: %s",
+ logcfg, error_system_string ());
+ glong inc = BUFSIZ, size = inc;
+ gchar *buf = (gchar *) g_malloc (size * sizeof (gchar));
+ buf = (gchar *) g_realloc (buf, size * sizeof(gchar));
+ buf[p] = (gchar)getc (handle);
+ } while (buf[p] != '\n' && buf[p] != EOF);
+ } else if (feof (handle) == 0 && p > 0) {
+ } else if (feof (handle) != 0) {
+ LV_INFO_EE ("get_line error: %s", error_system_string());
+ LV_ERR ("get_line %s", buf? buf:"EOFed");
+cp_logline (FILE *handle)
+ GSList *logfiles = NULL;
+ while ((buf = get_line(handle)) != NULL) {
+ if (g_str_has_prefix (g_strchug (buf), "#")) {
+ if (g_str_has_prefix(g_strstrip(buf), "[")) {
+ logfiles = g_slist_append (logfiles, g_strdup (buf));
+cp_logconf (FILE *handle)
+ GSList *logfiles = NULL;
+ while ((buf = get_line(handle)) != NULL) {
+ for (p = buf; g_ascii_isspace(*p); ++p);
+ if (*p == '\0' || *p == '#' || *p == '\n') {
+ list = g_strsplit_set (p, ", -\t()\n'`", 0);
+ for (i = 0; list[i]; ++i) {
+ g_slist_find_custom(logfiles, list[i],
+ (GCompareFunc)g_ascii_strcasecmp) == NULL) {
+ logfiles = g_slist_append (logfiles,
+/* one shell or command per line
+ * one log per line of output
+cp_shell_per_line (FILE *handle)
+ GSList *all_logs = NULL;
+ while ((buf = get_line(handle)) != NULL) {
+ if (g_str_has_prefix (g_strchug (buf), "#")) {
+ if (g_str_has_prefix(g_strchug (buf), "[")) {
+ if (strlen (buf) != 0) {
+ GSList *logfiles = NULL;
+ logfiles = get_logs (buf, cp_logline);
+ for (idx = logfiles; idx; idx=g_slist_next(idx)) {
+ if (g_slist_find_custom (all_logs, idx->data,
+ (GCompareFunc)g_ascii_strcasecmp)
+ all_logs = g_slist_append (all_logs,
+ g_slist_free (logfiles);
+cp_conf_per_line (FILE *handle)
+ GSList *all_logs = NULL;
+ while ((buf = get_line(handle)) != NULL) {
+ if (g_str_has_prefix (g_strchug (buf), "#")) {
+ if (g_str_has_prefix(g_strchug (buf), "[")) {
+ if (strlen (buf) != 0) {
+ GSList *logfiles = NULL;
+ logfiles = get_logs (buf, cp_logconf);
+ for (idx = logfiles; idx; idx=g_slist_next(idx)) {
+ if (g_slist_find_custom (all_logs, idx->data,
+ (GCompareFunc)g_ascii_strcasecmp)
+ all_logs = g_slist_append (all_logs,
+ g_slist_free (logfiles);
+cp_grab_conf (FILE *handle)
+ GSList *all_logs = NULL;
+ /* A line without any categories will be skipped */
+ category = get_line(handle);
+ while (feof (handle) == 0) {
+ if (g_str_has_prefix (g_strchug (category), "#"))
+ if (g_ascii_strcasecmp(g_strstrip(category),
+ LV_INFO ("grab category %s, enter", category);
+ all_logs = g_slist_concat (all_logs,
+ cp_shell_per_line (handle));
+ else if (g_ascii_strcasecmp(g_strstrip(category),
+ LV_INFO ("grab category %s, enter", category);
+ all_logs = g_slist_concat (all_logs,
+ else if (g_ascii_strcasecmp(g_strstrip(category),
+ LV_INFO ("grab category %s, enter", category);
+ all_logs = g_slist_concat (all_logs,
+ cp_conf_per_line (handle));
+ category = get_line(handle);
+get_all_logs (PluginGrabLogs *self)
+ GSList *plugin_paths, *i;
+ GSList *all_logs = NULL;
+ plugin_paths = (GSList *) get_plugin_paths ();
+ for (i = plugin_paths; i; i=g_slist_next(i)) {
+ gchar* path = g_build_path (G_DIR_SEPARATOR_S,
+ i->data, GRABLOGS_CONF, NULL);
+ if (local_file_exist (path)
+ && local_file_can_executed (path)) {
+ GSList *logfiles, *idx;
+ logfiles = get_logs (path, cp_grab_conf);
+ for (idx = logfiles; idx; idx = g_slist_next(idx)) {
+ if (g_slist_find_custom (all_logs, idx->data,
+ (GCompareFunc)g_ascii_strcasecmp) == NULL) {
+ all_logs = g_slist_append (all_logs, idx->data);
+ LV_ERR ("add %s", idx->data);
+ LV_ERR ("del %s", idx->data);
+ g_slist_free (logfiles);
+ /* break to search the sequent path of GRABLOGS_CONF */
+config_child_log (Log *log)
+ /* Check for older versions of the log */
+ gchar *log_name = NULL;
+ g_object_get (G_OBJECT (log), "path", &log_name, NULL);
+ for (i=0; i<OLD_LOG_NUM; i++) {
+ older_name = g_strdup_printf ("%s.%d", log_name, i);
+ if (local_file_exist (older_name)) {
+ older_name = g_strdup_printf ("%s.%
d.gz", log_name, i);
+ if (local_file_exist (older_name)) {
+ child = g_object_new (LOGVIEW_TYPE_LOG,
+ "protocol", file_protocol (older_name),
+ log_set_child (log, i, child);
+config_log_from_path (PluginGrabLogs *self, const gchar *log_path)
+ gchar *utf8_name = NULL;
+ protocol = file_protocol (log_path);
+ log = g_object_new (LOGVIEW_TYPE_LOG,
+ config_child_log (log);
+ utf8_name = locale_to_utf8 (log_path);
+ name = utf8_name ? utf8_name : log_path;
+ message = g_strdup_printf (_("Unknown file type: %d"), protocol);
+ log_error_appendv ("grablogs - %s - %s", name, message);
+iface_init (gpointer g_iface, gpointer iface_data)
+ LogviewInterface *iface = (LogviewInterface*) g_iface;
+ iface->can_handle = NULL; /* dummy */
+collector_init (gpointer g_iface, gpointer iface_data)
+ LogviewIFaceCollector *iface = (LogviewIFaceCollector*) g_iface;
+ iface->get_logs = (GSList* (*) (LogviewICollector*)) get_all_logs;
+ iface->config_log_from_path = (Log* (*) (LogviewICollector*, const gchar*))config_log_from_path;
+LOGVIEW_INIT_PLUGIN (grablogs_get_type)
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#define PLUGIN_PIPELOG(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), PLUGIN_TYPE_PIPELOG, PluginPipelog))
+#define PLUGIN_PIPELOG_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), PLUGIN_TYPE_PIPELOG, PluginPipelogClass))
+#define PIPELOG_IS_PLUGIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), PLUGIN_TYPE_PIPELOG))
+#define PIPELOG_IS_PLUGIN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), PLUGIN_TYPE_PIPELOG))
+#define PLUGIN_PIPELOG_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), PLUGIN_TYPE_PIPELOG, PluginPipelogClass))
+#define PLUGIN_DESC "For non-ASCII formatted log files"
+#define PLUGIN_PRIO (PLUG_PRIO_BASE + 1)
+typedef struct _PluginPipelog PluginPipelog;
+typedef struct _PluginPipelogClass PluginPipelogClass;
+ GnomeVFSFileSize file_size;
+struct _PluginPipelogClass {
+ LogviewPluginClass parent;
+static GObjectClass *parent_class = NULL;
+/* default routines for implement the plugin interfaces */
+static void iface_init (gpointer g_iface, gpointer iface_data);
+static void io_init (gpointer g_iface, gpointer iface_data);
+static gboolean plugin_init (PluginPipelog* self);
+static void plugin_destroy (PluginPipelog* self);
+static gboolean can_handle(PluginPipelog *self, Log *log);
+static gboolean can_monitor(PluginPipelog *self);
+static gboolean has_updated(PluginPipelog *self);
+static gboolean update(PluginPipelog *self);
+static void logf_extract_filepath (PluginPipelog *self, gchar** dirname, gchar** filename);
+static size_t logf_read (PluginPipelog *self, void* buffer, size_t size);
+static off_t logf_seek (PluginPipelog *self, off_t offset, int whence);
+static off_t logf_tell (PluginPipelog *self);
+static time_t get_modified_time (PluginPipelog* self);
+static off_t get_size (PluginPipelog* self);
+static gboolean seek_pipe_log (PluginPipelog* self, const gchar *filename);
+pipelog_finalize (PluginPipelog *self)
+ g_free (self->log_name);
+pipelog_class_init (gpointer g_class, gpointer g_class_data)
+ LogviewPluginClass *parent = LOGVIEW_PLUGIN_CLASS (g_class);
+ parent_class = g_type_class_peek_parent (g_class);
+ G_OBJECT_CLASS (g_class)->finalize = (void (*) (GObject*)) pipelog_finalize;
+ parent->plugin_init = (gboolean (*) (LogviewPlugin*)) plugin_init;
+ parent->plugin_destroy = (void (*) (LogviewPlugin*)) plugin_destroy;
+pipelog_instance_init (GTypeInstance *instance, gpointer g_class_data)
+ self = (PluginPipelog*) instance;
+pipelog_get_type (GTypeModule* module)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (PluginPipelogClass),
+ NULL, /* base_finalize */
+ pipelog_class_init, /* class_init */
+ NULL, /* class_finalize */
+ sizeof (PluginPipelog),
+ pipelog_instance_init /* instance_init */
+ static const GInterfaceInfo iface_info = {
+ iface_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ static const GInterfaceInfo io_info = {
+ io_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ type = g_type_module_register_type (module,
+ g_type_module_add_interface (module, type, LOGVIEW_TYPE_IFACE,
+ g_type_module_add_interface (module, type,
+ LOGVIEW_TYPE_IFACE_IO, &io_info);
+static void load_file (PluginPipelog* self)
+ gint inc = 5*BUFSIZ, p =0, size = 0;
+ self->pbuffer = malloc (inc * sizeof (gchar) + 1);
+ while ((size = fread(self->pbuffer + p,
+ self->file_handle)) == inc) {
+ self->pbuffer = realloc (self->pbuffer, p + inc + 1);
+ *(self->pbuffer + p + size) = '\0';
+ self->psize = p + size;
+plugin_init (PluginPipelog* self)
+ gchar *utf8_name = NULL;
+ self->file_handle = security_popen ((const char *)self->pipe, "r");
+ if (self->file_handle) {
+ name = _("NULL Filename");
+ utf8_name = locale_to_utf8 (self->log_name);
+ name = utf8_name ? utf8_name : self->log_name;
+ log_error_appendv ("pipelog - %s - %s", name, _("popen failed"));
+plugin_destroy (PluginPipelog* self)
+ if (self->file_handle != NULL) {
+ security_pclose (self->file_handle);
+ g_free (self->pbuffer);
+can_handle(PluginPipelog *self, Log *log)
+ gchar *utf8_name = NULL;
+ g_object_get (G_OBJECT (log),
+ "path", &self->log_name,
+ "protocol", &self->protocol,
+ if (self->log_name == NULL) {
+ log_error_appendv ("pipelog - %s", _("NULL Filename"));
+ switch (self->protocol) {
+ if (seek_pipe_log (self, self->log_name)) {
+ self->protocol = PIPE_LOG;
+ g_object_set (G_OBJECT (log),
+ "protocol", self->protocol,
+ utf8_name = locale_to_utf8 (self->log_name);
+ name = (utf8_name) ? (utf8_name) : self->log_name;
+ log_error_appendv ("pipelog - %s - %s", name, _("Cannot open"));
+ utf8_name = locale_to_utf8 (self->log_name);
+ name = (utf8_name) ? (utf8_name) : self->log_name;
+ message = g_strdup_printf (_("Unknown file type: %d"), self->protocol);
+ log_error_appendv ("pipelog - %s - %s", name, message);
+can_monitor(PluginPipelog *self)
+has_updated(PluginPipelog *self)
+update(PluginPipelog *self)
+ g_assert (self->log_name != NULL);
+ if (stat (self->log_name, &buf) == 0) {
+ LV_INFO_EE ("%s stat: %s", self->log_name,
+ error_system_string());
+logf_read (PluginPipelog *self, void* buffer, size_t size)
+ g_assert (size >= 0 && buffer);
+ g_assert (self->psize >=0 && self->pbuffer);
+ g_assert (self->poffset >=0 && self->poffset <= self->psize);
+ lsize = self->psize - self->poffset;
+ bcopy (self->pbuffer, buffer, size * sizeof(gchar));
+logf_seek (PluginPipelog *self, off_t offset, int whence)
+ g_assert (self->psize >=0 && self->pbuffer);
+ g_assert (self->poffset >=0 && self->poffset <= self->psize);
+ self->poffset = offset;
+ self->poffset += offset;
+ self->poffset = self->psize;
+ return logf_tell(self);
+logf_tell (PluginPipelog *self)
+ g_assert (self->psize >=0 && self->pbuffer);
+ g_assert (self->poffset >=0 && self->poffset <= self->psize);
+ return (off_t)self->poffset;
+logf_extract_filepath (PluginPipelog *self, gchar** dirname, gchar** filename)
+ extract_filepath (self->log_name, dirname, filename);
+get_size (PluginPipelog* self)
+ return self->file_size;
+get_modified_time (PluginPipelog* self)
+ return self->file_time;
+io_init (gpointer g_iface, gpointer iface_data)
+ LogviewIFaceIO *iface = (LogviewIFaceIO*)g_iface;
+ iface->can_monitor = (gboolean (*) (LogviewIIO*)) can_monitor;
+ iface->extract_filepath = (void (*) (LogviewIIO*, gchar**, gchar**)) logf_extract_filepath;
+ iface->has_updated = (gboolean (*) (LogviewIIO*)) has_updated;
+ iface->update = (void (*) (LogviewIIO*)) update;
+ iface->read = (size_t (*) (LogviewIIO*, void*, size_t)) logf_read;
+ iface->seek = (off_t (*) (LogviewIIO*, off_t, int)) logf_seek;
+ iface->tell = (off_t (*) (LogviewIIO*)) logf_tell;
+ iface->get_size = (off_t (*) (LogviewIIO*)) get_size;
+ iface->get_modified_time = (time_t (*) (LogviewIIO*)) get_modified_time;
+iface_init (gpointer g_iface, gpointer iface_data)
+ LogviewInterface *iface = (LogviewInterface*)g_iface;
+ iface->can_handle = (gboolean (*) (LogviewIFace*, Log*)) can_handle;
+seek_pipe_log (PluginPipelog* self, const gchar *filename)
+ GSList *plugin_paths, *i;
+ plugin_paths = (GSList *) get_plugin_paths ();
+ for (i = plugin_paths; !hint && i; i=g_slist_next(i)) {
+ gchar* path = g_build_path (G_DIR_SEPARATOR_S, i->data,
+ if (local_file_exist (path)
+ && local_file_can_executed (path)) {
+ FILE *handle = fopen (path, "r");
+ while (!hint && fgets(cbuf, sizeof(cbuf), handle) != NULL) {
+ g_strdelimit (cbuf, "\t\n", ' ');
+ str = g_strchug (cbuf);
+ if (g_str_has_prefix (str, "#"))
+ fp = g_strstr_len (str, strlen (str), filename);
+ self->pipe = g_strdup_printf (
+ g_strstrip(fp + strlen (filename) + 1),
+ LV_INFO ("found pipe log : %s", self->pipe);
+LOGVIEW_INIT_PLUGIN (pipelog_get_type)
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+ * Copyright (C) 2006 Lin Ma <Lin.Ma@sun.com>
+#define PLUGIN_PLAINLOG(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), PLUGIN_TYPE_PLAINLOG, PluginPlainlog))
+#define PLUGIN_PLAINLOG_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), PLUGIN_TYPE_PLAINLOG, PluginPlainlogClass))
+#define PLAINLOG_IS_PLUGIN(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), PLUGIN_TYPE_PLAINLOG))
+#define PLAINLOG_IS_PLUGIN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), PLUGIN_TYPE_PLAINLOG))
+#define PLUGIN_PLAINLOG_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), PLUGIN_TYPE_PLAINLOG, PluginPlainlogClass))
+#define PLUGIN_PRIO PLUG_PRIO_BASE
+#define PLUGIN_DESC "For ASCII formatted log files"
+typedef struct _PluginPlainLog PluginPlainLog;
+typedef struct _PluginPlainLogClass PluginPlainLogClass;
+struct _PluginPlainLog {
+ GnomeVFSFileSize file_size;
+ GnomeVFSHandle *file_handle;
+struct _PluginPlainLogClass {
+ LogviewPluginClass parent;
+static GObjectClass *parent_class = NULL;
+/* default routines for implement the plugin interfaces */
+static void iface_init (gpointer g_iface, gpointer iface_data);
+static void io_init (gpointer g_iface, gpointer iface_data);
+static gboolean plugin_init (PluginPlainLog* self);
+static void plugin_destroy (PluginPlainLog* self);
+static gboolean can_handle(PluginPlainLog *self, Log *log);
+static gboolean can_monitor(PluginPlainLog *self);
+static gboolean has_updated(PluginPlainLog *self);
+static gboolean update(PluginPlainLog *self);
+static void logf_extract_filepath (PluginPlainLog *self, gchar** dirname, gchar** filename);
+static size_t logf_read (PluginPlainLog *self, void* buffer, size_t size);
+static off_t logf_seek (PluginPlainLog *self, off_t offset, int whence);
+static off_t logf_tell (PluginPlainLog *self);
+static time_t get_modified_time (PluginPlainLog* self);
+static off_t get_size (PluginPlainLog* self);
+static gboolean regular_open (PluginPlainLog *self);
+static void regular_close (PluginPlainLog *self);
+plainlog_finalize (PluginPlainLog *self)
+ g_free (self->log_name);
+plainlog_class_init (gpointer g_class, gpointer g_class_data)
+ LogviewPluginClass *parent = LOGVIEW_PLUGIN_CLASS (g_class);
+ parent_class = g_type_class_peek_parent (g_class);
+ G_OBJECT_CLASS (g_class)->finalize = (void (*) (GObject*)) plainlog_finalize;
+ parent->plugin_init = (gboolean (*) (LogviewPlugin*)) plugin_init;
+ parent->plugin_destroy = (void (*) (LogviewPlugin*)) plugin_destroy;
+plainlog_instance_init (GTypeInstance *instance, gpointer g_class_data)
+ self = (PluginPlainLog*) instance;
+plainlog_get_type (GTypeModule* module)
+ static const GTypeInfo info = {
+ /* You fill this structure. */
+ sizeof (PluginPlainLogClass),
+ NULL, /* base_finalize */
+ plainlog_class_init, /* class_init */
+ NULL, /* class_finalize */
+ sizeof (PluginPlainLog),
+ plainlog_instance_init /* instance_init */
+ static const GInterfaceInfo iface_info = {
+ iface_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ static const GInterfaceInfo io_info = {
+ io_init, /* interface_init */
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ type = g_type_module_register_type (module,
+ g_type_module_add_interface (module, type, LOGVIEW_TYPE_IFACE,
+ g_type_module_add_interface (module, type, LOGVIEW_TYPE_IFACE_IO,
+plugin_init (PluginPlainLog* self)
+ gchar *utf8_name = NULL;
+ if (regular_open (self))
+ utf8_name = locale_to_utf8 (self->log_name);
+ name = utf8_name ? utf8_name : self->log_name;
+ log_error_appendv ("plainlog - %s - %s", name, _("Cannot open"));
+plugin_destroy (PluginPlainLog* self)
+ if (self->file_handle != NULL) {
+can_handle(PluginPlainLog *self, Log *log)
+ gchar *utf8_name = NULL;
+ g_object_get (G_OBJECT (log),
+ "path", &self->log_name,
+ "protocol", &self->protocol,
+ if (self->log_name == NULL) {
+ log_error_appendv ("plainlog - %s", _("NULL Filename"));
+ if (self->protocol == PLAIN_LOG ||
+ self->protocol == GZIP_LOG) {
+ } else if (self->protocol == UNKNOWN_LOG) {
+ if (try_to_open (self->log_name, FALSE)) {
+ self->protocol = PLAIN_LOG;
+ g_object_set (G_OBJECT (log),
+ "protocol", self->protocol,
+ utf8_name = locale_to_utf8 (self->log_name);
+ name = utf8_name ? utf8_name : self->log_name;
+ log_error_appendv ("plainlog - %s - %s", name, _("Cannot open"));
+ utf8_name = locale_to_utf8 (self->log_name);
+ name = utf8_name ? utf8_name : self->log_name;
+ message = g_strdup_printf (_("Unknown file type: %d"), self->protocol);
+ log_error_appendv ("plainlog - %s - %s", name, message);
+can_monitor(PluginPlainLog *self)
+ switch (self->protocol) {
+has_updated(PluginPlainLog *self)
+ if (stat (self->log_name, &buf) == 0) {
+ LV_INFO_EE ("%s stat: %s", self->log_name,
+ error_system_string());
+update(PluginPlainLog *self)
+ g_assert (self->log_name != NULL);
+ if (stat (self->log_name, &buf) == 0) {
+ LV_INFO_EE ("%s stat: %s", self->log_name,
+ error_system_string());
+logf_read (PluginPlainLog *self, void* buffer, size_t size)
+ GnomeVFSFileSize read_size;
+ g_return_val_if_fail (self->file_handle !=NULL, -1);
+ result = gnome_vfs_read (self->file_handle,
+ (GnomeVFSFileSize)size,
+ if ( result != GNOME_VFS_OK) {
+ LV_INFO_EE ("%s: (%d), %s",
+ result, gnome_vfs_result_to_string (result));
+ return (size_t)read_size;
+logf_seek (PluginPlainLog *self, off_t offset, int whence)
+ GnomeVFSSeekPosition sp;
+ sp = GNOME_VFS_SEEK_START;
+ sp = GNOME_VFS_SEEK_CURRENT;
+ sp = GNOME_VFS_SEEK_END;
+ if (gnome_vfs_seek (self->file_handle, sp, (GnomeVFSFileOffset)offset) == GNOME_VFS_OK) {
+ return logf_tell(self);
+logf_tell (PluginPlainLog *self)
+ if (gnome_vfs_tell (self->file_handle, &size) == GNOME_VFS_OK) {
+logf_extract_filepath (PluginPlainLog *self, gchar** dirname, gchar** filename)
+ extract_filepath (self->log_name, dirname, filename);
+get_size (PluginPlainLog* self)
+ return self->file_size;
+get_modified_time (PluginPlainLog* self)
+ return self->file_time;
+io_init (gpointer g_iface, gpointer iface_data)
+ LogviewIFaceIO *iface = (LogviewIFaceIO*) g_iface;
+ iface->can_monitor = (gboolean (*) (LogviewIIO*)) can_monitor;
+ iface->extract_filepath = (void (*) (LogviewIIO*, gchar**, gchar**)) logf_extract_filepath;
+ iface->has_updated = (gboolean (*) (LogviewIIO*)) has_updated;
+ iface->update = (void (*) (LogviewIIO*)) update;
+ iface->read = (size_t (*) (LogviewIIO*, void*, size_t)) logf_read;
+ iface->seek = (off_t (*) (LogviewIIO*, off_t, int)) logf_seek;
+ iface->tell = (off_t (*) (LogviewIIO*)) logf_tell;
+ iface->get_size = (off_t (*) (LogviewIIO*)) get_size;
+ iface->get_modified_time = (time_t (*) (LogviewIIO*)) get_modified_time;
+iface_init (gpointer g_iface, gpointer iface_data)
+ LogviewInterface *iface = (LogviewInterface*)g_iface;
+ iface->can_handle = (gboolean (*) (LogviewIFace*, Log*)) can_handle;
+regular_open (PluginPlainLog *self)
+ if (self->protocol == GZIP_LOG) {
+ file_name = g_strdup_printf ("%s#gzip:", self->log_name);
+ file_name = g_strdup (self->log_name);
+ result = gnome_vfs_open (&self->file_handle,
+ file_name, GNOME_VFS_OPEN_READ);
+ if (result != GNOME_VFS_OK) {
+ LV_INFO_EE ("%s: (%d), %s",
+ result, gnome_vfs_result_to_string (result));
+ self->file_handle = NULL;
+regular_close (PluginPlainLog *self)
+ result = gnome_vfs_close (self->file_handle);
+ if (result != GNOME_VFS_OK) {
+ LV_INFO_EE ("%s: (%d), %s",
+ result, gnome_vfs_result_to_string (result));
+LOGVIEW_INIT_PLUGIN (plainlog_get_type)
index c205a6d..35419f5 100644
#define LOGVIEW_DEFAULT_HEIGHT 400
#define LOGVIEW_DEFAULT_WIDTH 600
static GConfClient *gconf_client = NULL;
-parse_syslog(gchar *syslog_file) {
- /* Most of this stolen from sysklogd sources */
- GSList *logfiles = NULL;
- if ((cf = fopen(syslog_file, "r")) == NULL) {
- while (fgets(cline, sizeof(cbuf) - (cline - cbuf), cf) != NULL) {
- for (p = cline; g_ascii_isspace(*p); ++p);
- if (*p == '\0' || *p == '#' || *p == '\n')
- list = g_strsplit_set (p, ", -\t()\n", 0);
- for (i = 0; list[i]; ++i) {
- g_slist_find_custom(logfiles, list[i],
- (GCompareFunc)g_ascii_strcasecmp) == NULL) {
- logfiles = g_slist_insert (logfiles,
prefs_create_defaults (UserPrefs *p)
- GnomeVFSHandle *handle;
- /* For first time running, try parsing various logfiles */
+ g_assert (p->logs == NULL);
+ p->logs = pluginmgr_get_all_logs ();
- if (result == GNOME_VFS_OK) {
- gnome_vfs_close (handle);
- for (i=0; logfiles[i]; i++) {
- if (g_slist_find_custom(logs, logfiles[i], (GCompareFunc)g_ascii_strcasecmp) == NULL &&
- file_is_log (logfiles[i], FALSE))
- logs = g_slist_insert (logs, g_strdup(logfiles[i]), 0);
- p->logfile = logs->data;
+ for (idx = p->logs; idx != NULL; idx = idx->next) {
+ LV_ERR ("add|log: %s", (gchar*) idx->data);
@@ -159,22 +85,23 @@ prefs_load (void)
prefs_create_defaults (p);
+ p->logfile = p->logs->data;
logfile = gconf_client_get_string (gconf_client, GCONF_LOGFILE, NULL);
- if (logfile && logfile[0] != '\0' && file_is_log (logfile, FALSE)) {
+ if (logfile && logfile[0] != '\0') {
- p->logfile = g_strdup (logfile);
- for (found = FALSE, iter = p->logs;
+ for (iter = p->logs; iter != NULL;
iter = g_slist_next (iter)) {
- if (g_ascii_strncasecmp (iter->data, p->logfile, 255) == 0)
+ if (g_ascii_strncasecmp (iter->data,
+ p->logfile = iter->data;
width = gconf_client_get_int (gconf_client, GCONF_WIDTH_KEY, NULL);
@@ -184,6 +111,7 @@ prefs_load (void)
p->width = (width == 0 ? LOGVIEW_DEFAULT_WIDTH : width);
p->height = (height == 0 ? LOGVIEW_DEFAULT_HEIGHT : height);
+ p->logfile = g_strdup (p->logfile);
@@ -260,22 +188,38 @@ prefs_get_height (void)
- g_slist_free (prefs->logs);
+ for (idx = prefs->logs; idx; idx = g_slist_next(idx)) {
+ g_free ((gchar*)idx->data);
+ g_slist_free (prefs->logs);
+ g_free (prefs->logfile);
-prefs_store_log (gchar *name)
+prefs_store_log (const gchar *name)
+ LV_INFO ("[Prefs Store] %s", name);
if (name && name[0] != '\0')
- prefs->logs = g_slist_append (prefs->logs, name);
+ prefs->logs = g_slist_append (prefs->logs, g_strdup (name));
-prefs_store_active_log (gchar *name)
+prefs_store_active_log (const gchar *name)
/* name can be NULL if no active log */
+ g_free (prefs->logfile);
+ prefs->logfile = g_strdup(name);
@@ -287,8 +231,6 @@ prefs_store_fontsize (int fontsize)
g_assert (gconf_client != NULL);
index 1cf10fb..174165e 100644
@@ -33,8 +33,8 @@ gchar *prefs_get_active_log (void);
GSList *prefs_get_logs (void);
int prefs_get_width (void);
int prefs_get_height (void);
-void prefs_store_log (gchar *name);
-void prefs_store_active_log (gchar *name);
+void prefs_store_log (const gchar *name);
+void prefs_store_active_log (const gchar *name);
void prefs_store_fontsize (int fontsize);
void prefs_store_window_size (GtkWidget *window);