aboutsummaryrefslogtreecommitdiffstats
path: root/filter/filter-label.c
diff options
context:
space:
mode:
Diffstat (limited to 'filter/filter-label.c')
-rw-r--r--filter/filter-label.c217
1 files changed, 171 insertions, 46 deletions
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);
}