evolution r34788 - in trunk: e-util filter mail po



Author: mcrha
Date: Thu Jan 10 11:19:37 2008
New Revision: 34788
URL: http://svn.gnome.org/viewvc/evolution?rev=34788&view=rev

Log:
2008-01-10  Milan Crha  <mcrha redhat com>

	** Fix for bug #211353

	* po/POTFILES.in: Added new file e-util/e-util-labels.c

	* mail/filtertypes.xml:
	* mail/vfoldertypes.xml:
	* mail/em-folder-view.c:
	* mail/em-folder-browser.c:
	* mail/em-mailer-prefs.h:
	* mail/em-mailer-prefs.c:
	* mail/mail-config.h:
	* mail/mail-config.c:
	* mail/mail-config.glade:
	* mail/message-list.c:
	Label tags are now generated based on label name when creating, except
	of first 5 labels. New menu option "New Label" in popup menu over
	message list and editing of labels has been changed in Preferences.
	Also renaming tab in Preferences for "Labels", not "Colors", and the
	tab label too.
	mail-config-label... functions was moved to e-util/e-util-labels.c/.h.
	* mail/message-list.etspec: Normalized columns has been moved by one
	when label column has been added.

	* filter/filter-option.h:
	* filter/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/filter-label.c: Added support to notify changes on labels in runtime
	and use actual labels.

	* e-util/Makefile.am:
	* e-util/e-util-labels.h:
	* e-util/e-util-labels.c: New files to work with labels.



Added:
   trunk/e-util/e-util-labels.c
   trunk/e-util/e-util-labels.h
Modified:
   trunk/e-util/ChangeLog
   trunk/e-util/Makefile.am
   trunk/filter/ChangeLog
   trunk/filter/filter-label.c
   trunk/filter/filter-option.c
   trunk/filter/filter-option.h
   trunk/mail/ChangeLog
   trunk/mail/em-filter-i18n.h
   trunk/mail/em-folder-browser.c
   trunk/mail/em-folder-view.c
   trunk/mail/em-mailer-prefs.c
   trunk/mail/em-mailer-prefs.h
   trunk/mail/filtertypes.xml
   trunk/mail/mail-config.c
   trunk/mail/mail-config.glade
   trunk/mail/mail-config.h
   trunk/mail/message-list.c
   trunk/mail/message-list.etspec
   trunk/mail/vfoldertypes.xml
   trunk/po/ChangeLog
   trunk/po/POTFILES.in

Modified: trunk/e-util/Makefile.am
==============================================================================
--- trunk/e-util/Makefile.am	(original)
+++ trunk/e-util/Makefile.am	Thu Jan 10 11:19:37 2008
@@ -73,6 +73,7 @@
 	e-text-event-processor-types.h		\
 	e-text-event-processor.h		\
 	e-util.h				\
+	e-util-labels.h				\
 	e-util-marshal.h			\
 	e-xml-utils.h
 
@@ -111,6 +112,7 @@
 	e-text-event-processor-emacs-like.c     \
 	e-text-event-processor.c                \
 	e-util.c				\
+	e-util-labels.c				\
 	e-util-private.h			\
 	e-xml-utils.c				\
 	$(PLATFORM_SOURCES)

