/* * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) version 3. * * 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the program; if not, see * * * Authors: * Jeffrey Stedfast * Michael Zucchi * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "filter-label.h" #include #include "e-util/e-util.h" #include "e-util/e-util-labels.h" #define d(x) static void xml_create (FilterElement *fe, xmlNodePtr node); static void filter_label_class_init (FilterLabelClass *klass); static void filter_label_init (FilterLabel *label); static void filter_label_finalise (GObject *obj); static FilterElementClass *parent_class; GType filter_label_get_type (void) { static GType type = 0; if (!type) { static const GTypeInfo info = { sizeof (FilterLabelClass), NULL, /* base_class_init */ NULL, /* base_class_finalize */ (GClassInitFunc) filter_label_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (FilterLabel), 0, /* n_preallocs */ (GInstanceInitFunc) filter_label_init, }; type = g_type_register_static (FILTER_TYPE_OPTION, "FilterLabel", &info, 0); } return type; } static GStaticRecMutex cache_lock = G_STATIC_REC_MUTEX_INIT; static guint cache_notifier_id = 0; static GSList *tracked_filters = NULL; static GSList *labels_cache = NULL; static GConfClient *gconf_client = NULL; static void fill_cache (void); static void clear_cache (void); static void gconf_labels_changed (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data); static void filter_label_class_init (FilterLabelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); FilterElementClass *fe_class = FILTER_ELEMENT_CLASS (klass); parent_class = g_type_class_ref (FILTER_TYPE_OPTION); object_class->finalize = filter_label_finalise; /* override methods */ fe_class->xml_create = xml_create; } static void filter_label_init (FilterLabel *fl) { ((FilterOption *) fl)->type = "label"; g_static_rec_mutex_lock (&cache_lock); if (!tracked_filters) { fill_cache (); gconf_client = gconf_client_get_default (); gconf_client_add_dir (gconf_client, E_UTIL_LABELS_GCONF_KEY, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); cache_notifier_id = gconf_client_notify_add (gconf_client, E_UTIL_LABELS_GCONF_KEY, gconf_labels_changed, NULL, NULL, NULL); } tracked_filters = g_slist_prepend (tracked_filters, fl); g_static_rec_mutex_unlock (&cache_lock); } static void filter_label_finalise (GObject *obj) { G_OBJECT_CLASS (parent_class)->finalize (obj); g_static_rec_mutex_lock (&cache_lock); tracked_filters = g_slist_remove (tracked_filters, obj); if (!tracked_filters) { clear_cache (); if (cache_notifier_id) gconf_client_notify_remove (gconf_client, cache_notifier_id); cache_notifier_id = 0; g_object_unref (gconf_client); gconf_client = NULL; } g_static_rec_mutex_unlock (&cache_lock); } /** * filter_label_new: * * Create a new FilterLabel object. * * Return value: A new #FilterLabel object. **/ FilterLabel * filter_label_new (void) { return (FilterLabel *) g_object_new (FILTER_TYPE_LABEL, NULL, NULL); } /* ************************************************************************* */ /* should already hold the lock when calling this function */ static void fill_cache (void) { labels_cache = e_util_labels_parse (NULL); } /* should already hold the lock when calling this function */ static void clear_cache (void) { e_util_labels_free (labels_cache); labels_cache = NULL; } static void fill_options (FilterOption *fo) { GSList *l; g_static_rec_mutex_lock (&cache_lock); for (l = labels_cache; l; l = l->next) { EUtilLabel *label = l->data; const char *tag; char *title; if (!label) continue; title = e_str_without_underscores (label->name); tag = label->tag; if (tag && strncmp (tag, "$Label", 6) == 0) tag += 6; filter_option_add (fo, tag, title, NULL); g_free (title); } g_static_rec_mutex_unlock (&cache_lock); } static void regen_label_options (FilterOption *fo) { char *current; if (!fo) return; current = g_strdup (filter_option_get_current (fo)); filter_option_remove_all (fo); fill_options (fo); if (current) filter_option_set_current (fo, current); g_free (current); } static void gconf_labels_changed (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data) { g_static_rec_mutex_lock (&cache_lock); clear_cache (); fill_cache (); g_slist_foreach (tracked_filters, (GFunc)regen_label_options, NULL); g_static_rec_mutex_unlock (&cache_lock); } /* ************************************************************************* */ int filter_label_count (void) { int res; g_static_rec_mutex_lock (&cache_lock); res = g_slist_length (labels_cache); g_static_rec_mutex_unlock (&cache_lock); return res; } const char * filter_label_label (int i) { const char *res = NULL; GSList *l; EUtilLabel *label; g_static_rec_mutex_lock (&cache_lock); l = g_slist_nth (labels_cache, i); if (l) label = l->data; else label = NULL; if (label && label->tag) { if (strncmp (label->tag, "$Label", 6) == 0) res = label->tag + 6; else res = label->tag; } g_static_rec_mutex_unlock (&cache_lock); return res; } int filter_label_index (const char *label) { int i; GSList *l; g_static_rec_mutex_lock (&cache_lock); for (i = 0, l = labels_cache; l; i++, l = l->next) { EUtilLabel *lbl = l->data; const char *tag = lbl->tag; if (tag && strncmp (tag, "$Label", 6) == 0) tag += 6; if (tag && strcmp (tag, label) == 0) break; } g_static_rec_mutex_unlock (&cache_lock); if (l) return i; return -1; } static void xml_create (FilterElement *fe, xmlNodePtr node) { FILTER_ELEMENT_CLASS (parent_class)->xml_create (fe, node); fill_options ((FilterOption *) fe); }