diff options
-rw-r--r-- | mail/ChangeLog | 48 | ||||
-rw-r--r-- | mail/em-folder-view.c | 31 | ||||
-rw-r--r-- | mail/em-format-html.c | 5 | ||||
-rw-r--r-- | mail/em-mailer-prefs.c | 405 | ||||
-rw-r--r-- | mail/em-mailer-prefs.h | 19 | ||||
-rw-r--r-- | mail/evolution-mail.schemas.in.in | 18 | ||||
-rw-r--r-- | mail/mail-config.glade | 171 |
7 files changed, 690 insertions, 7 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index 4cb12cad6a..94fc17aa56 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,51 @@ +2003-12-11 Grahame Bowland <grahame@angrygoats.net> + + * em-format-html.c (efh_format_header): display + x-evolution-mailer pseudo header irrespective of + xmailer_mask. This is now handled by a header + configuration dialog. + + * mail-config.glade: add tab to mail configuration + dialog to allow custom headers to be specified for + display. + + * em-mailer-prefs.h: modify struct _EMMailerPrefs to + add widgets for custom header tab. Add defines for custom + header flags. Add struct EMMailerCustomHeader to describe + custom headers, and add function + em_mailer_custom_headers_from_xml to allow XML from gconf + key to be parsed into this structure. + + * em-folder-view.c (emfv_setting_notify): catch changes to + custom header gconf key and update mail view to correspond + + * em-mailer-prefs.c (em_mailer_prefs_apply): save custom + headers to gconf + (header_list_enabled_toggled): toggle clicked toggle column + (add_header): add header to custom header list if valid + (remove_header): remove selected custom header + (is_valid_header): return true if passed header is valid, + otherwise false + (entry_header_changed): call add_header_update_sensitivity + (em_mailer_prefs_construct): initialise header selection tab. + Load gconf data for header selection dialog. + (em_mailer_custom_header_to_xml): load a header structure + from XML document structure + (em_mailer_custom_header_from_xml): load a header + structure from a string containing valid XML. if any failure, + the header.name is set to NULL. + (header_list_row_selected): call + remove_header_update_sensitivity + (remove_header_update_sensitivity): set the sensitivity of + the remove button to FALSE if the list is empty or nothing + is selected. Otherwise, set it to TRUE. + (add_header_update_sensitivity): set the sensitivity of the + the add button to FALSE if the entry box is empty, contains + a duplicate header, or contains an invalid header. Otherwise, + set it to TRUE. + + * evolution-mail.schemas.in.in: add mail/display/headers + 2003-12-10 Larry Ewing <lewing@ximian.com> * em-format-html.c: add text/x-patch as a plain type. diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c index 5f7a1742e6..bb74f5b55e 100644 --- a/mail/em-folder-view.c +++ b/mail/em-folder-view.c @@ -62,6 +62,7 @@ #include "em-format-html-print.h" #include "em-folder-selection.h" #include "em-folder-view.h" +#include "em-mailer-prefs.h" #include "em-message-browser.h" #include "message-list.h" #include "em-utils.h" @@ -1901,6 +1902,7 @@ enum { EMFV_MARK_SEEN_TIMEOUT, EMFV_LOAD_HTTP, EMFV_XMAILER_MASK, + EMFV_HEADERS, EMFV_SETTINGS /* last, for loop count */ }; @@ -1916,6 +1918,7 @@ static const char * const emfv_display_keys[] = { "mark_seen_timeout", "load_http_images", "xmailer_mask", + "headers", }; static GHashTable *emfv_setting_key; @@ -1979,6 +1982,34 @@ emfv_setting_notify(GConfClient *gconf, guint cnxn_id, GConfEntry *entry, EMFold case EMFV_XMAILER_MASK: em_format_html_set_xmailer_mask((EMFormatHTML *)emfv->preview, gconf_value_get_int(gconf_entry_get_value(entry))); break; + case EMFV_HEADERS: { + GSList *header_config_list, *p; + EMFormat *emf = (EMFormat *)emfv->preview; + int added_headers = 0; + + header_config_list = gconf_client_get_list(gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, NULL); + em_format_clear_headers((EMFormat *)emfv->preview); + p = header_config_list; + while (p) { + EMMailerPrefsHeader *h; + char *xml = (char *)p->data; + + h = em_mailer_prefs_header_from_xml(xml); + if (h && h->enabled) { + em_format_add_header(emf, h->name, EM_FORMAT_HEADER_BOLD); + added_headers++; + } + em_mailer_prefs_header_free(h); + p = g_slist_next(p); + } + g_slist_foreach(header_config_list, (GFunc) g_free, NULL); + g_slist_free(header_config_list); + if (added_headers == 0) + em_format_default_headers(emf); + /* force a redraw */ + if (emf->message) + em_format_format_clone(emf, emf->message, emf); + break; } } } diff --git a/mail/em-format-html.c b/mail/em-format-html.c index db881e17a1..c3aa74440d 100644 --- a/mail/em-format-html.c +++ b/mail/em-format-html.c @@ -1451,10 +1451,7 @@ efh_format_header(EMFormat *emf, CamelStream *stream, CamelMedium *part, const c txt = camel_medium_get_header(part, "x-mailer"); if (txt == NULL) txt = camel_medium_get_header(part, "user-agent"); - if (txt == NULL - || ((efh->xmailer_mask & EM_FORMAT_HTML_XMAILER_OTHER) == 0 - && ((efh->xmailer_mask & EM_FORMAT_HTML_XMAILER_EVOLUTION) == 0 - || strstr(txt, "Evolution") == NULL))) + if (txt == NULL) return; label = _("Mailer"); diff --git a/mail/em-mailer-prefs.c b/mail/em-mailer-prefs.c index a4c5f2e25a..2143f78667 100644 --- a/mail/em-mailer-prefs.c +++ b/mail/em-mailer-prefs.c @@ -31,6 +31,7 @@ #include <gal/util/e-iconv.h> #include <gtkhtml/gtkhtml-properties.h> +#include <libxml/tree.h> #include "widgets/misc/e-charset-picker.h" #include <bonobo/bonobo-generic-factory.h> @@ -43,6 +44,30 @@ static void em_mailer_prefs_finalise (GObject *obj); static GtkVBoxClass *parent_class = NULL; +enum { + HEADER_LIST_NAME_COLUMN, /* displayable name of the header (may be a translation) */ + HEADER_LIST_ENABLED_COLUMN, /* is the header enabled? */ + HEADER_LIST_IS_DEFAULT_COLUMN, /* is this header a default header, eg From: */ + HEADER_LIST_HEADER_COLUMN, /* the real name of this header */ + HEADER_LIST_N_COLUMNS, +}; + +/* temporarily copied from em-format.c */ +static const struct { + const char *name; + guint32 flags; +} default_headers[] = { + { N_("From"), EM_FORMAT_HEADER_BOLD }, + { N_("Reply-To"), EM_FORMAT_HEADER_BOLD }, + { N_("To"), EM_FORMAT_HEADER_BOLD }, + { N_("Cc"), EM_FORMAT_HEADER_BOLD }, + { N_("Bcc"), EM_FORMAT_HEADER_BOLD }, + { N_("Subject"), EM_FORMAT_HEADER_BOLD }, + { N_("Date"), EM_FORMAT_HEADER_BOLD }, + { "x-evolution-mailer", 0 }, /* DO NOT translate */ +}; + +#define EM_FORMAT_HEADER_XMAILER "x-evolution-mailer" GtkType em_mailer_prefs_get_type (void) @@ -202,6 +227,153 @@ option_menu_connect (GtkOptionMenu *omenu, gpointer user_data) } } + +static void +emmp_header_remove_sensitivity (EMMailerPrefs *prefs) +{ + GtkTreeIter iter; + GtkTreeSelection *selection = gtk_tree_view_get_selection (prefs->header_list); + gboolean is_default; + + /* remove button should be sensitive if the currenlty selected entry in the list view + is not a default header. if there are no entries, or none is selected, it should be + disabled + */ + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { + gtk_tree_model_get (GTK_TREE_MODEL (prefs->header_list_store), &iter, + HEADER_LIST_IS_DEFAULT_COLUMN, &is_default, + -1); + if (is_default) + gtk_widget_set_sensitive (GTK_WIDGET (prefs->remove_header), FALSE); + else + gtk_widget_set_sensitive (GTK_WIDGET (prefs->remove_header), TRUE); + } else { + gtk_widget_set_sensitive (GTK_WIDGET (prefs->remove_header), FALSE); + } +} + +static gboolean +emmp_header_is_valid (const char *header) +{ + const char *p = header; + + if (strlen (header) == 0) + return FALSE; + while (*p) { + if ((*p == ':') || (*p == ' ')) + return FALSE; + p++; + } + return TRUE; +} + +static void +emmp_header_add_sensitivity (EMMailerPrefs *prefs) +{ + const char *entry_contents; + GtkTreeIter iter; + gboolean valid; + + /* the add header button should be sensitive if the text box contains + a valid header string, that is not a duplicate with something already + in the list view + */ + entry_contents = gtk_entry_get_text (GTK_ENTRY (prefs->entry_header)); + if (!emmp_header_is_valid (entry_contents)) { + gtk_widget_set_sensitive (GTK_WIDGET (prefs->add_header), FALSE); + return; + } + /* check if this is a duplicate */ + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (prefs->header_list_store), &iter); + while (valid) { + char *header_name; + + gtk_tree_model_get (GTK_TREE_MODEL (prefs->header_list_store), &iter, + HEADER_LIST_HEADER_COLUMN, &header_name, + -1); + if (g_ascii_strcasecmp (header_name, entry_contents) == 0) { + gtk_widget_set_sensitive (GTK_WIDGET(prefs->add_header), FALSE); + return; + } + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(prefs->header_list_store), &iter); + } + gtk_widget_set_sensitive (GTK_WIDGET (prefs->add_header), TRUE); +} + +static void +emmp_header_list_enabled_toggled (GtkCellRendererToggle *cell, const char *path_string, gpointer user_data) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; + GtkTreeModel *model = GTK_TREE_MODEL (prefs->header_list_store); + GtkTreePath *path = gtk_tree_path_new_from_string (path_string); + GtkTreeIter iter; + int enabled; + + gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_model_get (model, &iter, HEADER_LIST_ENABLED_COLUMN, &enabled, -1); + enabled = !enabled; + gtk_list_store_set (GTK_LIST_STORE (model), &iter, HEADER_LIST_ENABLED_COLUMN, + enabled, -1); + gtk_tree_path_free (path); + + if (prefs->control) + evolution_config_control_changed (prefs->control); +} + +static void +emmp_header_add_header (GtkWidget *widget, gpointer user_data) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; + GtkTreeModel *model = GTK_TREE_MODEL (prefs->header_list_store); + GtkTreeIter iter; + + gtk_list_store_append(GTK_LIST_STORE (model), &iter); + gtk_list_store_set(GTK_LIST_STORE (model), &iter, + HEADER_LIST_NAME_COLUMN, gtk_entry_get_text (prefs->entry_header), + HEADER_LIST_ENABLED_COLUMN, TRUE, + HEADER_LIST_HEADER_COLUMN, gtk_entry_get_text (prefs->entry_header), + HEADER_LIST_IS_DEFAULT_COLUMN, FALSE, + -1); + gtk_entry_set_text (prefs->entry_header, ""); + emmp_header_remove_sensitivity (prefs); + emmp_header_add_sensitivity (prefs); + + if (prefs->control) + evolution_config_control_changed (prefs->control); +} + +static void +emmp_header_remove_header (GtkWidget *button, gpointer user_data) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; + GtkTreeModel *model = GTK_TREE_MODEL (prefs->header_list_store); + GtkTreeSelection *selection = gtk_tree_view_get_selection (prefs->header_list); + GtkTreeIter iter; + + if (gtk_tree_selection_get_selected (selection, NULL, &iter)) { + gtk_list_store_remove (GTK_LIST_STORE (model), &iter); + emmp_header_remove_sensitivity (prefs); + if (prefs->control) + evolution_config_control_changed (prefs->control); + } +} + +static void +emmp_header_list_row_selected (GtkTreeSelection *selection, gpointer user_data) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; + + emmp_header_remove_sensitivity (prefs); +} + +static void +emmp_header_entry_changed (GtkWidget *entry, gpointer user_data) +{ + EMMailerPrefs *prefs = (EMMailerPrefs *) user_data; + + emmp_header_add_sensitivity (prefs); +} + static void em_mailer_prefs_construct (EMMailerPrefs *prefs) { @@ -209,10 +381,15 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) GSList *list; GladeXML *gui; gboolean bool; - char *font; + char *font, *buf; int i, val; - char *buf; - + GSList *header_config_list, *header_add_list, *p; + GtkTreeIter iter; + GHashTable *default_header_hash; + GtkTreeSelection *selection; + GtkCellRenderer *header_list_name_renderer; + GtkCellRenderer *header_list_enabled_renderer; + gui = glade_xml_new (EVOLUTION_GLADEDIR "/mail-config.glade", "preferences_tab", NULL); prefs->gui = gui; @@ -361,6 +538,101 @@ em_mailer_prefs_construct (EMMailerPrefs *prefs) prefs->restore_labels = GTK_BUTTON (glade_xml_get_widget (gui, "cmdRestoreLabels")); g_signal_connect (prefs->restore_labels, "clicked", G_CALLBACK (restore_labels_clicked), prefs); + /* headers */ + prefs->add_header = GTK_BUTTON (glade_xml_get_widget (gui, "cmdHeadersAdd")); + prefs->remove_header = GTK_BUTTON (glade_xml_get_widget (gui, "cmdHeadersRemove")); + prefs->entry_header = GTK_ENTRY (glade_xml_get_widget (gui, "txtHeaders")); + prefs->header_list = GTK_TREE_VIEW (glade_xml_get_widget (gui, "treeHeaders")); + selection = gtk_tree_view_get_selection (prefs->header_list); + g_signal_connect (selection, "changed", G_CALLBACK (emmp_header_list_row_selected), prefs); + g_signal_connect (prefs->entry_header, "changed", G_CALLBACK (emmp_header_entry_changed), prefs); + g_signal_connect (prefs->entry_header, "activate", G_CALLBACK (emmp_header_add_header), prefs); + /* initialise the tree with appropriate headings */ + prefs->header_list_store = gtk_list_store_new (HEADER_LIST_N_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING); + g_signal_connect (prefs->add_header, "clicked", G_CALLBACK (emmp_header_add_header), prefs); + g_signal_connect (prefs->remove_header, "clicked", G_CALLBACK (emmp_header_remove_header), prefs); + gtk_tree_view_set_model (prefs->header_list, GTK_TREE_MODEL (prefs->header_list_store)); + + header_list_enabled_renderer = gtk_cell_renderer_toggle_new (); + g_object_set (header_list_enabled_renderer, "activatable", TRUE, NULL); + g_signal_connect (header_list_enabled_renderer, "toggled", G_CALLBACK (emmp_header_list_enabled_toggled), prefs); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (prefs->header_list), -1, + "Enabled", header_list_enabled_renderer, + "active", HEADER_LIST_ENABLED_COLUMN, + NULL); + header_list_name_renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (prefs->header_list), -1, + "Name", header_list_name_renderer, + "text", HEADER_LIST_NAME_COLUMN, + NULL); + + /* populated the listview with entries; firstly we add all the default headers, and then + we add read header configuration out of gconf. If a header in gconf is a default header, + we update the enabled flag accordingly + */ + header_add_list = NULL; + default_header_hash = g_hash_table_new (g_str_hash, g_str_equal); + for (i = 0; i < sizeof (default_headers) / sizeof (default_headers[0]); i++) { + struct _EMMailerPrefsHeader *h; + + + h = g_malloc (sizeof (struct _EMMailerPrefsHeader)); + h->is_default = TRUE; + h->name = g_strdup(default_headers[i].name); + if (g_ascii_strcasecmp (default_headers[i].name, EM_FORMAT_HEADER_XMAILER) == 0) + h->enabled = FALSE; + else + h->enabled = TRUE; + g_hash_table_insert (default_header_hash, (gpointer)default_headers[i].name, h); + header_add_list = g_slist_append (header_add_list, h); + } + + /* read stored headers from gconf */ + header_config_list = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, NULL); + p = header_config_list; + while (p) { + char *xml = (char *)p->data; + struct _EMMailerPrefsHeader *h, *def; + + h = em_mailer_prefs_header_from_xml (xml); + if (h) { + def = (struct _EMMailerPrefsHeader *)g_hash_table_lookup (default_header_hash, h->name); + if (def) { + def->enabled = h->enabled; + em_mailer_prefs_header_free(h); + } else { + h->is_default = FALSE; + header_add_list = g_slist_append (header_add_list, h); + } + } + p = g_slist_next (p); + } + g_hash_table_destroy (default_header_hash); + g_slist_foreach (header_config_list, (GFunc) g_free, NULL); + g_slist_free (header_config_list); + + p = header_add_list; + while (p) { + struct _EMMailerPrefsHeader *h = (struct _EMMailerPrefsHeader *)p->data; + const char *name; + + if (g_ascii_strcasecmp (h->name, EM_FORMAT_HEADER_XMAILER) == 0) + name = _("Mailer"); + else + name = _(h->name); + gtk_list_store_append (prefs->header_list_store, &iter); + gtk_list_store_set (prefs->header_list_store, &iter, + HEADER_LIST_NAME_COLUMN, name, + HEADER_LIST_ENABLED_COLUMN, h->enabled, + HEADER_LIST_IS_DEFAULT_COLUMN, h->is_default, + HEADER_LIST_HEADER_COLUMN, h->name, + -1); + em_mailer_prefs_header_free(h); + p = g_slist_next(p); + } + g_slist_free (header_add_list); + emmp_header_remove_sensitivity (prefs); + /* Junk prefs */ prefs->check_incoming = GTK_TOGGLE_BUTTON (glade_xml_get_widget (gui, "chkCheckIncomingMail")); bool = gconf_client_get_bool (prefs->gconf, "/apps/evolution/mail/junk/check_incoming", NULL); @@ -390,6 +662,9 @@ em_mailer_prefs_apply (EMMailerPrefs *prefs) GSList *list, *l, *n; guint32 rgb; int i, val; + GtkTreeIter iter; + gboolean valid; + GSList *header_list; /* General tab */ @@ -475,6 +750,28 @@ em_mailer_prefs_apply (EMMailerPrefs *prefs) g_slist_free_1 (l); l = n; } + + /* Headers */ + header_list = NULL; + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (prefs->header_list_store), &iter); + while (valid) { + struct _EMMailerPrefsHeader h; + gboolean enabled; + char *xml; + + gtk_tree_model_get (GTK_TREE_MODEL (prefs->header_list_store), &iter, + HEADER_LIST_HEADER_COLUMN, &h.name, + HEADER_LIST_ENABLED_COLUMN, &enabled, + -1); + h.enabled = enabled; + xml = em_mailer_prefs_header_to_xml (&h); + if (xml != NULL) + header_list = g_slist_append (header_list, xml); + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (prefs->header_list_store), &iter); + } + gconf_client_set_list (prefs->gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, header_list, NULL); + g_slist_foreach (header_list, (GFunc) g_free, NULL); + g_slist_free (header_list); /* junk prefs */ gconf_client_set_bool (prefs->gconf, "/apps/evolution/mail/junk/check_incoming", @@ -482,3 +779,105 @@ em_mailer_prefs_apply (EMMailerPrefs *prefs) gconf_client_suggest_sync (prefs->gconf, NULL); } + +static struct _EMMailerPrefsHeader * +emmp_header_from_xmldoc (xmlDocPtr doc) +{ + xmlNodePtr root; + xmlChar *name; + struct _EMMailerPrefsHeader *h; + + if (doc == NULL) + return NULL; + root = doc->children; + if (strcmp (root->name, "header") != 0) + return NULL; + name = xmlGetProp (root, "name"); + if (name == NULL) + return NULL; + h = g_malloc0 (sizeof (struct _EMMailerPrefsHeader)); + h->name = g_strdup (name); + xmlFree (name); + if (xmlHasProp (root, "enabled")) + h->enabled = 1; + else + h->enabled = 0; + return h; +} + +/** + * em_mailer_prefs_header_from_xml + * @xml: XML configuration data + * + * Parses passed XML data, which should be of + * the format <header name="foo" enabled />, and + * returns a EMMailerPrefs structure, or NULL if there + * is an error. + **/ +struct _EMMailerPrefsHeader * +em_mailer_prefs_header_from_xml (const char *xml) +{ + xmlDocPtr doc; + struct _EMMailerPrefsHeader *header; + + doc = xmlParseDoc ((char *)xml); + if (doc == NULL) + return NULL; + header = emmp_header_from_xmldoc (doc); + xmlFreeDoc (doc); + return header; +} + +/** + * em_mailer_prefs_header_free + * @header: header to free + * + * Frees the memory associated with the passed header + * structure. + */ +void +em_mailer_prefs_header_free (struct _EMMailerPrefsHeader *header) +{ + if (header == NULL) + return; + g_free (header->name); + g_free (header); +} + +/** + * em_mailer_prefs_header_to_xml + * @header: header from which to generate XML + * + * Returns the passed header as a XML structure, + * or NULL on error + */ +char * +em_mailer_prefs_header_to_xml (struct _EMMailerPrefsHeader *header) +{ + xmlDocPtr doc; + xmlNodePtr root; + xmlChar *xml; + char *out; + int size; + + g_return_val_if_fail (header != NULL, NULL); + g_return_val_if_fail (header->name != NULL, NULL); + + doc = xmlNewDoc ("1.0"); + + root = xmlNewDocNode (doc, NULL, "header", NULL); + xmlSetProp (root, "name", header->name); + if (header->enabled) + xmlSetProp (root, "enabled", NULL); + + xmlDocSetRootElement (doc, root); + xmlDocDumpMemory (doc, &xml, &size); + xmlFreeDoc (doc); + + out = g_malloc (size + 1); + memcpy (out, xml, size); + out[size] = 0; + xmlFree (xml); + + return out; +} diff --git a/mail/em-mailer-prefs.h b/mail/em-mailer-prefs.h index 27de7b3ca9..60c362607c 100644 --- a/mail/em-mailer-prefs.h +++ b/mail/em-mailer-prefs.h @@ -37,6 +37,7 @@ extern "C" { #include <libgnomeui/gnome-font-picker.h> #include "evolution-config-control.h" +#include "em-format.h" #include <shell/Evolution.h> @@ -48,6 +49,13 @@ extern "C" { typedef struct _EMMailerPrefs EMMailerPrefs; typedef struct _EMMailerPrefsClass EMMailerPrefsClass; +typedef struct _EMMailerPrefsHeader EMMailerPrefsHeader; + +struct _EMMailerPrefsHeader { + char *name; + int enabled:1; + int is_default:1; +}; struct _EMMailerPrefs { GtkVBox parent_object; @@ -99,6 +107,13 @@ struct _EMMailerPrefs { } labels[5]; GtkButton *restore_labels; + /* Headers tab */ + GtkButton *add_header; + GtkButton *remove_header; + GtkEntry *entry_header; + GtkTreeView *header_list; + GtkListStore *header_list_store; + /* Junk prefs */ GtkToggleButton *check_incoming; }; @@ -117,6 +132,10 @@ GtkWidget *em_mailer_prefs_new (void); void em_mailer_prefs_apply (EMMailerPrefs *prefs); +EMMailerPrefsHeader *em_mailer_prefs_header_from_xml(const char *xml); +char *em_mailer_prefs_header_to_xml(EMMailerPrefsHeader *header); +void em_mailer_prefs_header_free(EMMailerPrefsHeader *header); + /* needed by global config */ #define EM_MAILER_PREFS_CONTROL_ID "OAFIID:GNOME_Evolution_Mail_MailerPrefs_ConfigControl:" BASE_VERSION diff --git a/mail/evolution-mail.schemas.in.in b/mail/evolution-mail.schemas.in.in index 297d158d6b..7f8d6a25c3 100644 --- a/mail/evolution-mail.schemas.in.in +++ b/mail/evolution-mail.schemas.in.in @@ -233,6 +233,24 @@ </schema> <schema> + <key>/schemas/apps/evolution/mail/display/headers</key> + <applyto>/apps/evolution/mail/display/headers</applyto> + <owner>evolution-mail</owner> + <type>list</type> + <list_type>string</list_type> + <default>[]</default> + <locale name="C"> + <short>List of custom headers and whether they are enabled.</short> + <long> + This key should contain a list of XML structures specifying custom headers, + and whether they are to be displayed. The format of the XML structure is + <header enabled> - set enabled if the header is to be displayed + in the mail view. + </long> + </locale> + </schema> + + <schema> <key>/schemas/apps/evolution/mail/display/mime_types</key> <applyto>/apps/evolution/mail/display/mime_types</applyto> <owner>evolution-mail</owner> diff --git a/mail/mail-config.glade b/mail/mail-config.glade index 7b451f0a56..b900f19870 100644 --- a/mail/mail-config.glade +++ b/mail/mail-config.glade @@ -4477,6 +4477,177 @@ For example: "Work" or "Personal"</property> </child> <child> + <widget class="GtkVBox" id="vboxHeaderTab"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="lblHeaders"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>_Displayed Mail Headers</b></property> + <property name="use_underline">True</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="mnemonic_widget">txtHeaders</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkHBox" id="hboxTreeButtons"> + <property name="border_width">6</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkVBox" id="vboxEntryTree"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">6</property> + + <child> + <widget class="GtkEntry" id="txtHeaders"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char" translatable="yes">*</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow49"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="treeHeaders"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">False</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox162"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkButton" id="cmdHeadersAdd"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="can_focus">True</property> + <property name="label">gtk-add</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + </widget> + <packing> + <property name="padding">6</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="cmdHeadersRemove"> + <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> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">6</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="lblHeaders"> + <property name="visible">True</property> + <property name="label" translatable="yes">H_eaders</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> + </widget> + <packing> + <property name="type">tab</property> + </packing> + </child> + + <child> <widget class="GtkVBox" id="vbox161"> <property name="border_width">6</property> <property name="visible">True</property> |