diff options
Diffstat (limited to 'filter')
-rw-r--r-- | filter/ChangeLog | 11 | ||||
-rw-r--r-- | filter/filter-label.c | 217 | ||||
-rw-r--r-- | filter/filter-option.c | 23 | ||||
-rw-r--r-- | filter/filter-option.h | 3 |
4 files changed, 208 insertions, 46 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog index 95e18e332b..cff5724f0a 100644 --- a/filter/ChangeLog +++ b/filter/ChangeLog @@ -1,3 +1,14 @@ +2008-01-10 Milan Crha <mcrha@redhat.com> + + ** Fix for bug #211353 + + * filter-option.h: + * filter-option.c: (filter_option_get_current), + (filter_option_remove_all): New functions to be able to refill options + even after initialization of the filter element. + * filter-label.c: Added support to notify changes on labels in runtime + and use actual labels. + 2007-12-17 Srinivasa Ragavan <sragavan@novell.com> * filter-label.c: (filter_label_count), (filter_label_label), diff --git a/filter/filter-label.c b/filter/filter-label.c index ca0ae005fe..d2d67baecd 100644 --- a/filter/filter-label.c +++ b/filter/filter-label.c @@ -38,6 +38,7 @@ #include "filter-label.h" #include <libedataserver/e-sexp.h> #include "e-util/e-util.h" +#include "e-util/e-util-labels.h" #define d(x) @@ -47,10 +48,8 @@ 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) { @@ -75,6 +74,16 @@ filter_label_get_type (void) return type; } +static GStaticMutex cache_lock = G_STATIC_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) { @@ -93,12 +102,43 @@ static void filter_label_init (FilterLabel *fl) { ((FilterOption *) fl)->type = "label"; + + g_static_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_mutex_unlock (&cache_lock); } static void filter_label_finalise (GObject *obj) { G_OBJECT_CLASS (parent_class)->finalize (obj); + + g_static_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_mutex_unlock (&cache_lock); } /** @@ -114,72 +154,157 @@ filter_label_new (void) return (FilterLabel *) g_object_new (FILTER_TYPE_LABEL, NULL, NULL); } -static struct { - char *title; - char *value; -} labels[] = { - { N_("Important"), "important" }, - { N_("Work"), "work" }, - { N_("Personal"), "personal" }, - { N_("To Do"), "todo" }, - { N_("Later"), "later" }, -}; - -int filter_label_count (void) +/* ************************************************************************* */ + +/* 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_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_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_mutex_lock (&cache_lock); + clear_cache (); + fill_cache (); + g_static_mutex_unlock (&cache_lock); + + g_slist_foreach (tracked_filters, (GFunc)regen_label_options, NULL); +} + +/* ************************************************************************* */ + +int +filter_label_count (void) { - return sizeof (labels) / sizeof (labels[0]); + int res; + + g_static_mutex_lock (&cache_lock); + + res = g_slist_length (labels_cache); + + g_static_mutex_unlock (&cache_lock); + + return res; } const char * filter_label_label (int i) { - if (i < 0 || i >= sizeof (labels) / sizeof (labels[0])) - return NULL; + const char *res = NULL; + GSList *l; + EUtilLabel *label; + + g_static_mutex_lock (&cache_lock); + + l = g_slist_nth (labels_cache, i); + + if (l) + label = l->data; else - return labels[i].value; + label = NULL; + + if (label && label->tag) { + if (strncmp (label->tag, "$Label", 6) == 0) + res = label->tag + 6; + else + res = label->tag; + } + + g_static_mutex_unlock (&cache_lock); + + return res; } int filter_label_index (const char *label) { int i; + GSList *l; + + g_static_mutex_lock (&cache_lock); + + for (i = 0, l = labels_cache; l; i++, l = l->next) { + EUtilLabel *lbl = l->data; + const char *tag = lbl->tag; - for (i = 0; i < sizeof (labels) / sizeof (labels[0]); i++) { - if (strcmp (labels[i].value, label) == 0) - return i; + if (tag && strncmp (tag, "$Label", 6) == 0) + tag += 6; + + if (tag && strcmp (tag, label) == 0) + break; } + g_static_mutex_unlock (&cache_lock); + + if (l) + return i; + return -1; } static void xml_create (FilterElement *fe, xmlNodePtr node) { - FilterOption *fo = (FilterOption *) fe; - GConfClient *gconf; - GSList *list, *l; - char *title, *p, *nounderscores_title; - int i = 0; - FILTER_ELEMENT_CLASS (parent_class)->xml_create (fe, node); - gconf = gconf_client_get_default (); - - l = list = gconf_client_get_list (gconf, "/apps/evolution/mail/labels", GCONF_VALUE_STRING, NULL); - while (l != NULL) { - title = (char *) l->data; - if ((p = strrchr (title, ':'))) - *p++ = '\0'; - - nounderscores_title = e_str_without_underscores (title); - - filter_option_add (fo, i < 5 ? labels[i++].value : (p ? p : "#ffffff"), nounderscores_title, NULL); - g_free (title); - g_free (nounderscores_title); - - l = l->next; - } - g_slist_free (list); - - g_object_unref (gconf); + fill_options ((FilterOption *) fe); } diff --git a/filter/filter-option.c b/filter/filter-option.c index 2aea362bbc..f56943f22c 100644 --- a/filter/filter-option.c +++ b/filter/filter-option.c @@ -183,6 +183,29 @@ filter_option_add(FilterOption *fo, const char *value, const char *title, const return op; } +const char * +filter_option_get_current (FilterOption *option) +{ + g_return_val_if_fail (IS_FILTER_OPTION (option), NULL); + + if (!option->current) + return NULL; + + return option->current->value; +} + +void +filter_option_remove_all (FilterOption *fo) +{ + g_return_if_fail (IS_FILTER_OPTION (fo)); + + g_list_foreach (fo->options, (GFunc)free_option, NULL); + g_list_free (fo->options); + fo->options = NULL; + + fo->current = NULL; +} + static int option_eq(FilterElement *fe, FilterElement *cm) { diff --git a/filter/filter-option.h b/filter/filter-option.h index 58f984d8e4..a7a36151e0 100644 --- a/filter/filter-option.h +++ b/filter/filter-option.h @@ -64,6 +64,9 @@ FilterOption *filter_option_new (void); /* methods */ void filter_option_set_current (FilterOption *option, const char *name); +const char *filter_option_get_current (FilterOption *option); + struct _filter_option *filter_option_add (FilterOption *fo, const char *name, const char *title, const char *code); +void filter_option_remove_all (FilterOption *fo); #endif /* ! _FILTER_OPTION_H */ |