summaryrefslogtreecommitdiff
path: root/logview/logview-prefs.c
diff options
context:
space:
mode:
Diffstat (limited to 'logview/logview-prefs.c')
-rw-r--r--logview/logview-prefs.c630
1 files changed, 630 insertions, 0 deletions
diff --git a/logview/logview-prefs.c b/logview/logview-prefs.c
new file mode 100644
index 00000000..2ce0aa81
--- /dev/null
+++ b/logview/logview-prefs.c
@@ -0,0 +1,630 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* logview-prefs.c - logview user preferences handling
+ *
+ * Copyright (C) 1998 Cesar Miquel <[email protected]>
+ * Copyright (C) 2004 Vincent Noel
+ * Copyright (C) 2006 Emmanuele Bassi
+ * Copyright (C) 2008 Cosimo Cecchi <[email protected]>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <mateconf/mateconf-client.h>
+
+#include "logview-prefs.h"
+
+#define LOGVIEW_DEFAULT_HEIGHT 400
+#define LOGVIEW_DEFAULT_WIDTH 600
+
+/* logview settings */
+#define MATECONF_DIR "/apps/mate-system-log"
+#define MATECONF_WIDTH_KEY MATECONF_DIR "/width"
+#define MATECONF_HEIGHT_KEY MATECONF_DIR "/height"
+#define MATECONF_LOGFILE MATECONF_DIR "/logfile"
+#define MATECONF_LOGFILES MATECONF_DIR "/logfiles"
+#define MATECONF_FONTSIZE_KEY MATECONF_DIR "/fontsize"
+#define MATECONF_FILTERS MATECONF_DIR "/filters"
+
+/* desktop-wide settings */
+#define MATECONF_MONOSPACE_FONT_NAME "/desktop/mate/interface/monospace_font_name"
+#define MATECONF_MENUS_HAVE_TEAROFF "/desktop/mate/interface/menus_have_tearoff"
+
+static LogviewPrefs *singleton = NULL;
+
+enum {
+ SYSTEM_FONT_CHANGED,
+ HAVE_TEAROFF_CHANGED,
+ LAST_SIGNAL
+};
+
+enum {
+ FILTER_NAME,
+ FILTER_INVISIBLE,
+ FILTER_FOREGROUND,
+ FILTER_BACKGROUND,
+ FILTER_REGEX,
+ MAX_TOKENS
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+#define GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOGVIEW_TYPE_PREFS, LogviewPrefsPrivate))
+
+struct _LogviewPrefsPrivate {
+ MateConfClient *client;
+
+ guint size_store_timeout;
+
+ GHashTable *filters;
+};
+
+typedef struct {
+ int width;
+ int height;
+} WindowSize;
+
+G_DEFINE_TYPE (LogviewPrefs, logview_prefs, G_TYPE_OBJECT);
+
+static void
+do_finalize (GObject *obj)
+{
+ LogviewPrefs *prefs = LOGVIEW_PREFS (obj);
+
+ g_hash_table_destroy (prefs->priv->filters);
+
+ g_object_unref (prefs->priv->client);
+
+ G_OBJECT_CLASS (logview_prefs_parent_class)->finalize (obj);
+}
+
+static void
+logview_prefs_class_init (LogviewPrefsClass *klass)
+{
+ GObjectClass *oclass = G_OBJECT_CLASS (klass);
+
+ oclass->finalize = do_finalize;
+
+ signals[SYSTEM_FONT_CHANGED] = g_signal_new ("system-font-changed",
+ G_OBJECT_CLASS_TYPE (oclass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LogviewPrefsClass, system_font_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+ signals[HAVE_TEAROFF_CHANGED] = g_signal_new ("have-tearoff-changed",
+ G_OBJECT_CLASS_TYPE (oclass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LogviewPrefsClass, have_tearoff_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1,
+ G_TYPE_BOOLEAN);
+
+ g_type_class_add_private (klass, sizeof (LogviewPrefsPrivate));
+}
+
+static void
+have_tearoff_changed_cb (MateConfClient *client,
+ guint id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ LogviewPrefs *prefs = data;
+
+ if (entry->value && (entry->value->type == MATECONF_VALUE_BOOL)) {
+ gboolean add_tearoffs;
+
+ add_tearoffs = mateconf_value_get_bool (entry->value);
+ g_signal_emit (prefs, signals[HAVE_TEAROFF_CHANGED], 0, add_tearoffs, NULL);
+ }
+}
+
+static void
+monospace_font_changed_cb (MateConfClient *client,
+ guint id,
+ MateConfEntry *entry,
+ gpointer data)
+{
+ LogviewPrefs *prefs = data;
+
+ if (entry->value && (entry->value->type == MATECONF_VALUE_STRING)) {
+ const gchar *monospace_font_name;
+
+ monospace_font_name = mateconf_value_get_string (entry->value);
+ g_signal_emit (prefs, signals[SYSTEM_FONT_CHANGED], 0, monospace_font_name, NULL);
+ }
+}
+
+static gboolean
+size_store_timeout_cb (gpointer data)
+{
+ WindowSize *size = data;
+ LogviewPrefs *prefs = logview_prefs_get ();
+
+ if (size->width > 0 && size->height > 0) {
+ if (mateconf_client_key_is_writable (prefs->priv->client, MATECONF_WIDTH_KEY, NULL))
+ mateconf_client_set_int (prefs->priv->client,
+ MATECONF_WIDTH_KEY,
+ size->width,
+ NULL);
+
+ if (mateconf_client_key_is_writable (prefs->priv->client, MATECONF_HEIGHT_KEY, NULL))
+ mateconf_client_set_int (prefs->priv->client,
+ MATECONF_HEIGHT_KEY,
+ size->height,
+ NULL);
+ }
+
+ /* reset the source id */
+ prefs->priv->size_store_timeout = 0;
+
+ g_free (size);
+
+ return FALSE;
+}
+
+#define DELIMITER ":"
+
+static void
+load_filters (LogviewPrefs *prefs)
+{
+ GSList *node;
+ GSList *filters;
+ gchar **tokens;
+ LogviewFilter *filter;
+ GtkTextTag *tag;
+ GdkColor color;
+
+ filters = mateconf_client_get_list (prefs->priv->client,
+ MATECONF_FILTERS,
+ MATECONF_VALUE_STRING,
+ NULL);
+
+ prefs->priv->filters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+
+ for (node = filters; node != NULL; node = g_slist_next (node)) {
+ tokens = g_strsplit (node->data, DELIMITER, MAX_TOKENS);
+ filter = logview_filter_new (tokens[FILTER_NAME], tokens[FILTER_REGEX]);
+ tag = gtk_text_tag_new (tokens[FILTER_NAME]);
+
+ g_object_set (tag, "invisible",
+ g_str_equal (tokens[FILTER_INVISIBLE], "1"), NULL);
+
+ if (strlen (tokens[FILTER_FOREGROUND])) {
+ gdk_color_parse (tokens[FILTER_FOREGROUND], &color);
+ g_object_set (tag, "foreground-gdk", &color,
+ "foreground-set", TRUE, NULL);
+ }
+
+ if (strlen (tokens[FILTER_BACKGROUND])) {
+ gdk_color_parse (tokens[FILTER_BACKGROUND], &color);
+ g_object_set (tag, "paragraph-background-gdk", &color,
+ "paragraph-background-set", TRUE, NULL);
+ }
+
+ g_object_set (filter, "texttag", tag, NULL);
+ g_hash_table_insert (prefs->priv->filters,
+ g_strdup(tokens[FILTER_NAME]),
+ filter);
+
+ g_object_ref (filter);
+ g_object_unref (tag);
+ g_strfreev (tokens);
+ }
+
+ g_slist_foreach (filters, (GFunc) g_free, NULL);
+ g_slist_free (filters);
+}
+
+static void
+save_filter_foreach_func (gpointer key, gpointer value, gpointer user_data)
+{
+ GSList **filters;
+ const gchar *name;
+ LogviewFilter *filter;
+ GdkColor *foreground;
+ gboolean foreground_set;
+ GdkColor *background;
+ gboolean background_set;
+ gchar *regex, *color;
+ gboolean invisible;
+ GtkTextTag *tag;
+ GString *prefs_string;
+
+ filters = user_data;
+ filter = LOGVIEW_FILTER (value);
+ name = key;
+ color = NULL;
+
+ prefs_string = g_string_new (name);
+ g_string_append (prefs_string, DELIMITER);
+
+ g_object_get (filter,
+ "regex", &regex,
+ "texttag", &tag,
+ NULL);
+ g_object_get (tag,
+ "foreground-gdk", &foreground,
+ "paragraph-background-gdk", &background,
+ "foreground-set", &foreground_set,
+ "paragraph-background-set", &background_set,
+ "invisible", &invisible, NULL);
+
+ if (invisible) {
+ g_string_append (prefs_string, "1" DELIMITER);
+ } else {
+ g_string_append (prefs_string, "0" DELIMITER);
+ }
+
+ if (foreground_set) {
+ color = gdk_color_to_string (foreground);
+ g_string_append (prefs_string, color);
+ g_free (color);
+ }
+
+ if (foreground) {
+ gdk_color_free (foreground);
+ }
+
+ g_string_append (prefs_string, DELIMITER);
+
+ if (background_set) {
+ color = gdk_color_to_string (background);
+ g_string_append (prefs_string, color);
+ g_free (color);
+ }
+
+ if (background) {
+ gdk_color_free (background);
+ }
+
+ g_string_append (prefs_string, DELIMITER);
+ g_string_append (prefs_string, regex);
+
+ g_free (regex);
+ g_object_unref (tag);
+
+ *filters = g_slist_prepend (*filters, g_string_free (prefs_string, FALSE));
+}
+
+static void
+save_filters (LogviewPrefs *prefs)
+{
+ GSList *filters;
+
+ filters = NULL;
+
+ g_hash_table_foreach (prefs->priv->filters,
+ save_filter_foreach_func,
+ &filters);
+ mateconf_client_set_list (prefs->priv->client,
+ MATECONF_FILTERS,
+ MATECONF_VALUE_STRING,
+ filters, NULL);
+
+ g_slist_foreach (filters, (GFunc) g_free, NULL);
+ g_slist_free (filters);
+}
+
+static void
+get_filters_foreach (gpointer key, gpointer value, gpointer user_data)
+{
+ GList **list;
+ list = user_data;
+ *list = g_list_append (*list, value);
+}
+
+static void
+logview_prefs_init (LogviewPrefs *self)
+{
+ LogviewPrefsPrivate *priv;
+
+ priv = self->priv = GET_PRIVATE (self);
+
+ priv->client = mateconf_client_get_default ();
+ priv->size_store_timeout = 0;
+
+ mateconf_client_notify_add (priv->client,
+ MATECONF_MONOSPACE_FONT_NAME,
+ (MateConfClientNotifyFunc) monospace_font_changed_cb,
+ self, NULL, NULL);
+ mateconf_client_notify_add (priv->client,
+ MATECONF_MENUS_HAVE_TEAROFF,
+ (MateConfClientNotifyFunc) have_tearoff_changed_cb,
+ self, NULL, NULL);
+
+ load_filters (self);
+}
+
+/* public methods */
+
+LogviewPrefs *
+logview_prefs_get ()
+{
+ if (!singleton)
+ singleton = g_object_new (LOGVIEW_TYPE_PREFS, NULL);
+
+ return singleton;
+}
+
+void
+logview_prefs_store_window_size (LogviewPrefs *prefs,
+ int width, int height)
+{
+ /* we want to be smart here: since we will get a lot of configure events
+ * while resizing, we schedule the real MateConf storage in a timeout.
+ */
+ WindowSize *size;
+
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ size = g_new0 (WindowSize, 1);
+ size->width = width;
+ size->height = height;
+
+ if (prefs->priv->size_store_timeout != 0) {
+ /* reschedule the timeout */
+ g_source_remove (prefs->priv->size_store_timeout);
+ prefs->priv->size_store_timeout = 0;
+ }
+
+ prefs->priv->size_store_timeout = g_timeout_add (200,
+ size_store_timeout_cb,
+ size);
+}
+
+void
+logview_prefs_get_stored_window_size (LogviewPrefs *prefs,
+ int *width, int *height)
+{
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ *width = mateconf_client_get_int (prefs->priv->client,
+ MATECONF_WIDTH_KEY,
+ NULL);
+
+ *height = mateconf_client_get_int (prefs->priv->client,
+ MATECONF_HEIGHT_KEY,
+ NULL);
+
+ if ((*width == 0) ^ (*height == 0)) {
+ /* if one of the two failed, return default for both */
+ *width = LOGVIEW_DEFAULT_WIDTH;
+ *height = LOGVIEW_DEFAULT_HEIGHT;
+ }
+}
+
+char *
+logview_prefs_get_monospace_font_name (LogviewPrefs *prefs)
+{
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ return (mateconf_client_get_string (prefs->priv->client, MATECONF_MONOSPACE_FONT_NAME, NULL));
+}
+
+gboolean
+logview_prefs_get_have_tearoff (LogviewPrefs *prefs)
+{
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ return (mateconf_client_get_bool (prefs->priv->client, MATECONF_MENUS_HAVE_TEAROFF, NULL));
+}
+
+/* the elements should be freed with g_free () */
+
+GSList *
+logview_prefs_get_stored_logfiles (LogviewPrefs *prefs)
+{
+ GSList *retval;
+
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ retval = mateconf_client_get_list (prefs->priv->client,
+ MATECONF_LOGFILES,
+ MATECONF_VALUE_STRING,
+ NULL);
+ return retval;
+}
+
+void
+logview_prefs_store_log (LogviewPrefs *prefs, GFile *file)
+{
+ GSList *stored_logs, *l;
+ GFile *stored;
+ gboolean found = FALSE;
+
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+ g_assert (G_IS_FILE (file));
+
+ stored_logs = logview_prefs_get_stored_logfiles (prefs);
+
+ for (l = stored_logs; l; l = l->next) {
+ stored = g_file_parse_name (l->data);
+ if (g_file_equal (file, stored)) {
+ found = TRUE;
+ }
+
+ g_object_unref (stored);
+
+ if (found) {
+ break;
+ }
+ }
+
+ if (!found) {
+ stored_logs = g_slist_prepend (stored_logs, g_file_get_parse_name (file));
+ mateconf_client_set_list (prefs->priv->client,
+ MATECONF_LOGFILES,
+ MATECONF_VALUE_STRING,
+ stored_logs,
+ NULL);
+ }
+
+ /* the string list is copied */
+ g_slist_foreach (stored_logs, (GFunc) g_free, NULL);
+ g_slist_free (stored_logs);
+}
+
+void
+logview_prefs_remove_stored_log (LogviewPrefs *prefs, GFile *target)
+{
+ GSList *stored_logs, *l, *removed = NULL;
+ GFile *stored;
+
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+ g_assert (G_IS_FILE (target));
+
+ stored_logs = logview_prefs_get_stored_logfiles (prefs);
+
+ for (l = stored_logs; l; l = l->next) {
+ stored = g_file_parse_name (l->data);
+ if (g_file_equal (stored, target)) {
+ removed = l;
+ stored_logs = g_slist_remove_link (stored_logs, l);
+ }
+
+ g_object_unref (stored);
+
+ if (removed) {
+ break;
+ }
+ }
+
+ if (removed) {
+ mateconf_client_set_list (prefs->priv->client,
+ MATECONF_LOGFILES,
+ MATECONF_VALUE_STRING,
+ stored_logs,
+ NULL);
+ }
+
+ /* the string list is copied */
+ g_slist_foreach (stored_logs, (GFunc) g_free, NULL);
+ g_slist_free (stored_logs);
+
+ if (removed) {
+ g_free (removed->data);
+ g_slist_free (removed);
+ }
+}
+
+void
+logview_prefs_store_fontsize (LogviewPrefs *prefs, int fontsize)
+{
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+ g_assert (fontsize > 0);
+
+ if (mateconf_client_key_is_writable (prefs->priv->client, MATECONF_FONTSIZE_KEY, NULL)) {
+ mateconf_client_set_int (prefs->priv->client,
+ MATECONF_FONTSIZE_KEY,
+ fontsize, NULL);
+ }
+}
+
+int
+logview_prefs_get_stored_fontsize (LogviewPrefs *prefs)
+{
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ return mateconf_client_get_int (prefs->priv->client, MATECONF_FONTSIZE_KEY, NULL);
+}
+
+void
+logview_prefs_store_active_logfile (LogviewPrefs *prefs,
+ const char *filename)
+{
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ if (mateconf_client_key_is_writable (prefs->priv->client, MATECONF_LOGFILE, NULL)) {
+ mateconf_client_set_string (prefs->priv->client,
+ MATECONF_LOGFILE,
+ filename,
+ NULL);
+ }
+}
+
+char *
+logview_prefs_get_active_logfile (LogviewPrefs *prefs)
+{
+ char *filename;
+
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ filename = mateconf_client_get_string (prefs->priv->client, MATECONF_LOGFILE, NULL);
+
+ return filename;
+}
+
+GList *
+logview_prefs_get_filters (LogviewPrefs *prefs)
+{
+ GList *filters = NULL;
+
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ g_hash_table_foreach (prefs->priv->filters,
+ get_filters_foreach,
+ &filters);
+
+ return filters;
+}
+
+void
+logview_prefs_remove_filter (LogviewPrefs *prefs,
+ const gchar *name)
+{
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ g_hash_table_remove (prefs->priv->filters,
+ name);
+
+ save_filters (prefs);
+}
+
+void
+logview_prefs_add_filter (LogviewPrefs *prefs,
+ LogviewFilter *filter)
+{
+ gchar* name;
+
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+ g_assert (LOGVIEW_IS_FILTER (filter));
+
+ g_object_get (filter, "name", &name, NULL);
+ g_hash_table_insert (prefs->priv->filters, name, g_object_ref (filter));
+
+ save_filters (prefs);
+}
+
+LogviewFilter *
+logview_prefs_get_filter (LogviewPrefs *prefs,
+ const gchar *name)
+{
+ g_assert (LOGVIEW_IS_PREFS (prefs));
+
+ return g_hash_table_lookup (prefs->priv->filters, name);
+}
+