Added: trunk/e-util/e-util-labels.c
==============================================================================
--- (empty file)
+++ trunk/e-util/e-util-labels.c	Thu Jan 10 11:19:37 2008
@@ -0,0 +1,551 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*  e-util-labels.c
+ *
+ *  Copyright (C) 2007 Novell, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <gconf/gconf-client.h>
+
+#include <gtk/gtkbox.h>
+#include <gtk/gtkcolorbutton.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtktable.h>
+
+#include <camel/camel-utf8.h>
+
+#include "e-util-labels.h"
+#include "e-dialog-utils.h"
+
+/* Note, the first element of each EUtilLabel must NOT be translated */
+EUtilLabel label_defaults[LABEL_DEFAULTS_NUM] = {
+	{ "$Labelimportant", N_("I_mportant"), "#EF2929" },  /* red */
+	{ "$Labelwork",      N_("_Work"),      "#F57900" },  /* orange */
+	{ "$Labelpersonal",  N_("_Personal"),  "#4E9A06" },  /* green */
+	{ "$Labeltodo",      N_("_To Do"),     "#3465A4" },  /* blue */
+	{ "$Labellater",     N_("_Later"),     "#75507B" }   /* purple */
+};
+
+/**
+ * e_util_labels_parse
+ * Reads the setup from client and parses it to list of EUtilLabel objects.
+ *
+ * @param client The config client to be used for reading setup.
+ *        Can be NULL, in that case it will use the default client.
+ * @return Newly allocated list of labels, should be freed with @ref e_util_labels_free.
+ **/
+GSList *
+e_util_labels_parse (GConfClient *client)
+{
+	GSList *labels, *list, *head;
+	EUtilLabel *label;
+	char *buf;
+	int num = 0;
+	gboolean unref_client = client == NULL;
+
+	labels = NULL;
+
+	if (!client)
+		client = gconf_client_get_default ();
+
+	head = gconf_client_get_list (client, E_UTIL_LABELS_GCONF_KEY, GCONF_VALUE_STRING, NULL);
+
+	for (list = head; list; list = list->next) {
+		char *color, *name, *tag;
+		name = buf = list->data;
+		color = strrchr (buf, ':');
+
+		*color++ = '\0';
+		tag = strchr (color, '|');
+		if (tag)
+			*tag++ = '\0';
+
+		label = g_new (EUtilLabel, 1);
+
+		/* Needed for Backward Compatibility */
+		if (num < LABEL_DEFAULTS_NUM) {
+			label->name = g_strdup (_(buf));
+			label->tag = g_strdup (label_defaults[num].tag);
+			num++;
+		} else if (!tag) {
+			g_free (buf);
+			g_free (label);
+			continue;
+		} else {
+			label->name = g_strdup (name);
+			label->tag = g_strdup (tag);
+		}
+
+		label->colour = g_strdup (color);
+		labels = g_slist_prepend (labels, label);
+
+		g_free (buf);
+	}
+
+	if (head)
+		g_slist_free (head);
+
+	while (num < LABEL_DEFAULTS_NUM) {
+		/* complete the list with defaults */
+		label = g_new (EUtilLabel, 1);
+		label->tag = g_strdup (label_defaults[num].tag);
+		label->name = g_strdup (_(label_defaults[num].name));
+		label->colour = g_strdup (label_defaults[num].colour);
+
+		labels = g_slist_prepend (labels, label);
+
+		num++;
+	}
+
+	if (unref_client)
+		g_object_unref (client);
+
+	return g_slist_reverse (labels);
+}
+
+static void
+free_label_struct (EUtilLabel *label)
+{
+	if (!label)
+		return;
+
+	g_free (label->tag);
+	g_free (label->name);
+	g_free (label->colour);
+	g_free (label);
+}
+
+/**
+ * e_util_labels_free
+ * Frees memory previously allocated by @ref e_util_labels_parse
+ *
+ * @param labels Labels list, previously allocated by @ref e_util_labels_parse
+ *               It is safe to call with NULL.
+ **/
+void
+e_util_labels_free (GSList *labels)
+{
+	if (!labels)
+		return;
+
+	g_slist_foreach (labels, (GFunc)free_label_struct, NULL);
+	g_slist_free (labels);
+}
+
+/* stores the actual cache to gconf */
+static gboolean
+flush_labels_cache (GSList *labels, gboolean free_labels)
+{
+	GSList *l, *text_labels;
+	GConfClient *client;
+
+	if (!labels)
+		return FALSE;
+
+	text_labels = NULL;
+
+	for (l = labels; l; l = l->next) {
+		EUtilLabel *label = l->data;
+
+		if (label && label->tag && label->name && label->colour)
+			text_labels = g_slist_prepend (text_labels, g_strdup_printf ("%s:%s|%s", label->name, label->colour, label->tag));
+	}
+
+	if (!text_labels) {
+		if (free_labels)
+			e_util_labels_free (labels);
+
+		return FALSE;
+	}
+
+	text_labels = g_slist_reverse (text_labels);
+
+	client = gconf_client_get_default ();
+	gconf_client_set_list (client, E_UTIL_LABELS_GCONF_KEY, GCONF_VALUE_STRING, text_labels, NULL);
+	g_object_unref (client);
+
+	g_slist_foreach (text_labels, (GFunc)g_free, NULL);
+	g_slist_free (text_labels);
+
+	if (free_labels)
+		e_util_labels_free (labels);
+
+	/* not true if gconf failed to write; who cares */
+	return TRUE;
+}
+
+/**
+ * find_label
+ *
+ * Looks for label in labels cache by tag and returns actual pointer to cache.
+ * @param labels The cache of labels; comes from @ref e_util_labels_parse
+ * @param tag Tag of label you are looking for.
+ * @return Pointer to cache data if label with such tag exists or NULL. Do not free it!
+ **/
+static EUtilLabel *
+find_label (GSList *labels, const char *tag)
+{
+	GSList *l;
+
+	g_return_val_if_fail (tag != NULL, NULL);
+
+	for (l = labels; l; l = l->next) {
+		EUtilLabel *label = l->data;
+	
+		if (label && label->tag && !strcmp (tag, label->tag))
+			return label;
+	}
+
+	return NULL;
+}
+
+
+static char *
+tag_from_name (const char *name)
+{
+	/* this does thunderbird, just do not ask */
+	char *s1, *s2, *p;
+	const char *bads = " ()/{%*<>\\\"";
+
+	if (!name || !*name)
+		return NULL;
+
+	s1 = g_strdup (name);
+	for (p = s1; p && *p; p++) {
+		if (strchr (bads, *p))
+			*p = '_';
+	}
+
+	s2 = camel_utf8_utf7 (s1);
+	g_free (s1);
+
+	s1 = g_ascii_strdown (s2, -1);
+	g_free (s2);
+
+	return s1;
+}
+
+/**
+ * e_util_labels_add
+ * Creates new label at the end of actual list of labels.
+ *
+ * @param name User readable name of this label. Should not be NULL.
+ * @param color Color assigned to this label. Should not be NULL.
+ * @return If succeeded then new label tag, NULL otherwise.
+ *         Returned pointer should be freed with g_free.
+ *         It will return NULL when the tag will be same as already existed.
+ *         Tag name is generated in similar way as in Thunderbird.
+ **/
+char *
+e_util_labels_add (const char *name, const GdkColor *color)
+{
+	EUtilLabel *label;
+	GSList *labels;
+	char *tag;
+
+	g_return_val_if_fail (name != NULL, NULL);
+	g_return_val_if_fail (color != NULL, NULL);
+
+	labels = e_util_labels_parse (NULL);
+	tag = tag_from_name (name);
+
+	if (!tag || find_label (labels, tag) != NULL) {
+		g_free (tag);
+		e_util_labels_free (labels);
+		return NULL;
+	}
+
+	label = g_new0 (EUtilLabel, 1);
+	label->tag = g_strdup (tag);
+	label->name = g_strdup (name);
+	label->colour = gdk_color_to_string (color);
+
+	labels = g_slist_append (labels, label);
+
+	flush_labels_cache (labels, TRUE);
+
+	return tag;
+}
+
+/**
+ * e_util_labels_add_with_dlg
+ * This will open a dialog to add or edit label.
+ *
+ * @param parent Parent widget for the dialog.
+ * @param tag A tag for existing label to edit or NULL to add new label.
+ * @return Tag for newly added label or NULL, if something failed.
+ *         Returned value should be freed with g_free.
+ **/
+char *
+e_util_labels_add_with_dlg (GtkWindow *parent, const char *tag)
+{
+	GtkWidget *table, *dialog, *l, *e, *c;
+	const char *name;
+	GdkColor color;
+	gboolean is_edit = FALSE;
+	char *new_tag = NULL;
+	GSList *labels;
+
+	table = gtk_table_new (2, 2, FALSE);
+
+	labels = e_util_labels_parse (NULL);
+	name = tag ? e_util_labels_get_name (labels, tag) : NULL;
+
+	l = gtk_label_new_with_mnemonic (_("Label _Name:"));
+	e = gtk_entry_new ();
+	c = gtk_color_button_new ();
+
+	if (!tag || !e_util_labels_get_color (labels, tag, &color))
+		memset (&color, 0xCD, sizeof (GdkColor));
+	else
+		is_edit = TRUE;
+
+	if (name)
+		gtk_entry_set_text (GTK_ENTRY (e), name);
+
+	gtk_label_set_mnemonic_widget (GTK_LABEL (l), e);
+	gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.0);
+	gtk_color_button_set_color (GTK_COLOR_BUTTON (c), &color);
+
+	gtk_table_attach (GTK_TABLE (table), l, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
+	gtk_table_attach (GTK_TABLE (table), e, 0, 1, 1, 2, 0, 0, 0, 0);
+	gtk_table_attach (GTK_TABLE (table), c, 1, 2, 1, 2, 0, 0, 0, 0);
+	gtk_container_set_border_width (GTK_CONTAINER (table), 10);
+	gtk_widget_show_all (table);
+
+	dialog = gtk_dialog_new_with_buttons (is_edit ? _("Edit Label") : _("Add Label"),
+					      parent,
+					      GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+                                              GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+                                              GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+					      NULL);
+
+	gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
+	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, TRUE, TRUE, 0);
+
+	while (!new_tag) {
+		const char *error = NULL;
+
+		if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
+			name = gtk_entry_get_text (GTK_ENTRY (e));
+			gtk_color_button_get_color (GTK_COLOR_BUTTON (c), &color);
+
+			if (!name || !*name)
+				error = _("Label name cannot be empty.");
+			else if (is_edit) {
+				e_util_labels_set_data (tag, name, &color);
+				break;
+			} else if (!(new_tag = e_util_labels_add (name, &color)))
+				error = _("Label with same tag already exists. Rename your label please.");
+			else
+				break;
+		} else
+			break;
+
+		if (error)
+			e_notice (parent, GTK_MESSAGE_ERROR, error);
+	}
+
+	gtk_widget_destroy (dialog);
+	e_util_labels_free (labels);
+
+	return new_tag;
+}
+
+/**
+ * e_util_labels_remove
+ *
+ * @param tag Tag of the label to remove.
+ * @return Whether was removed.
+ **/
+gboolean
+e_util_labels_remove (const char *tag)
+{
+	EUtilLabel *label;
+	GSList *labels;
+
+	g_return_val_if_fail (tag != NULL, FALSE);
+
+	labels = e_util_labels_parse (NULL);
+	label = find_label (labels, tag);
+
+	if (!label) {
+		e_util_labels_free (labels);
+		return FALSE;
+	}
+
+	labels = g_slist_remove (labels, label);
+
+	free_label_struct (label);
+
+	return 	flush_labels_cache (labels, TRUE);
+}
+
+/**
+ * e_util_labels_set_data
+ *
+ * @param tag Tag of the label of our interest.
+ * @param name New name for the label.
+ * @param color New color for the label.
+ * @return Whether successfully saved.
+ **/
+gboolean
+e_util_labels_set_data (const char *tag, const char *name, const GdkColor *color)
+{
+	EUtilLabel *label;
+	GSList *labels;
+
+	g_return_val_if_fail (tag != NULL, FALSE);
+	g_return_val_if_fail (name != NULL, FALSE);
+	g_return_val_if_fail (color != NULL, FALSE);
+
+	labels = e_util_labels_parse (NULL);
+	label = find_label (labels, tag);
+
+	if (!label) {
+		e_util_labels_free (labels);
+		return FALSE;
+	}
+
+	g_free (label->name);
+	label->name = g_strdup (name);
+
+	g_free (label->colour);
+	label->colour = gdk_color_to_string (color);
+
+	return flush_labels_cache (labels, TRUE);
+}
+
+/**
+ * e_util_labels_is_system
+ *
+ * @return Whether the tag is one of default/system labels or not.
+ **/
+gboolean
+e_util_labels_is_system (const char *tag)
+{
+	int i;
+
+	if (!tag)
+		return FALSE;
+
+	for (i = 0; i < LABEL_DEFAULTS_NUM; i++) {
+		if (strcmp (tag, label_defaults[i].tag) == 0)
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+/**
+ * e_util_labels_get_new_tag
+ *
+ * @param old_tag Tag of the label from old version of Evolution.
+ * @return New tag name equivalent with the old tag, or NULL if no such name existed before.
+ **/
+const char *
+e_util_labels_get_new_tag (const char *old_tag)
+{
+	int i;
+
+	if (!old_tag)
+		return NULL;
+
+	for (i = 0; i < LABEL_DEFAULTS_NUM; i++) {
+		/* default labels have same name as those old, only with prefix "$Label" */
+		if (!strcmp (old_tag, label_defaults[i].tag + 6))
+			return label_defaults[i].tag;
+	}
+
+	return NULL;
+}
+
+/**
+ * e_util_labels_get_name
+ *
+ * @param labels Cache of labels from call of @ref e_util_labels_parse.
+ *        The returned pointer will be taken from this list, so it's alive as long as the list.
+ * @param tag Tag of the label of our interest.
+ * @return Name of the label with that tag or NULL, if no such label exists.
+ **/
+const char *
+e_util_labels_get_name (GSList *labels, const char *tag)
+{
+	EUtilLabel *label;
+
+	g_return_val_if_fail (tag != NULL, NULL);
+
+	label = find_label (labels, tag);
+	if (!label)
+		return NULL;
+
+	return label->name;
+}
+
+/**
+ * e_util_labels_get_color
+ *
+ * @param labels Cache of labels from call of @ref e_util_labels_parse.
+ * @param tag Tag of the label of our interest.
+ * @param color [out] Actual color of the label with that tag, or unchanged if failed.
+ * @return Whether found such label and color has been set.
+ **/
+gboolean
+e_util_labels_get_color (GSList *labels, const char *tag, GdkColor *color)
+{
+	EUtilLabel *label;
+
+	g_return_val_if_fail (tag != NULL, FALSE);
+	g_return_val_if_fail (color != NULL, FALSE);
+
+	label = find_label (labels, tag);
+	if (!label)
+		return FALSE;
+
+	return gdk_color_parse (label->colour, color);
+}
+
+/**
+ * e_util_labels_get_color_str
+ *
+ * @param labels Cache of labels from call of @ref e_util_labels_parse.
+ *        The returned pointer will be taken from this list, so it's alive as long as the list.
+ * @param tag Tag of the label of our interest.
+ * @return String representation of that label, or NULL, is no such label exists.
+ **/
+const char *
+e_util_labels_get_color_str (GSList *labels, const char *tag)
+{
+	EUtilLabel *label;
+
+	g_return_val_if_fail (tag != NULL, FALSE);
+
+	label = find_label (labels, tag);
+	if (!label)
+		return FALSE;
+
+	return label->colour;
+}

Added: trunk/e-util/e-util-labels.h
==============================================================================
--- (empty file)
+++ trunk/e-util/e-util-labels.h	Thu Jan 10 11:19:37 2008
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*  e-util-labels.h
+ *
+ *  Copyright (C) 2007 Novell, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library 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
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _E_UTIL_LABELS_H
+#define _E_UTIL_LABELS_H
+
+#include <glib.h>
+#include <gdk/gdkcolor.h>
+
+struct _GtkWindow;
+struct _GConfClient;
+
+typedef struct {
+	char *tag;
+	char *name;
+	char *colour;
+} EUtilLabel;
+
+#define E_UTIL_LABELS_GCONF_KEY "/apps/evolution/mail/labels"
+
+#define LABEL_DEFAULTS_NUM 5
+extern EUtilLabel label_defaults[LABEL_DEFAULTS_NUM];
+
+GSList *    e_util_labels_parse         (struct _GConfClient *client);
+void        e_util_labels_free          (GSList *labels);
+
+char *      e_util_labels_add           (const char *name, const GdkColor *color);
+char *      e_util_labels_add_with_dlg  (struct _GtkWindow *parent, const char *tag);
+gboolean    e_util_labels_remove        (const char *tag);
+gboolean    e_util_labels_set_data      (const char *tag, const char *name, const GdkColor *color);
+
+gboolean    e_util_labels_is_system     (const char *tag);
+const char *e_util_labels_get_new_tag   (const char *old_tag);
+
+const char *e_util_labels_get_name      (GSList *labels, const char *tag);
+gboolean    e_util_labels_get_color     (GSList *labels, const char *tag, GdkColor *color);
+const char *e_util_labels_get_color_str (GSList *labels, const char *tag);
+
+#endif /* _E_UTIL_LABELS_H */

Modified: trunk/filter/filter-label.c
==============================================================================
--- trunk/filter/filter-label.c	(original)
+++ trunk/filter/filter-label.c	Thu Jan 10 11:19:37 2008
@@ -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_init (FilterLabel *label);
 static void filter_label_finalise (GObject *obj);
 
-
 static FilterElementClass *parent_class;
 
-
 GType
 filter_label_get_type (void)
 {
@@ -75,6 +74,16 @@
 	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 @@
 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 @@
 	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"     },
-};
+/* ************************************************************************* */
+
+/* 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;
+}
 
-int filter_label_count (void)
+static void
+fill_options (FilterOption *fo)
 {
-	return sizeof (labels) / sizeof (labels[0]);
+	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)
+{
+	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;
 
-	for (i = 0; i < sizeof (labels) / sizeof (labels[0]); i++) {
-		if (strcmp (labels[i].value, label) == 0)
-			return i;
+	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;
+
+		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);
 }

Modified: trunk/filter/filter-option.c
==============================================================================
--- trunk/filter/filter-option.c	(original)
+++ trunk/filter/filter-option.c	Thu Jan 10 11:19:37 2008
@@ -183,6 +183,29 @@
 	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)
 {

Modified: trunk/filter/filter-option.h
==============================================================================
--- trunk/filter/filter-option.h	(original)
+++ trunk/filter/filter-option.h	Thu Jan 10 11:19:37 2008
@@ -64,6 +64,9 @@
 
 /* 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 */

Modified: trunk/mail/em-filter-i18n.h
==============================================================================
--- trunk/mail/em-filter-i18n.h	(original)
+++ trunk/mail/em-filter-i18n.h	Thu Jan 10 11:19:37 2008
@@ -3,7 +3,10 @@
 char *s = N_("Assign Color");
 char *s = N_("Assign Score");
 char *s = N_("Attachments");
+char *s = N_("BCC");
 char *s = N_("Beep");
+char *s = N_("CC");
+char *s = N_("Completed On");
 char *s = N_("contains");
 char *s = N_("Copy to Folder");
 char *s = N_("Date received");
@@ -32,6 +35,8 @@
 char *s = N_("is less than");
 char *s = N_("is not");
 char *s = N_("is not Flagged");
+char *s = N_("is not set");
+char *s = N_("is set");
 char *s = N_("Junk");
 char *s = N_("Junk Test");
 char *s = N_("Label");
@@ -54,6 +59,7 @@
 char *s = N_("Run Program");
 char *s = N_("Score");
 char *s = N_("Sender");
+char *s = N_("Set Label");
 char *s = N_("Set Status");
 char *s = N_("Size (kB)");
 char *s = N_("sounds like");

Modified: trunk/mail/em-folder-browser.c
==============================================================================
--- trunk/mail/em-folder-browser.c	(original)
+++ trunk/mail/em-folder-browser.c	Thu Jan 10 11:19:37 2008
@@ -82,6 +82,7 @@
 #include "e-util/e-util.h"
 #include "e-util/e-error.h"
 #include "e-util/e-util-private.h"
+#include "e-util/e-util-labels.h"
 #include "em-utils.h"
 #include "em-composer-utils.h"
 #include "em-format-html-display.h"
@@ -309,8 +310,8 @@
 	}
 
 	/* Add the labels */
-	for (l = mail_config_get_labels(), i = 0; l; l = l->next, i++) {
-		MailConfigLabel *label = l->data;
+	for (l = mail_config_get_labels (), i = 0; l; l = l->next, i++) {
+		EUtilLabel *label = l->data;
 		if (label->name && *(label->name)) {
 			char *str;
 			GdkPixmap *pixmap;
@@ -335,9 +336,8 @@
 			g_object_set_data (G_OBJECT (menu_item), "EsbItemId",
 					   GINT_TO_POINTER (VIEW_LABEL + (VIEW_ITEMS_MASK + 1) * i));
 
-			/* label->tag starts with "$Label" so it's safe to do */
 			g_object_set_data (G_OBJECT (menu_item), "LabelTag",
-					   g_strdup (label->tag + 6));
+					   g_strdup (strncmp (label->tag, "$Label", 6) == 0 ? label->tag + 6 : label->tag));
 		}
 
 		gtk_widget_show (menu_item);
@@ -379,9 +379,9 @@
 	for (i = 0; emfb_view_items[i].search.id != -1; i++)
 		g_array_append_vals (menu, &emfb_view_items[i], 1);
 
-	for (l = mail_config_get_labels(); l; l = l->next) {
+	for (l = mail_config_get_labels (); l; l = l->next) {
 		ESearchBarItem item;
-		MailConfigLabel *label = l->data;
+		EUtilLabel *label = l->data;
 
 		item.text = label->name;
 		item.id = VIEW_LABEL;
@@ -499,7 +499,7 @@
 		gtk_box_pack_start((GtkBox *)emfb, (GtkWidget *)emfb->search, FALSE, TRUE, 0);
 
 		gconf = mail_config_get_gconf_client ();
-		emfb->priv->labels_change_notify_id = gconf_client_notify_add (gconf, "/apps/evolution/mail/labels", gconf_labels_changed, emfb, NULL, NULL);
+		emfb->priv->labels_change_notify_id = gconf_client_notify_add (gconf, E_UTIL_LABELS_GCONF_KEY, gconf_labels_changed, emfb, NULL, NULL);
 	}
 
 	emfb->priv->show_wide = gconf_client_get_bool(mail_config_get_gconf_client(), "/apps/evolution/mail/display/show_wide", NULL);
@@ -877,11 +877,16 @@
 		GString *s = g_string_new ("(and");
 
 		for (l = mail_config_get_labels (); l; l = l->next) {
-			MailConfigLabel *label = (MailConfigLabel *)l->data;
+			EUtilLabel *label = (EUtilLabel *)l->data;
 
-			/* tag is always with "$Label" prefix */
-			if (label && label->tag)
-				g_string_append_printf (s, " (match-all (not (or (= (user-tag \"label\") \"%s\") (user-flag \"$Label%s\"))))", label->tag + 6, label->tag + 6);
+			if (label && label->tag) {
+				const gchar *tag = label->tag;
+
+				if (strncmp (tag, "$Label", 6) == 0)
+					tag += 6;
+
+				g_string_append_printf (s, " (match-all (not (or (= (user-tag \"label\") \"%s\") (user-flag \"$Label%s\") (user-flag \"%s\"))))", tag, tag, tag);
+			}
 		}
 
 		g_string_append (s, ")");
@@ -891,7 +896,7 @@
 		} break;
         case VIEW_LABEL:
 		tag = (char *)g_object_get_data (G_OBJECT (menu_item), "LabelTag");
-		view_sexp = g_strdup_printf ("(match-all (or (= (user-tag \"label\") \"%s\") (user-flag \"$Label%s\" )))", tag, tag);
+		view_sexp = g_strdup_printf ("(match-all (or (= (user-tag \"label\") \"%s\") (user-flag \"$Label%s\") (user-flag \"%s\")))", tag, tag, tag);
 		duplicate = FALSE;
 		break;
 	case VIEW_MESSAGES_MARKED_AS_IMPORTANT:

Modified: trunk/mail/em-folder-view.c
==============================================================================
--- trunk/mail/em-folder-view.c	(original)
+++ trunk/mail/em-folder-view.c	Thu Jan 10 11:19:37 2008
@@ -89,6 +89,7 @@
 #include "e-util/e-print.h"
 #include "e-util/e-profile-event.h"
 #include "e-util/e-util-private.h"
+#include "e-util/e-util-labels.h"
 
 #include "filter/filter-rule.h"
 
@@ -1233,9 +1234,9 @@
 {
 	EMFolderView *emfv = data;
 	GSList *l;
-	MailConfigLabel *label; 
+	EUtilLabel *label; 
 
-	for (l = mail_config_get_labels(); l; l = l->next) {
+	for (l = mail_config_get_labels (); l; l = l->next) {
 		label = l->data;
 		emfv_unset_label(emfv, label->tag);
 	}
@@ -1253,6 +1254,18 @@
 }
 
 static void
+emfv_popup_label_new (EPopup *ep, EPopupItem *pitem, void *data)
+{
+	EMFolderView *emfv = data;
+	char *tag = e_util_labels_add_with_dlg (NULL, NULL);
+
+	if (tag) {
+		emfv_set_label (emfv, tag);
+		g_free (tag);
+	}
+}
+
+static void
 emfv_popup_add_sender(EPopup *ep, EPopupItem *pitem, void *data)
 {
 	EMFolderView *emfv = data;
@@ -1343,6 +1356,8 @@
 	{ E_POPUP_SUBMENU, "60.label.00", N_("_Label"), NULL, NULL, NULL, EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY },
 	{ E_POPUP_ITEM, "60.label.00/00.label", N_("_None"), emfv_popup_label_clear, NULL, NULL, EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY },
 	{ E_POPUP_BAR, "60.label.00/00.label.00", NULL, NULL, NULL, NULL },
+	{ E_POPUP_BAR, "60.label.00/01.label", NULL, NULL, NULL, NULL },
+	{ E_POPUP_ITEM, "60.label.00/01.label.00", N_("_New Label"), emfv_popup_label_new, NULL, NULL, EM_POPUP_SELECT_MANY|EM_FOLDER_VIEW_SELECT_LISTONLY },
 
 	{ E_POPUP_BAR, "70.emfv.06", NULL, NULL, NULL, NULL },
 
@@ -1381,7 +1396,7 @@
 		if (camel_folder_get_message_user_flag (emfv->folder, uids->pdata[i], label_tag))
 			exists = TRUE;
 		else {
-			const char *label = mail_config_get_new_label_tag (camel_folder_get_message_user_tag (emfv->folder, uids->pdata[i], "label"));
+			const char *label = e_util_labels_get_new_tag (camel_folder_get_message_user_tag (emfv->folder, uids->pdata[i], "label"));
 
 			/* backward compatibility... */
 			if (label && !strcmp (label, label_tag))
@@ -1448,9 +1463,9 @@
 	if (!on_display) {
 		GPtrArray *uids = message_list_get_selected (emfv->list);
 
-		for (l = mail_config_get_labels(); l; l = l->next) {
+		for (l = mail_config_get_labels (); l; l = l->next) {
 			EPopupItem *item;
-			MailConfigLabel *label = l->data;
+			EUtilLabel *label = l->data;
 			GdkPixmap *pixmap;
 			GdkColor colour;
 			GdkGC *gc;

Modified: trunk/mail/em-mailer-prefs.c
==============================================================================
--- trunk/mail/em-mailer-prefs.c	(original)
+++ trunk/mail/em-mailer-prefs.c	Thu Jan 10 11:19:37 2008
@@ -57,6 +57,7 @@
 #include "libedataserverui/e-cell-renderer-color.h"
 
 #include "e-util/e-util-private.h"
+#include "e-util/e-util-labels.h"
 
 #include "mail-config.h"
 #include "em-junk-hook.h"
@@ -156,6 +157,12 @@
 
 	g_object_unref (prefs->gui);
 
+	if (prefs->labels_change_notify_id) {
+		gconf_client_notify_remove (prefs->gconf, prefs->labels_change_notify_id);
+
+		prefs->labels_change_notify_id = 0;
+	}
+
         ((GObjectClass *)(parent_class))->finalize (obj);
 }
 
@@ -191,31 +198,6 @@
 };
 
 static void
-label_name_edited_cb (GtkCellRendererText *cell, gchar *path_string, gchar *new_text, EMMailerPrefs *prefs)
-{
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (prefs->label_tree));
-
-	gtk_tree_model_get_iter_from_string (model, &iter, path_string);
-
-	g_strstrip (new_text);
-
-	/* allow only nonempty texts and always strip spaces there */
-	if (new_text && *new_text) {
-		gchar *tag = NULL;
-
-		gtk_tree_model_get (model, &iter, LABEL_LIST_COLUMN_TAG, &tag, -1);
-
-		gtk_list_store_set (GTK_LIST_STORE (model), &iter, LABEL_LIST_COLUMN_NAME, new_text, -1);
-		mail_config_set_label_name (tag, new_text);
-
-		g_free (tag);
-	}
-}
-
-static void
 label_sensitive_buttons (EMMailerPrefs *prefs)
 {
 	gboolean can_remove = FALSE, have_selected = FALSE, locked;
@@ -236,7 +218,7 @@
 
 			gtk_tree_model_get (model, &iter, LABEL_LIST_COLUMN_TAG, &tag, -1);
 
-			can_remove = tag && !mail_config_is_system_label (tag);
+			can_remove = tag && !e_util_labels_is_system (tag);
 			have_selected = TRUE;
 
 			g_free (tag);
@@ -244,7 +226,7 @@
 	}
 
 	gtk_widget_set_sensitive (prefs->label_remove, !locked && can_remove);
-	gtk_widget_set_sensitive (prefs->label_color,  !locked && have_selected);
+	gtk_widget_set_sensitive (prefs->label_edit,  !locked && have_selected);
 }
 
 static void
@@ -253,11 +235,77 @@
 	label_sensitive_buttons (user_data);
 }
 
+static void
+label_tree_refill (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
+{
+	EMMailerPrefs *prefs = (EMMailerPrefs *)user_data;
+	GSList *labels, *l;
+	GtkTreeSelection *selection;
+	GtkListStore *store;
+	GtkTreeModel *model;
+	GtkTreeIter last_iter;
+	gchar *last_path = NULL;
+
+	g_return_if_fail (prefs != NULL);
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->label_tree));
+	if (gtk_tree_selection_get_selected (selection, &model, &last_iter))
+		last_path = gtk_tree_model_get_string_from_iter (model, &last_iter);
+
+	store = GTK_LIST_STORE (model);
+	gtk_list_store_clear (store);
+
+	/* cannot use mail-config cache here, because it's (or can be) updated later than this function call */
+	labels = e_util_labels_parse (client);
+
+	for (l = labels; l; l = l->next) {
+		GdkColor color;
+		GtkTreeIter iter;
+		EUtilLabel *label = l->data;
+
+		if (label->colour)
+			gdk_color_parse (label->colour, &color);
+
+		gtk_list_store_append (store, &iter);
+		gtk_list_store_set (
+			store, &iter,
+			LABEL_LIST_COLUMN_COLOR, label->colour ? &color : NULL,
+			LABEL_LIST_COLUMN_NAME, label->name,
+			LABEL_LIST_COLUMN_TAG, label->tag,
+			-1);
+	}
+
+	if (last_path) {
+		gint children;
+
+		children = gtk_tree_model_iter_n_children (model, NULL);
+		if (children > 0) {
+			GtkTreePath *path;
+
+			if (!gtk_tree_model_get_iter_from_string (model, &last_iter, last_path))
+				gtk_tree_model_iter_nth_child (model, &last_iter, NULL, children - 1);
+
+			path = gtk_tree_model_get_path (model, &last_iter);
+			if (path) {
+				GtkTreeViewColumn *focus_col = gtk_tree_view_get_column (GTK_TREE_VIEW (prefs->label_tree), LABEL_LIST_COLUMN_NAME);
+
+				gtk_tree_view_set_cursor (GTK_TREE_VIEW (prefs->label_tree), path, focus_col, FALSE);
+				gtk_tree_view_row_activated (GTK_TREE_VIEW (prefs->label_tree), path, focus_col);
+				gtk_tree_path_free (path);
+			}
+		}
+
+		g_free (last_path);
+	}
+
+	label_sensitive_buttons (prefs);
+	e_util_labels_free (labels);
+}
+
 static GtkListStore *
 init_label_tree (GtkWidget *label_tree, EMMailerPrefs *prefs, gboolean locked)
 {
 	GtkListStore *store;
-	GSList *labels;
 	GtkCellRenderer *renderer;
 	gint col;
 
@@ -277,31 +325,14 @@
 
 	renderer = gtk_cell_renderer_text_new ();
 	gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (label_tree), -1, _("Name"), renderer, "text", LABEL_LIST_COLUMN_NAME, NULL);
-	g_object_set (G_OBJECT (renderer), "editable", !locked, NULL);
+	g_object_set (G_OBJECT (renderer), "editable", FALSE, NULL);
 
-	if (!locked) {
-		g_signal_connect (renderer, "edited", G_CALLBACK (label_name_edited_cb), prefs);
+	if (!locked)
 		g_signal_connect (label_tree, "cursor-changed", G_CALLBACK (label_tree_cursor_changed), prefs);
-	}
 
-	for (labels = mail_config_get_labels (); labels; labels = labels->next) {
-		GdkColor color;
-		GtkTreeIter iter;
-		MailConfigLabel *label = labels->data;
+	label_tree_refill (NULL, 0, NULL, prefs);
 
-		if (label->colour)
-			gdk_color_parse (label->colour, &color);
-
-		gtk_list_store_append (store, &iter);
-		gtk_list_store_set (
-			store, &iter,
-			LABEL_LIST_COLUMN_COLOR, label->colour ? &color : NULL,
-			LABEL_LIST_COLUMN_NAME, label->name,
-			LABEL_LIST_COLUMN_TAG, label->tag,
-			-1);
-	}
-
-	label_sensitive_buttons (prefs);
+	prefs->labels_change_notify_id = gconf_client_notify_add (prefs->gconf, E_UTIL_LABELS_GCONF_KEY, label_tree_refill, prefs, NULL, NULL);
 
 	return store;
 }
@@ -309,45 +340,11 @@
 static void
 label_add_cb (GtkWidget *widget, gpointer user_data)
 {
-	EMMailerPrefs *prefs = user_data;
-	GtkTreeModel *model;
-	GtkTreeIter iter;
-	char *tag, *name;
-	int tagid;
-	GtkTreePath *path;
-	GdkColor gray;
-
-	g_return_if_fail (prefs != NULL);
-
-	tag = mail_config_get_next_label_tag (&tagid);
-
-	if (!tag)
-		return;
-
-	memset (&gray, 0xCD, sizeof (GdkColor));
-	name = g_strdup_printf ("%s %d", _("Label"), tagid);
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (prefs->label_tree));
+	char *tag;
 
-	if (mail_config_add_label (tag, name, &gray)) {
-		gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-		gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-			LABEL_LIST_COLUMN_COLOR, &gray,
-			LABEL_LIST_COLUMN_NAME, name,
-			LABEL_LIST_COLUMN_TAG, tag,
-			-1);
-
-		path = gtk_tree_model_get_path (model, &iter);
-		if (path) {
-			GtkTreeViewColumn *focus_col = gtk_tree_view_get_column (GTK_TREE_VIEW (prefs->label_tree), LABEL_LIST_COLUMN_NAME);
-
-			gtk_tree_view_set_cursor (GTK_TREE_VIEW (prefs->label_tree), path, focus_col, TRUE);
-			gtk_tree_view_row_activated (GTK_TREE_VIEW (prefs->label_tree), path, focus_col);
-			gtk_tree_path_free (path);
-		}
-	}
+	tag = e_util_labels_add_with_dlg (GTK_WINDOW (gtk_widget_get_toplevel (widget)), NULL);
 
 	g_free (tag);
