Re: [evolution-patches] Another custom headers patch



On Fri, 2003-12-05 at 08:47, Not Zed wrote:
> it still leaks :)
> 
> anyway only a copule of real issues left, see below

They should be fixed in this patch. Sorry for spamming the list with
endless patches :) I've fixed the crash, the remaining leak, and the
X-Evolution-whatsit header is now displayed and works correctly.

Cheers
Grahame

Index: mail/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/mail/ChangeLog,v
retrieving revision 1.2937
diff -u -r1.2937 ChangeLog
--- mail/ChangeLog	4 Dec 2003 22:40:39 -0000	1.2937
+++ mail/ChangeLog	5 Dec 2003 11:16:38 -0000
@@ -1,3 +1,49 @@
+2003-12-05  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.
+	
 2003-12-04  Jeffrey Stedfast  <fejj ximian com>
 
 	* em-folder-tree-model.c (em_folder_tree_model_remove_folders):
Index: mail/em-folder-view.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-folder-view.c,v
retrieving revision 1.18
diff -u -r1.18 em-folder-view.c
--- mail/em-folder-view.c	4 Dec 2003 17:10:51 -0000	1.18
+++ mail/em-folder-view.c	5 Dec 2003 11:16:45 -0000
@@ -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 @@
 	EMFV_MARK_SEEN_TIMEOUT,
 	EMFV_LOAD_HTTP,
 	EMFV_XMAILER_MASK,
+	EMFV_HEADERS,
 	EMFV_SETTINGS		/* last, for loop count */
 };
 
@@ -1916,6 +1918,7 @@
 	"mark_seen_timeout",
 	"load_http_images",
 	"xmailer_mask",
+	"headers",
 };
 
 static GHashTable *emfv_setting_key;
@@ -1979,6 +1982,34 @@
 	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; }
 	}
 }
 
Index: mail/em-format-html.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html.c,v
retrieving revision 1.15
diff -u -r1.15 em-format-html.c
--- mail/em-format-html.c	24 Nov 2003 22:35:33 -0000	1.15
+++ mail/em-format-html.c	5 Dec 2003 11:16:50 -0000
@@ -1441,10 +1441,7 @@
 			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");
Index: mail/em-mailer-prefs.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-mailer-prefs.c,v
retrieving revision 1.2
diff -u -r1.2 em-mailer-prefs.c
--- mail/em-mailer-prefs.c	4 Dec 2003 14:14:35 -0000	1.2
+++ mail/em-mailer-prefs.c	5 Dec 2003 11:16:50 -0000
@@ -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 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 @@
 	}
 }
 
+
+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 @@
 	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 @@
 	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 @@
 	GSList *list, *l, *n;
 	guint32 rgb;
 	int i, val;
+	GtkTreeIter iter;
+	gboolean valid;
+	GSList *header_list;
 	
 	/* General tab */
 	
@@ -475,6 +750,28 @@
 		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 @@
 
 	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;
+}
Index: mail/em-mailer-prefs.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-mailer-prefs.h,v
retrieving revision 1.4
diff -u -r1.4 em-mailer-prefs.h
--- mail/em-mailer-prefs.h	4 Dec 2003 14:14:35 -0000	1.4
+++ mail/em-mailer-prefs.h	5 Dec 2003 11:16:51 -0000
@@ -37,6 +37,7 @@
 #include <libgnomeui/gnome-font-picker.h>
 
 #include "evolution-config-control.h"
+#include "em-format.h"
 
 #include <shell/Evolution.h>
 
@@ -48,6 +49,13 @@
 
 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 @@
 	} 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 @@
 
 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
 
Index: mail/evolution-mail.schemas.in.in
===================================================================
RCS file: /cvs/gnome/evolution/mail/evolution-mail.schemas.in.in,v
retrieving revision 1.2
diff -u -r1.2 evolution-mail.schemas.in.in
--- mail/evolution-mail.schemas.in.in	4 Dec 2003 14:14:35 -0000	1.2
+++ mail/evolution-mail.schemas.in.in	5 Dec 2003 11:16:52 -0000
@@ -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 
+           &lt;header enabled&gt; - 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>
Index: mail/mail-config.glade
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-config.glade,v
retrieving revision 1.125
diff -u -r1.125 mail-config.glade
--- mail/mail-config.glade	4 Dec 2003 14:14:35 -0000	1.125
+++ mail/mail-config.glade	5 Dec 2003 11:17:05 -0000
@@ -4477,6 +4477,177 @@
       </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">&lt;b&gt;_Displayed Mail Headers&lt;/b&gt;</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>


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