diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2009-02-08 04:04:52 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2009-02-08 04:04:52 +0800 |
commit | 14e8637d6b1a98b4ed6bedc70d0fca744b7b3e0f (patch) | |
tree | ec49b42bc6e0cfb3115ca56f41106e63a0b67d85 /e-util | |
parent | fee5916b60c605ff5086d8fdc2a85c5ea21351f6 (diff) | |
download | gsoc2013-evolution-14e8637d6b1a98b4ed6bedc70d0fca744b7b3e0f.tar.gz gsoc2013-evolution-14e8637d6b1a98b4ed6bedc70d0fca744b7b3e0f.tar.zst gsoc2013-evolution-14e8637d6b1a98b4ed6bedc70d0fca744b7b3e0f.zip |
Rewrite the mail label code from top to bottom.
- Kill the e-util-labels API and read label information into a
single-column GtkListStore. Use GConfBridge to automatically
keep GConf synched with the list store.
- The list store (a singleton instance) is stored in EShellSettings
so it's available everywhere.
- The list store serves as the model for EMailLabelTreeView,
which itself is embedded in EMailLabelManager; a complete
label management UI as seen in the preferences dialog.
- EMailLabelDialog is used to add or edit a label. Avoid using a
color button, instead embed a GtkColorSelection directly in the
dialog so everything is in one window.
Open issues:
- The weird toggle/color/text menu items in the popup menu aren't
there. For now they're just regular toggle items. I'll deal
with it later.
- Filter intergration is broken at the moment.
svn path=/branches/kill-bonobo/; revision=37233
Diffstat (limited to 'e-util')
-rw-r--r-- | e-util/Makefile.am | 2 | ||||
-rw-r--r-- | e-util/e-util-labels.c | 586 | ||||
-rw-r--r-- | e-util/e-util-labels.h | 57 | ||||
-rw-r--r-- | e-util/gconf-bridge.c | 6 |
4 files changed, 3 insertions, 648 deletions
diff --git a/e-util/Makefile.am b/e-util/Makefile.am index 389694fb46..8131a820cd 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -79,7 +79,6 @@ eutilinclude_HEADERS = \ e-text-event-processor-types.h \ e-text-event-processor.h \ e-util.h \ - e-util-labels.h \ e-xml-utils.h libeutil_la_SOURCES = \ @@ -122,7 +121,6 @@ libeutil_la_SOURCES = \ 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 \ gconf-bridge.c \ diff --git a/e-util/e-util-labels.c b/e-util/e-util-labels.c deleted file mode 100644 index 85984da59c..0000000000 --- a/e-util/e-util-labels.c +++ /dev/null @@ -1,586 +0,0 @@ -/* - * 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 <http://www.gnu.org/licenses/> - * - * - * Authors: - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include <gtk/gtk.h> -#include <glib/gi18n.h> - -#include <stdio.h> -#include <string.h> - -#include <gconf/gconf-client.h> - -#include <camel/camel-utf8.h> - -#include "e-util.h" -#include "e-util-labels.h" -#include "e-dialog-utils.h" -#include "filter/filter-option.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, ':'); - if (color == NULL) { - g_free (buf); - continue; - } - - *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 && *buf) ? buf : _(label_defaults[num].name)); - 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_entry_set_activates_default (GTK_ENTRY (e), TRUE); - 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_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); - 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 = _("A label having the same tag already exists on the server. Please rename your label."); - 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; -} - -/** - * e_util_labels_get_filter_options: - * Returns list of newly allocated struct _filter_option-s, to be used in filters. - **/ -GSList * -e_util_labels_get_filter_options (void) -{ - GSList *known = e_util_labels_parse (NULL), *l; - GSList *res = NULL; - - for (l = known; l; l = l->next) { - EUtilLabel *label = l->data; - const char *tag; - struct _filter_option *fo; - - if (!label) - continue; - - tag = label->tag; - - if (tag && strncmp (tag, "$Label", 6) == 0) - tag += 6; - - fo = g_new0 (struct _filter_option, 1); - fo->title = e_str_without_underscores (label->name); - fo->value = g_strdup (tag); - - res = g_slist_prepend (res, fo); - } - - e_util_labels_free (known); - - return g_slist_reverse (res); -} diff --git a/e-util/e-util-labels.h b/e-util/e-util-labels.h deleted file mode 100644 index 26520ff226..0000000000 --- a/e-util/e-util-labels.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * 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 <http://www.gnu.org/licenses/> - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _E_UTIL_LABELS_H -#define _E_UTIL_LABELS_H - -#include <gtk/gtk.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); - -GSList * e_util_labels_get_filter_options (void); - -#endif /* _E_UTIL_LABELS_H */ diff --git a/e-util/gconf-bridge.c b/e-util/gconf-bridge.c index 451b7052cb..5accdcd71d 100644 --- a/e-util/gconf-bridge.c +++ b/e-util/gconf-bridge.c @@ -1082,17 +1082,17 @@ gconf_bridge_bind_string_list_store (GConfBridge *bridge, (list_store_binding_store_changed_cb), binding); binding->row_changed_id = - g_signal_connect_swapped (list_store, "row-inserted", + g_signal_connect_swapped (list_store, "row-changed", G_CALLBACK (list_store_binding_store_changed_cb), binding); binding->row_deleted_id = - g_signal_connect_swapped (list_store, "row-inserted", + g_signal_connect_swapped (list_store, "row-deleted", G_CALLBACK (list_store_binding_store_changed_cb), binding); binding->rows_reordered_id = - g_signal_connect_swapped (list_store, "row-inserted", + g_signal_connect_swapped (list_store, "rows-reordered", G_CALLBACK (list_store_binding_store_changed_cb), binding); |