-	g_free (name);
 }
 
 static void
@@ -366,36 +363,15 @@
 
 		gtk_tree_model_get (model, &iter, LABEL_LIST_COLUMN_TAG, &tag, -1);
 
-		if (tag && !mail_config_is_system_label (tag)) {
-			gint children;
-
-			gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
-			mail_config_remove_label (tag);
-
-			children = gtk_tree_model_iter_n_children (model, NULL);
-			if (children > 0) {
-				GtkTreePath *path;
-
-				if (!gtk_list_store_iter_is_valid (GTK_LIST_STORE (model), &iter))
-					gtk_tree_model_iter_nth_child (model, &iter, NULL, children - 1);
-
-				path = gtk_tree_model_get_path (model, &iter);
-				if (path) {
-					GtkTreeViewColumn *focus_col = gtk_tree_view_get_column (GTK_TREE_VIEW (prefs->label_tree), LABEL_LIST_COLUMN_NAME);
-
-					gtk_tree_view_set_cursor (GTK_TREE_VIEW (prefs->label_tree), path, focus_col, FALSE);
-					gtk_tree_view_row_activated (GTK_TREE_VIEW (prefs->label_tree), path, focus_col);
-					gtk_tree_path_free (path);
-				}
-			}
-		}
+		if (tag && !e_util_labels_is_system (tag))
+			e_util_labels_remove (tag);
 
 		g_free (tag);
 	}
 }
 
 static void
