diff options
Diffstat (limited to 'mail')
-rw-r--r-- | mail/ChangeLog | 23 | ||||
-rw-r--r-- | mail/em-filter-i18n.h | 6 | ||||
-rw-r--r-- | mail/em-folder-browser.c | 29 | ||||
-rw-r--r-- | mail/em-folder-view.c | 25 | ||||
-rw-r--r-- | mail/em-mailer-prefs.c | 229 | ||||
-rw-r--r-- | mail/em-mailer-prefs.h | 3 | ||||
-rw-r--r-- | mail/filtertypes.xml | 4 | ||||
-rw-r--r-- | mail/mail-config.c | 428 | ||||
-rw-r--r-- | mail/mail-config.glade | 78 | ||||
-rw-r--r-- | mail/mail-config.h | 22 | ||||
-rw-r--r-- | mail/message-list.c | 25 | ||||
-rw-r--r-- | mail/message-list.etspec | 6 | ||||
-rw-r--r-- | mail/vfoldertypes.xml | 4 |
13 files changed, 216 insertions, 666 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index 3315c1b57c..3f50c66c3f 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,26 @@ +2008-01-10 Milan Crha <mcrha@redhat.com> + + ** Fix for bug #211353 + + * filtertypes.xml: + * vfoldertypes.xml: + * em-folder-view.c: + * em-folder-browser.c: + * em-mailer-prefs.h: + * em-mailer-prefs.c: + * mail-config.h: + * mail-config.c: + * mail-config.glade: + * 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. + * message-list.etspec: Normalized columns has been moved by one + when label column has been added. + 2008-01-10 Srinivasa Ragavan <sragavan@novell.com> ** Most of the errors are now non-intrusive diff --git a/mail/em-filter-i18n.h b/mail/em-filter-i18n.h index 7f11882c97..7db8144860 100644 --- a/mail/em-filter-i18n.h +++ b/mail/em-filter-i18n.h @@ -3,7 +3,10 @@ char *s = N_("Adjust Score"); 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 greater than"); 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_("returns less than"); 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"); diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c index 5b11c11a18..12d02e4b27 100644 --- a/mail/em-folder-browser.c +++ b/mail/em-folder-browser.c @@ -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 @@ generate_viewoption_menu (GtkWidget *emfv) } /* 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 @@ generate_viewoption_menu (GtkWidget *emfv) 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 @@ viewoption_menu_generator () 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 @@ emfb_init(GObject *o) 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 @@ get_view_query (ESearchBar *esb, CamelFolder *folder, const char *folder_uri) 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 @@ get_view_query (ESearchBar *esb, CamelFolder *folder, const char *folder_uri) } 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: diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c index 97b7359402..c745ebf073 100644 --- a/mail/em-folder-view.c +++ b/mail/em-folder-view.c @@ -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 @@ emfv_popup_label_clear(EPopup *ep, EPopupItem *pitem, void *data) { 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 @@ emfv_popup_label_set(EPopup *ep, EPopupItem *pitem, void *data) } 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 @@ static EPopupItem emfv_popup_items[] = { { 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 @@ emfv_popup_labels_get_state_for_tag (EMFolderView *emfv, GPtrArray *uids, const 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 @@ emfv_popup(EMFolderView *emfv, GdkEvent *event, int on_display) 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; diff --git a/mail/em-mailer-prefs.c b/mail/em-mailer-prefs.c index ef4a6d64c8..85a2ce1e32 100644 --- a/mail/em-mailer-prefs.c +++ b/mail/em-mailer-prefs.c @@ -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 @@ em_mailer_prefs_finalise (GObject *obj) 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 @@ enum { }; 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 @@ label_sensitive_buttons (EMMailerPrefs *prefs) 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 @@ label_sensitive_buttons (EMMailerPrefs *prefs) } 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_tree_cursor_changed (GtkWidget *widget, gpointer user_data) 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 @@ init_label_tree (GtkWidget *label_tree, EMMailerPrefs *prefs, gboolean locked) 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 @@ init_label_tree (GtkWidget *label_tree, EMMailerPrefs *prefs, gboolean locked) 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)); - - 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); + char *tag; - 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 @@ label_remove_cb (GtkWidget *widget, gpointer user_data) 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 @@ label_color_cb (GtkWidget *widget, gpointer user_data) 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 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) 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 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) 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 */ diff --git a/mail/em-mailer-prefs.h b/mail/em-mailer-prefs.h index a9a4327cb7..16df0a93f4 100644 --- a/mail/em-mailer-prefs.h +++ b/mail/em-mailer-prefs.h @@ -104,10 +104,11 @@ struct _EMMailerPrefs { /* 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; diff --git a/mail/filtertypes.xml b/mail/filtertypes.xml index 1f8d39b34c..74029112d1 100644 --- a/mail/filtertypes.xml +++ b/mail/filtertypes.xml @@ -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> diff --git a/mail/mail-config.c b/mail/mail-config.c index ef9185ecbd..2a483750c8 100644 --- a/mail/mail-config.c +++ b/mail/mail-config.c @@ -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 @@ mail_config_save_signatures (void) 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 @@ config_write_style (void) } 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 @@ mail_config_init (void) 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 @@ mail_config_init (void) 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 @@ mail_config_get_enable_magic_spacebar () 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 @@ mail_config_get_labels (void) 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) { diff --git a/mail/mail-config.glade b/mail/mail-config.glade index be41d9fb59..7e08e2b01b 100644 --- a/mail/mail-config.glade +++ b/mail/mail-config.glade @@ -5861,7 +5861,7 @@ For example: "Work" or "Personal"</property> <child> <widget class="GtkLabel" id="label502"> <property name="visible">True</property> - <property name="label" translatable="yes"><span weight="bold">Labels and Colors</span></property> + <property name="label" translatable="yes"><span weight="bold">Labels</span></property> <property name="use_underline">False</property> <property name="use_markup">True</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -6011,10 +6011,10 @@ For example: "Work" or "Personal"</property> </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 @@ For example: "Work" or "Personal"</property> </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 @@ For example: "Work" or "Personal"</property> <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> diff --git a/mail/mail-config.h b/mail/mail-config.h index 454a44f2bf..c08eaf34a4 100644 --- a/mail/mail-config.h +++ b/mail/mail-config.h @@ -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 @@ typedef enum { 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 @@ struct _GConfClient *mail_config_get_gconf_client (void); 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); diff --git a/mail/message-list.c b/mail/message-list.c index 6920141b27..e81093cc93 100644 --- a/mail/message-list.c +++ b/mail/message-list.c @@ -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 @@ get_all_labels (CamelMessageInfo *msg_info, char **label_str, gboolean get_tags) 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 @@ get_all_labels (CamelMessageInfo *msg_info, char **label_str, gboolean get_tags) 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 @@ ml_tree_value_at (ETreeModel *etm, ETreePath path, int col, void *model_data) 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"; diff --git a/mail/message-list.etspec b/mail/message-list.etspec index 4581bc354f..bd2ec76554 100644 --- a/mail/message-list.etspec +++ b/mail/message-list.etspec @@ -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"/> diff --git a/mail/vfoldertypes.xml b/mail/vfoldertypes.xml index a0ef98a717..2ccb552cb5 100644 --- a/mail/vfoldertypes.xml +++ b/mail/vfoldertypes.xml @@ -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> |