diff options
Diffstat (limited to 'logview/logview-prefs.c')
-rw-r--r-- | logview/logview-prefs.c | 630 |
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", ®ex, + "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); +} + |