-label_color_cb (GtkWidget *widget, gpointer user_data)
+label_edit_cb (GtkWidget *widget, gpointer user_data)
 {
 	EMMailerPrefs *prefs = user_data;
 	GtkTreeSelection *selection;
@@ -406,32 +382,17 @@
 
 	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (prefs->label_tree));
 	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
-		GtkWidget *dialog;
-		GdkColor *color = NULL, color2;
-
-		gtk_tree_model_get (model, &iter, LABEL_LIST_COLUMN_COLOR, &color, -1);
-
-		dialog = gtk_color_selection_dialog_new (_("Select color for label..."));
-		gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dialog)->colorsel), color);
-
-		if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
-			gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (dialog)->colorsel), &color2);
-
-			if (!color || memcmp (color, &color2, sizeof(GdkColor)) != 0) {
-				gchar *tag = NULL;
+		gchar *tag = NULL;
 
-				gtk_tree_model_get (model, &iter, LABEL_LIST_COLUMN_TAG, &tag, -1);
-				gtk_list_store_set (GTK_LIST_STORE (model), &iter, LABEL_LIST_COLUMN_COLOR, &color2, -1);
+		gtk_tree_model_get (model, &iter, LABEL_LIST_COLUMN_TAG, &tag, -1);
 
-				mail_config_set_label_color (tag, &color2);
+		if (tag) {
+			char *str = e_util_labels_add_with_dlg (GTK_WINDOW (gtk_widget_get_toplevel (widget)), tag);
 
-				g_free (tag);
-			}
+			g_free (str);
 		}
 
-		gtk_widget_destroy (dialog);
-		if (color)
-			gdk_color_free (color);
+		g_free (tag);
 	}
 }
 
@@ -1204,15 +1165,15 @@
 			    G_CALLBACK (toggle_button_toggled));
 
 	/* Labels... */
-	locked = !gconf_client_key_is_writable (prefs->gconf, "/apps/evolution/mail/labels", NULL);
+	locked = !gconf_client_key_is_writable (prefs->gconf, E_UTIL_LABELS_GCONF_KEY, NULL);
 	prefs->label_add    = glade_xml_get_widget (gui, "labelAdd");
+	prefs->label_edit   = glade_xml_get_widget (gui, "labelEdit");
 	prefs->label_remove = glade_xml_get_widget (gui, "labelRemove");
-	prefs->label_color  = glade_xml_get_widget (gui, "labelColor");
 	prefs->label_tree   = glade_xml_get_widget (gui, "labelTree");
 
 	gtk_widget_set_sensitive (prefs->label_add, !locked);
 	gtk_widget_set_sensitive (prefs->label_remove, !locked);
-	gtk_widget_set_sensitive (prefs->label_color, !locked);
+	gtk_widget_set_sensitive (prefs->label_edit, !locked);
 	gtk_widget_set_sensitive (prefs->label_tree, !locked);
 
 	prefs->label_list_store = init_label_tree (prefs->label_tree, prefs, locked);
@@ -1220,7 +1181,7 @@
 	if (!locked) {
 		g_signal_connect (G_OBJECT (prefs->label_add), "clicked", G_CALLBACK (label_add_cb), prefs);
 		g_signal_connect (G_OBJECT (prefs->label_remove), "clicked", G_CALLBACK (label_remove_cb), prefs);
-		g_signal_connect (G_OBJECT (prefs->label_color), "clicked", G_CALLBACK (label_color_cb), prefs);
+		g_signal_connect (G_OBJECT (prefs->label_edit), "clicked", G_CALLBACK (label_edit_cb), prefs);
 	}
 
 	/* headers */

Modified: trunk/mail/em-mailer-prefs.h
==============================================================================
--- trunk/mail/em-mailer-prefs.h	(original)
+++ trunk/mail/em-mailer-prefs.h	Thu Jan 10 11:19:37 2008
@@ -104,10 +104,11 @@
 
 	/* Labels and Colours tab */
 	struct _GtkWidget *label_add;
+	struct _GtkWidget *label_edit;
 	struct _GtkWidget *label_remove;
-	struct _GtkWidget *label_color;
 	struct _GtkWidget *label_tree;
 	struct _GtkListStore *label_list_store;
+	guint labels_change_notify_id; /* mail_config's notify id */
 
 	/* Headers tab */
 	struct _GtkButton *add_header;

Modified: trunk/mail/filtertypes.xml
==============================================================================
--- trunk/mail/filtertypes.xml	(original)
+++ trunk/mail/filtertypes.xml	Thu Jan 10 11:19:37 2008
@@ -523,13 +523,13 @@
    <option value="is">
     <title>is</title>
     <code>
-       (match-all (or (= (user-tag "label") ${versus}) (user-flag (+ "$Label" ${versus}))))
+       (match-all (or (= (user-tag "label") ${versus}) (user-flag (+ "$Label" ${versus})) (user-flag ${versus})))
     </code>
    </option>
    <option value="is-not">
     <title>is not</title>
     <code>
-       (match-all (not (or (= (user-tag "label") ${versus}) (user-flag (+ "$Label" ${versus})))))
+       (match-all (not (or (= (user-tag "label") ${versus}) (user-flag (+ "$Label" ${versus})) (user-flag ${versus}))))
     </code>
    </option>
   </input>

Modified: trunk/mail/mail-config.c
==============================================================================
--- trunk/mail/mail-config.c	(original)
+++ trunk/mail/mail-config.c	Thu Jan 10 11:19:37 2008
@@ -58,6 +58,7 @@
 #include <libedataserver/e-data-server-util.h>
 #include <e-util/e-util.h>
 #include <misc/e-gui-utils.h>
+#include "e-util/e-util-labels.h"
 
 #include <libedataserver/e-account-list.h>
 #include <e-util/e-signature-list.h>
@@ -76,17 +77,6 @@
 #include "mail-mt.h"
 #include "mail-tools.h"
 
-/* Note, the first element of each MailConfigLabel must NOT be translated */
-/* Note, the label tag should Always starts with prefix "$Label"!
-         It's also because filters and search folders, so beware people. */
-MailConfigLabel label_defaults[LABEL_DEFAULTS_NUM] = {
-	{ "$Labelimportant", N_("I_mportant"), "#EF2929" },  /* red */
-	{ "$Labelwork",      N_("_Work"),      "#F57900" },  /* orange */
-	{ "$Labelpersonal",  N_("_Personal"),  "#4E9A06" },  /* green */
-	{ "$Labeltodo",      N_("_To Do"),     "#3465A4" },  /* blue */
-	{ "$Labellater",     N_("_Later"),     "#75507B" }   /* purple */
-};
-
 typedef struct {
 	GConfClient *gconf;
 
@@ -139,123 +129,6 @@
 	e_signature_list_save (config->signatures);
 }
 
-
-static void
-config_clear_labels (void)
-{
-	MailConfigLabel *label;
-	GSList *list, *n;
-
-	list = config->labels;
-	while (list != NULL) {
-		label = list->data;
-		g_free(label->tag);
-		g_free (label->name);
-		g_free (label->colour);
-		g_free (label);
-
-		n = list->next;
-		g_slist_free_1 (list);
-		list = n;
-	}
-
-	config->labels = NULL;
-}
-
-static void
-config_cache_labels (void)
-{
-	GSList *labels, *list, *head;
-	MailConfigLabel *label;
-	char *buf;
-	int num = 0;
-
-	labels = NULL;
-
-	head = gconf_client_get_list (config->gconf, "/apps/evolution/mail/labels", GCONF_VALUE_STRING, NULL);
-
-	for (list = head; list; list = list->next) {
-		char *color, *name, *tag;
-		name = buf = list->data;
-		color = strrchr (buf, ':');
-
-		*color++ = '\0';
-		tag = strchr (color, '|');
-		if (tag)
-			*tag++ = '\0';
-
-		label = g_new (MailConfigLabel, 1);
-
-		/* Needed for Backward Compatibility */
-		if (num < LABEL_DEFAULTS_NUM) {
-			label->name = g_strdup (_(buf));
-			label->tag = g_strdup (label_defaults[num].tag);
-			num++;
-		} else if (!tag) {
-			g_free (buf);
-			g_free (label);
-			continue;
-		} else {
-			label->name = g_strdup (name);
-			label->tag = g_strdup (tag);
-		}
-
-		label->colour = g_strdup (color);
-		labels = g_slist_prepend (labels, label);
-
-		g_free (buf);
-	}
-
-	if (head)
-		g_slist_free (head);
-
-	while (num < LABEL_DEFAULTS_NUM) {
-		/* complete the list with defaults */
-		label = g_new (MailConfigLabel, 1);
-		label->tag = g_strdup (label_defaults[num].tag);
-		label->name = g_strdup (_(label_defaults[num].name));
-		label->colour = g_strdup (label_defaults[num].colour);
-
-		labels = g_slist_prepend (labels, label);
-
-		num++;
-	}
-
-	config->labels = g_slist_reverse (labels);
-}
-
-/* stores the actual cache to gconf */
-static gboolean
-config_cache_labels_flush (void)
-{
-	GSList *l, *text_labels;
-
-	if (!config || !config->labels)
-		return FALSE;
-
-	text_labels = NULL;
-
-	for (l = config->labels; l; l = l->next) {
-		MailConfigLabel *label = l->data;
-
-		if (label && label->tag && label->name && label->colour)
-			text_labels = g_slist_prepend (text_labels, g_strdup_printf ("%s:%s|%s", label->name, label->colour, label->tag));
-	}
-
-	if (!text_labels)
-		return FALSE;
-
-	text_labels = g_slist_reverse (text_labels);
-
-	gconf_client_set_list (config->gconf, "/apps/evolution/mail/labels", GCONF_VALUE_STRING, text_labels, NULL);
-
-	g_slist_foreach (text_labels, (GFunc)g_free, NULL);
-	g_slist_free (text_labels);
-
-	/* not true if gconf failed to write; who cares */
-	return TRUE;
-}
-
 static void
 config_clear_mime_types (void)
 {
@@ -344,11 +217,30 @@
 }
 
 static void
+config_clear_labels (void)
+{
+	if (!config)
+		return;
+
+	e_util_labels_free (config->labels);
+	config->labels = NULL;
+}
+
+static void
+config_cache_labels (GConfClient *client)
+{
+	if (!config)
+		return;
+
+	config->labels = e_util_labels_parse (client);
+}
+
+static void
 gconf_labels_changed (GConfClient *client, guint cnxn_id,
 		      GConfEntry *entry, gpointer user_data)
 {
 	config_clear_labels ();
-	config_cache_labels ();
+	config_cache_labels (client);
 }
 
 static void
@@ -461,10 +353,10 @@
 	config->citation_colour_notify_id = gconf_client_notify_add (config->gconf, "/apps/evolution/mail/display/citation_colour",
 								     gconf_style_changed, NULL, NULL, NULL);
 
-	gconf_client_add_dir (config->gconf, "/apps/evolution/mail/labels",
+	gconf_client_add_dir (config->gconf, E_UTIL_LABELS_GCONF_KEY,
 			      GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
 	config->label_notify_id =
-		gconf_client_notify_add (config->gconf, "/apps/evolution/mail/labels",
+		gconf_client_notify_add (config->gconf, E_UTIL_LABELS_GCONF_KEY,
 					 gconf_labels_changed, NULL, NULL, NULL);
 
 	gconf_client_add_dir (config->gconf, "/apps/evolution/mail/mime_types",
@@ -473,7 +365,7 @@
 		gconf_client_notify_add (config->gconf, "/apps/evolution/mail/mime_types",
 					 gconf_mime_types_changed, NULL, NULL, NULL);
 
-	config_cache_labels ();
+	config_cache_labels (config->gconf);
 	config_cache_mime_types ();
 	config->address_compress = gconf_client_get_bool (config->gconf, "/apps/evolution/mail/display/address_compress", NULL);
 	config->address_count = gconf_client_get_int (config->gconf, "/apps/evolution/mail/display/address_count", NULL);
@@ -651,36 +543,10 @@
 	return config->magic_spacebar;
 }
 
-/* public Label functions */
-
-/**
- * config_get_label
- *
- * Looks for label in labels cache by tag and returns actual pointer to cache.
- * @param tag Tag of label you are looking for.
- * @return Pointer to cache data if label with such tag exists or NULL. Do not free it!
- **/
-static MailConfigLabel *
-config_get_label (const char *tag)
-{
-	GSList *l;
-
-	g_return_val_if_fail (tag != NULL, NULL);
-
-	for (l = config->labels; l; l = l->next) {
-		MailConfigLabel *label = l->data;
-	
-		if (label && label->tag && !strcmp (tag, label->tag))
-			return label;
-	}
-
-	return NULL;
-}
-
 /**
  * mail_config_get_labels
  *
- * @return list of known labels, each member data is MailConfigLabel structure.
+ * @return list of known labels, each member data is EUtilLabel structure.
  *         Returned list should not be freed, neither data inside it.
  **/
 GSList *
@@ -689,250 +555,6 @@
 	return config->labels;
 }
 
-/**
- * mail_config_get_next_label_tag
- *
- * @param id [out] if not NULL, then assigned used number of the next free tag.
- * @return Next free tag, which can be used for new label.
- *         Returned pointer should be freed with g_free.
- *
- * @note All labels should always start with "$Label" string, it's very important
- *       for filters and search folders!
- **/
-char *
-mail_config_get_next_label_tag (int *id)
-{
-	char *tag = NULL;
-	int count = LABEL_DEFAULTS_NUM;
-
-	/* who wants more than 100 labels? */
-	while (!tag && count <= 100) {
-		count++;
-		tag = g_strdup_printf ("$Label%d", count);
-
-		if (config_get_label (tag)) {
-			g_free (tag);
-			tag = NULL;
-		}
-	}
-
-	if (id)
-		*id = count;
-
-	return tag;
-}
-
-/**
- * mail_config_is_system_label
- *
- * @return Whether the tag is one of default/system labels or not.
- **/
-gboolean
-mail_config_is_system_label (const char *tag)
-{
-	int i;
-
-	if (!tag)
-		return FALSE;
-
-	for (i = 0; i < LABEL_DEFAULTS_NUM; i++) {
-		if (strcmp (tag, label_defaults[i].tag) == 0)
-			return TRUE;
-	}
-
-	return FALSE;
-}
-
-/**
- * mail_config_add_label
- * Creates new label at the end of actual list of labels.
- *
- * @param tag Unique identifier of this new label.
- * @param name User readable name of this label. Should not be NULL.
- * @param color Color assigned to this label. Should not be NULL.
- * @return Whether was added.
- **/
-gboolean
-mail_config_add_label (const char *tag, const char *name, const GdkColor *color)
-{
-	MailConfigLabel *label;
-
-	g_return_val_if_fail (tag != NULL, FALSE);
-	g_return_val_if_fail (name != NULL, FALSE);
-	g_return_val_if_fail (color != NULL, FALSE);
-
-	if (config_get_label (tag) != NULL)
-		return FALSE;
-
-	label = g_new0 (MailConfigLabel, 1);
-	label->tag = g_strdup (tag);
-	label->name = g_strdup (name);
-	label->colour = gdk_color_to_string (color);
-
-	config->labels = g_slist_append (config->labels, label);
-
-	return config_cache_labels_flush ();
-}
-
-/**
- * mail_config_remove_label
- *
- * @param tag Tag of the label to remove.
- * @return Whether was removed.
- **/
-gboolean
-mail_config_remove_label (const char *tag)
-{
-	MailConfigLabel *label;
-
-	g_return_val_if_fail (tag != NULL, FALSE);
-
-	label = config_get_label (tag);
-	if (!label)
-		return FALSE;
-
-	config->labels = g_slist_remove (config->labels, label);
-
-	g_free (label);
-
-	return config_cache_labels_flush ();
-}
-
-/**
- * mail_config_get_label_name
- *
- * @param tag Tag of the label of our interest.
- * @return Name of the label with that tag or NULL, if no such label exists.
- **/
-const char *
-mail_config_get_label_name (const char *tag)
-{
-	MailConfigLabel *label;
-
-	g_return_val_if_fail (tag != NULL, NULL);
-
-	label = config_get_label (tag);
-	if (!label)
-		return NULL;
-
-	return label->name;
-}
-
-/**
- * mail_config_get_label_color
- *
- * @param tag Tag of the label of our interest.
- * @param color [out] Actual color of the label with that tag, or unchanged if failed.
- * @return Whether found such label and color has been set.
- **/
-gboolean
-mail_config_get_label_color (const char *tag, GdkColor *color)
-{
-	MailConfigLabel *label;
-
-	g_return_val_if_fail (tag != NULL, FALSE);
-	g_return_val_if_fail (color != NULL, FALSE);
-
-	label = config_get_label (tag);
-	if (!label)
-		return FALSE;
-
-	return gdk_color_parse (label->colour, color);
-}
-
-/**
- * mail_config_get_label_color_str
- *
- * @param tag Tag of the label of our interest.
- * @return String representation of that label, or NULL, is no such label exists.
- **/
-const char *
-mail_config_get_label_color_str (const char *tag)
-{
-	MailConfigLabel *label;
-
-	g_return_val_if_fail (tag != NULL, FALSE);
-
-	label = config_get_label (tag);
-	if (!label)
-		return FALSE;
-
-	return label->colour;
-}
-
-/**
- * mail_config_get_new_label_tag
- *
- * @param old_tag Tag of the label from old version of Evolution.
- * @return New tag name equivalent with the old tag, or NULL if no such name existed before.
- **/
-const char *
-mail_config_get_new_label_tag (const char *old_tag)
-{
-	int i;
-
-	if (!old_tag)
-		return NULL;
-
-	for (i = 0; i < LABEL_DEFAULTS_NUM; i++) {
-		/* default labels have same name as those old, only with prefix "$Label" */
-		if (!strcmp (old_tag, label_defaults[i].tag + 6))
-			return label_defaults[i].tag;
-	}
-
-	return NULL;
-}
-
-/**
- * mail_config_set_label_name
- *
- * @param tag Tag of the label of our interest.
- * @param name New name for the label.
- * @return Whether successfully saved.
- **/
-gboolean
-mail_config_set_label_name (const char *tag, const char *name)
-{
-	MailConfigLabel *label;
-
-	g_return_val_if_fail (tag != NULL, FALSE);
-	g_return_val_if_fail (name != NULL, FALSE);
-
-	label = config_get_label (tag);
-	if (!label)
-		return FALSE;
-
-	g_free (label->name);
-	label->name = g_strdup (name);
-
-	return config_cache_labels_flush ();
-}
-
-/**
- * mail_config_set_label_color
- *
- * @param tag Tag of the label of our interest.
- * @param color New color for the label.
- * @return Whether successfully saved.
- **/
-gboolean
-mail_config_set_label_color (const char *tag, const GdkColor *color)
-{
-	MailConfigLabel *label;
-
-	g_return_val_if_fail (tag != NULL, FALSE);
-	g_return_val_if_fail (color != NULL, FALSE);
-
-	label = config_get_label (tag);
-	if (!label)
-		return FALSE;
-
-	g_free (label->colour);
-	label->colour = gdk_color_to_string (color);
-
-	return config_cache_labels_flush ();
-}
-
 const char **
 mail_config_get_allowable_mime_types (void)
 {

Modified: trunk/mail/mail-config.glade
==============================================================================
--- trunk/mail/mail-config.glade	(original)
+++ trunk/mail/mail-config.glade	Thu Jan 10 11:19:37 2008
@@ -5861,7 +5861,7 @@
 	  <child>
 	    <widget class="GtkLabel" id="label502">
 	      <property name="visible">True</property>
-	      <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Labels and Colors&lt;/span&gt;</property>
+	      <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot;&gt;Labels&lt;/span&gt;</property>
 	      <property name="use_underline">False</property>
 	      <property name="use_markup">True</property>
 	      <property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -6011,10 +6011,10 @@
 		      </child>
 
 		      <child>
-			<widget class="GtkButton" id="labelRemove">
+			<widget class="GtkButton" id="labelEdit">
 			  <property name="visible">True</property>
 			  <property name="can_focus">True</property>
-			  <property name="label">gtk-remove</property>
+			  <property name="label">gtk-edit</property>
 			  <property name="use_stock">True</property>
 			  <property name="relief">GTK_RELIEF_NORMAL</property>
 			  <property name="focus_on_click">True</property>
@@ -6027,78 +6027,16 @@
 		      </child>
 
 		      <child>
-			<widget class="GtkButton" id="labelColor">
+			<widget class="GtkButton" id="labelRemove">
 			  <property name="visible">True</property>
 			  <property name="can_focus">True</property>
+			  <property name="label">gtk-remove</property>
+			  <property name="use_stock">True</property>
 			  <property name="relief">GTK_RELIEF_NORMAL</property>
 			  <property name="focus_on_click">True</property>
-
-			  <child>
-			    <widget class="GtkAlignment" id="alignment36">
-			      <property name="visible">True</property>
-			      <property name="xalign">0.5</property>
-			      <property name="yalign">0.5</property>
-			      <property name="xscale">0</property>
-			      <property name="yscale">0</property>
-			      <property name="top_padding">0</property>
-			      <property name="bottom_padding">0</property>
-			      <property name="left_padding">0</property>
-			      <property name="right_padding">0</property>
-
-			      <child>
-				<widget class="GtkHBox" id="hbox243">
-				  <property name="visible">True</property>
-				  <property name="homogeneous">False</property>
-				  <property name="spacing">2</property>
-
-				  <child>
-				    <widget class="GtkImage" id="image11">
-				      <property name="visible">True</property>
-				      <property name="stock">gtk-select-color</property>
-				      <property name="icon_size">4</property>
-				      <property name="xalign">0.5</property>
-				      <property name="yalign">0.5</property>
-				      <property name="xpad">0</property>
-				      <property name="ypad">0</property>
-				    </widget>
-				    <packing>
-				      <property name="padding">0</property>
-				      <property name="expand">False</property>
-				      <property name="fill">False</property>
-				    </packing>
-				  </child>
-
-				  <child>
-				    <widget class="GtkLabel" id="label590">
-				      <property name="visible">True</property>
-				      <property name="label" translatable="yes">C_olor</property>
-				      <property name="use_underline">True</property>
-				      <property name="use_markup">False</property>
-				      <property name="justify">GTK_JUSTIFY_LEFT</property>
-				      <property name="wrap">False</property>
-				      <property name="selectable">False</property>
-				      <property name="xalign">0.5</property>
-				      <property name="yalign">0.5</property>
-				      <property name="xpad">0</property>
-				      <property name="ypad">0</property>
-				      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-				      <property name="width_chars">-1</property>
-				      <property name="single_line_mode">False</property>
-				      <property name="angle">0</property>
-				    </widget>
-				    <packing>
-				      <property name="padding">0</property>
-				      <property name="expand">False</property>
-				      <property name="fill">False</property>
-				    </packing>
-				  </child>
-				</widget>
-			      </child>
-			    </widget>
-			  </child>
 			</widget>
 			<packing>
-			  <property name="padding">10</property>
+			  <property name="padding">0</property>
 			  <property name="expand">False</property>
 			  <property name="fill">False</property>
 			</packing>
@@ -6138,7 +6076,7 @@
       <child>
 	<widget class="GtkLabel" id="lblColours">
 	  <property name="visible">True</property>
-	  <property name="label" translatable="yes">Colors</property>
+	  <property name="label" translatable="yes">Labels</property>
 	  <property name="use_underline">True</property>
 	  <property name="use_markup">False</property>
 	  <property name="justify">GTK_JUSTIFY_CENTER</property>

Modified: trunk/mail/mail-config.h
==============================================================================
--- trunk/mail/mail-config.h	(original)
+++ trunk/mail/mail-config.h	Thu Jan 10 11:19:37 2008
@@ -25,7 +25,6 @@
 
 #include <glib.h>
 #include <glib-object.h>
-#include <gdk/gdkcolor.h>
 
 #include "camel/camel-provider.h" /* can't forward-declare enums, bah */
 
@@ -88,15 +87,6 @@
 	MAIL_CONFIG_XMAILER_RUPERT_APPROVED = 4
 } MailConfigXMailerDisplayStyle;
 
-typedef struct {
-	char *tag;
-	char *name;
-	char *colour;
-} MailConfigLabel;
-
-#define LABEL_DEFAULTS_NUM 5
-extern MailConfigLabel label_defaults[LABEL_DEFAULTS_NUM];
-
 /* Configuration */
 void mail_config_init (void);
 void mail_config_clear (void);
@@ -109,17 +99,7 @@
 gboolean mail_config_is_configured            (void);
 gboolean mail_config_is_corrupt               (void);
 
-GSList *    mail_config_get_labels          (void);
-char *      mail_config_get_next_label_tag  (int *id);
-gboolean    mail_config_is_system_label     (const char *tag);
-gboolean    mail_config_add_label           (const char *tag, const char *name, const GdkColor *color);
-gboolean    mail_config_remove_label        (const char *tag);
-const char *mail_config_get_label_name      (const char *tag);
-gboolean    mail_config_get_label_color     (const char *tag, GdkColor *color);
-const char *mail_config_get_label_color_str (const char *tag);
-const char *mail_config_get_new_label_tag   (const char *old_tag);
-gboolean    mail_config_set_label_name      (const char *tag, const char *name);
-gboolean    mail_config_set_label_color     (const char *tag, const GdkColor *color);
+GSList *mail_config_get_labels (void);
 
 const char **mail_config_get_allowable_mime_types (void);
 

Modified: trunk/mail/message-list.c
==============================================================================
--- trunk/mail/message-list.c	(original)
+++ trunk/mail/message-list.c	Thu Jan 10 11:19:37 2008
@@ -52,6 +52,7 @@
 #include "e-util/e-profile-event.h"
 #include "e-util/e-util-private.h"
 #include "e-util/e-util.h"
+#include "e-util/e-util-labels.h"
 
 #include "misc/e-gui-utils.h"
 
@@ -1244,29 +1245,27 @@
 	const char *old_label;
 	int count = 0;
 	const CamelFlag *flag;
+	GSList *labels;
 
+	labels = mail_config_get_labels ();
 	str = g_string_new ("");
 
 	for (flag = camel_message_info_user_flags (msg_info); flag; flag = flag->next) {
-		/* We will be able to show in the column even unknown labels from
-		   other Evolution, because every label starts with "$Label".
-		   This doesn't apply for filters and search folders, but here
-		   we can see that we should add new labels to this Evolution too. */
-		if (strncmp (flag->name, "$Label", 6) == 0) {
-			const char *name = NULL;
+		const char *name = e_util_labels_get_name (labels, flag->name);
 
+		if (name) {
 			if (str->len)
 				g_string_append (str, ", ");
 
-			if (!get_tags)
-				name = mail_config_get_label_name (flag->name);
+			if (get_tags)
+				name = flag->name;
 
-			g_string_append (str, get_tags || !name ? flag->name : name);
+			g_string_append (str, name);
 			count++;
 		}
 	}
 
-	old_label = mail_config_get_new_label_tag (camel_message_info_user_tag (msg_info, "label"));
+	old_label = e_util_labels_get_new_tag (camel_message_info_user_tag (msg_info, "label"));
 
 	if (old_label != NULL) {
 		const char *name = NULL;
@@ -1275,9 +1274,9 @@
 			g_string_append (str, ", ");
 
 		if (!get_tags)
-			name = mail_config_get_label_name (old_label);
+			name = e_util_labels_get_name (labels, old_label);
 
-		g_string_append (str, get_tags || !name ? old_label : name);
+		g_string_append (str, (get_tags || !name) ? old_label : name);
 		++count;
 	}
 
@@ -1426,7 +1425,7 @@
 		if (colour == NULL) {
 			if ((n = get_all_labels (msg_info,  &labels_string, TRUE)) == 1) {
 
-				colour = mail_config_get_label_color_str (labels_string);
+				colour = e_util_labels_get_color_str (mail_config_get_labels (), labels_string);
 			} else if (camel_message_info_flags(msg_info) & CAMEL_MESSAGE_FLAGGED) {
 				/* FIXME: extract from the important.xpm somehow. */
 				colour = "#A7453E";

Modified: trunk/mail/message-list.etspec
==============================================================================
--- trunk/mail/message-list.etspec	(original)
+++ trunk/mail/message-list.etspec	Thu Jan 10 11:19:37 2008
@@ -7,15 +7,15 @@
 
   <ETableColumn model_col="3" _title="Attachment" pixbuf="attachment" expansion="0.0" minimum_width="18" resizable="false" cell="render_attachment" compare="integer" />
 
-  <ETableColumn model_col="4" compare_col="18" _title="From" expansion="1.0" minimum_width="32" resizable="true" cell="render_text" compare="address_compare" search="string" priority="10"/>
+  <ETableColumn model_col="4" compare_col="19" _title="From" expansion="1.0" minimum_width="32" resizable="true" cell="render_text" compare="address_compare" search="string" priority="10"/>
 
-  <ETableColumn model_col="5" compare_col="19" _title="Subject" expansion="1.6" minimum_width="32" resizable="true" cell="render_tree" compare="collate" search="string"/>
+  <ETableColumn model_col="5" compare_col="20" _title="Subject" expansion="1.6" minimum_width="32" resizable="true" cell="render_tree" compare="collate" search="string"/>
 
   <ETableColumn model_col="6" _title="Date" expansion="0.4" minimum_width="32" resizable="true" cell="render_date" compare="integer"/>
 
   <ETableColumn model_col="7" _title="Received" expansion="0.4" minimum_width="32" resizable="true" cell="render_date" compare="integer"/>
 
-  <ETableColumn model_col="8" compare_col="20" _title="To" expansion="1.0" minimum_width="32" resizable="true" cell="render_text" compare="address_compare" search="string" priority="5"/>
+  <ETableColumn model_col="8" compare_col="21" _title="To" expansion="1.0" minimum_width="32" resizable="true" cell="render_text" compare="address_compare" search="string" priority="5"/>
 
   <ETableColumn model_col="9" _title="Size" expansion="0.2" minimum_width="32" resizable="true" cell="render_size" compare="integer"/>
 

Modified: trunk/mail/vfoldertypes.xml
==============================================================================
--- trunk/mail/vfoldertypes.xml	(original)
+++ trunk/mail/vfoldertypes.xml	Thu Jan 10 11:19:37 2008
@@ -260,13 +260,13 @@
    <option value="is">
     <title>is</title>
     <code>
-       (match-all (or (= (user-tag "label") ${versus}) (user-flag (+ "$Label" ${versus}))))
+       (match-all (or (= (user-tag "label") ${versus}) (user-flag (+ "$Label" ${versus})) (user-flag ${versus})))
     </code>
    </option>
    <option value="is-not">
     <title>is not</title>
     <code>
-       (match-all (not (or (= (user-tag "label") ${versus}) (user-flag (+ "$Label" ${versus})))))
+       (match-all (not (or (= (user-tag "label") ${versus}) (user-flag (+ "$Label" ${versus})) (user-flag ${versus}))))
     </code>
    </option>
   </input>

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Thu Jan 10 11:19:37 2008
@@ -188,6 +188,7 @@
 e-util/e-error.c
 e-util/e-print.c
 e-util/e-system.error.xml
+e-util/e-util-labels.c
 filter/filter-datespec.c
 filter/filter-file.c
 filter/filter-input.c



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]