[evolution-patches] Patch for custom mail headers



Hi all

I sent an older version of this to NotZed and fejj yesterday, but 
haven't heard back - I'm being impatient :-) The patch does 
seems to work, could I have some feedback?

Config dialog screenshot: 
http://grahame.angrygoats.net/images/custom-mail-headers.png
Viewing a mail:
http://grahame.angrygoats.net/images/custom-mail-headers-view.png

Patch attached, it should apply to the current CVS version of 
evolution.

Oh, the patch is for Ximian Bug #1186 and #127523 in Gnome 
bugzilla.

Cheers
Grahame

Index: mail/em-folder-view.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-folder-view.c,v
retrieving revision 1.14
diff -u -r1.14 em-folder-view.c
--- mail/em-folder-view.c	14 Nov 2003 16:20:17 -0000	1.14
+++ mail/em-folder-view.c	27 Nov 2003 18:53:12 -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"
@@ -1896,6 +1897,8 @@
 	EMFV_MARK_SEEN_TIMEOUT,
 	EMFV_LOAD_HTTP,
 	EMFV_XMAILER_MASK,
+	EMFV_HEADERS,
+	EMFV_HEADERS_FLAGS,
 	EMFV_SETTINGS		/* last, for loop count */
 };
 
@@ -1911,6 +1914,8 @@
 	"mark_seen_timeout",
 	"load_http_images",
 	"xmailer_mask",
+	"headers",
+	"headers_flags",
 };
 
 static GHashTable *emfv_setting_key;
@@ -1974,6 +1979,27 @@
 	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:
+	case EMFV_HEADERS_FLAGS: {
+		GSList *header_config_list, *header_flags_config_list, *p, *q;
+		header_config_list = gconf_client_get_list (gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, NULL);
+		header_flags_config_list = gconf_client_get_list (gconf, "/apps/evolution/mail/display/headers_flags", GCONF_VALUE_INT, NULL);
+      		em_format_clear_headers((EMFormat *)emfv->preview);
+		em_format_default_headers((EMFormat *)emfv->preview);
+		p = header_config_list;
+		q = header_flags_config_list;
+		while (p && q) {
+			gint header_flags = 0;
+			if (GPOINTER_TO_INT(q->data) & EM_MAILER_PREFS_FLAGS_BOLD) {
+				header_flags |= EM_FORMAT_HEADER_BOLD;
+			}
+			em_format_add_header((EMFormat *)emfv->preview, (gchar *)p->data, header_flags);
+			p = g_slist_next(p);
+			q = g_slist_next(q);
+		}
+		g_slist_free(header_config_list);
+		g_slist_free(header_flags_config_list);
+		break; }
 	}
 }
 
Index: mail/em-mailer-prefs.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-mailer-prefs.c,v
retrieving revision 1.1
diff -u -r1.1 em-mailer-prefs.c
--- mail/em-mailer-prefs.c	24 Oct 2003 19:31:22 -0000	1.1
+++ mail/em-mailer-prefs.c	27 Nov 2003 18:53:14 -0000
@@ -43,6 +43,12 @@
 
 static GtkVBoxClass *parent_class = NULL;
 
+enum {
+	HEADER_LIST_NAME_COLUMN, 
+	HEADER_LIST_BOLD_COLUMN,
+	HEADER_LIST_N_COLUMNS
+};
+
 
 GtkType
 em_mailer_prefs_get_type (void)
@@ -203,6 +209,172 @@
 }
 
 static void
+header_sanitize_name(gchar *header)
+{
+	gchar *p = header;
+	while (*p) {
+		if (*p == ' ') {
+			*p = '-';
+		}
+		p++;
+	}
+	if (p == header) {
+		return;
+	}
+	p--;
+	/* back up removing trailing colon characters.. */
+	while ((p >= header) && (*p == ':')) {
+		*p = '\0';
+		p--;
+	}
+}
+
+static void
+header_list_cell_edited (GtkCellRendererText *cell, const gchar *path_string, const gchar *new_text, 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;
+	gchar *old_text, *new_header;
+	gint i;
+	gboolean valid;
+
+	/* we want to make sure this is a valid header */
+	new_header = g_strdup(new_text);
+	header_sanitize_name(new_header);
+	/* no zero length headers */
+	if (strlen(new_header) == 0) {
+		g_free(new_header);
+		return;
+	}
+
+	/* check that the header isn't a duplicate.. */
+	valid = gtk_tree_model_get_iter_first (model, &iter);
+	i = 0;
+	while (valid) {
+		gchar *header_name;
+		gtk_tree_model_get (GTK_TREE_MODEL(prefs->header_list_store), &iter, 
+				    HEADER_LIST_NAME_COLUMN, &header_name, 
+				    -1);
+		if (!strcasecmp(header_name, new_header)) {
+			i++;
+		}
+		g_free(header_name);
+		valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(prefs->header_list_store), &iter);
+	}
+	if (i > 0) {
+		/* duplicate... reject the edit */
+		g_free(new_header);
+		return;
+	}
+	gtk_tree_model_get_iter (model, &iter, path);
+	gtk_tree_model_get (model, &iter, HEADER_LIST_NAME_COLUMN, &old_text, -1);
+	g_free (old_text);
+	
+	gtk_list_store_set(GTK_LIST_STORE(model), &iter, HEADER_LIST_NAME_COLUMN, 
+			   new_header, -1);
+	gtk_tree_path_free(path);
+
+	if (prefs->control)
+		evolution_config_control_changed (prefs->control);
+}
+
+static void
+header_list_bold_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;
+	gint enabled;
+
+	gtk_tree_model_get_iter (model, &iter, path);
+	gtk_tree_model_get (model, &iter, HEADER_LIST_BOLD_COLUMN, &enabled, -1);
+	enabled = !enabled;
+	gtk_list_store_set(GTK_LIST_STORE(model), &iter, HEADER_LIST_BOLD_COLUMN,
+			   enabled, -1);
+	gtk_tree_path_free(path);
+
+	if (prefs->control)
+		evolution_config_control_changed (prefs->control);
+}
+
+static void
+add_header (GtkWidget *button, gpointer user_data)
+{
+	EMMailerPrefs *prefs = (EMMailerPrefs *) user_data;
+	GtkTreeModel *model = GTK_TREE_MODEL(prefs->header_list_store);
+	GtkTreeIter iter;
+	gint loops = 0;
+	gint matches;
+	gchar *new_header_name = NULL;
+
+	/* find an initial name for the header */
+	do {
+		gboolean valid;
+		if (new_header_name) {
+			g_free(new_header_name);
+		}
+		if (loops == 0) {
+			new_header_name = g_strdup("New-header");
+		} else {
+			new_header_name = g_strdup_printf("New-header-%d", loops);
+		}
+		matches = 0;
+		valid = gtk_tree_model_get_iter_first (model, &iter);
+		while (valid) {
+			gchar *header_name;
+			gtk_tree_model_get (GTK_TREE_MODEL(prefs->header_list_store), &iter, 
+					    HEADER_LIST_NAME_COLUMN, &header_name, 
+					    -1);
+			if (!strcasecmp(header_name, new_header_name)) {
+				matches++;
+			}
+			g_free(header_name);
+			valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(prefs->header_list_store), &iter);
+		}
+		loops++;
+	} while (matches > 0);
+	gtk_list_store_append(GTK_LIST_STORE(model), &iter);
+	gtk_list_store_set(GTK_LIST_STORE(model), &iter, 
+			   HEADER_LIST_NAME_COLUMN, new_header_name, 
+			   HEADER_LIST_BOLD_COLUMN, FALSE, 
+			   -1);
+	if (!GTK_WIDGET_SENSITIVE(GTK_WIDGET(prefs->remove_header))) {
+		GtkTreeSelection *selection = gtk_tree_view_get_selection (prefs->header_list);
+		gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
+		gtk_widget_set_sensitive(GTK_WIDGET(prefs->remove_header), TRUE);
+		gtk_tree_selection_select_iter(selection, &iter);
+	}
+	if (prefs->control)
+		evolution_config_control_changed (prefs->control);
+}
+
+static void
+remove_header (GtkWidget *button, gpointer user_data)
+{
+	EMMailerPrefs *prefs = (EMMailerPrefs *) user_data;
+	GtkTreeView *treeview = prefs->header_list;
+	GtkTreeModel *model = GTK_TREE_MODEL(prefs->header_list_store);
+	GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
+	GtkTreeIter iter;
+	
+	if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
+		gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
+		if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) {
+			/* list is empty - disable the remove button*/
+			gtk_widget_set_sensitive(GTK_WIDGET(prefs->remove_header), FALSE);
+		} else {
+			/* select the first entry */
+			gtk_tree_selection_select_iter(selection, &iter);
+		}
+		if (prefs->control)
+			evolution_config_control_changed (prefs->control);
+	}
+}
+
+static void
 em_mailer_prefs_construct (EMMailerPrefs *prefs)
 {
 	GtkWidget *toplevel, *menu;
@@ -212,7 +384,9 @@
 	char *font;
 	int i, val;
 	char *buf;
-	
+	GSList *header_config_list, *bold_config_list, *p, *q;
+	GtkTreeIter iter;
+
 	gui = glade_xml_new (EVOLUTION_GLADEDIR "/mail-config.glade", "preferences_tab", NULL);
 	prefs->gui = gui;
 	
@@ -360,6 +534,60 @@
 	
 	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->header_list = GTK_TREE_VIEW (glade_xml_get_widget (gui, "treeHeaders"));
+	/* 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_signal_connect (prefs->add_header, "clicked",
+			  G_CALLBACK (add_header), prefs);
+	g_signal_connect (prefs->remove_header, "clicked", 
+			  G_CALLBACK (remove_header), prefs);
+	gtk_tree_view_set_model(prefs->header_list, GTK_TREE_MODEL (prefs->header_list_store));
+	prefs->header_list_bold_renderer = gtk_cell_renderer_toggle_new();
+	g_object_set(prefs->header_list_bold_renderer, "activatable", TRUE, NULL);
+	g_signal_connect(prefs->header_list_bold_renderer, "toggled", 
+			 G_CALLBACK(header_list_bold_toggled), prefs);
+        gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(prefs->header_list), -1, 
+						    "Bold", prefs->header_list_bold_renderer,
+						    "active", HEADER_LIST_BOLD_COLUMN, 
+						    NULL);
+	prefs->header_list_name_renderer = gtk_cell_renderer_text_new();
+	g_object_set(prefs->header_list_name_renderer, "editable", TRUE, NULL);
+	g_signal_connect(prefs->header_list_name_renderer, "edited",
+			 G_CALLBACK(header_list_cell_edited), prefs);
+	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(prefs->header_list), -1, 
+						    "Name", prefs->header_list_name_renderer,
+						    "text", HEADER_LIST_NAME_COLUMN, 
+						    NULL);
+	/* read stored values from gconf */
+	header_config_list = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/display/headers", GCONF_VALUE_STRING, NULL);
+	bold_config_list = gconf_client_get_list (prefs->gconf, "/apps/evolution/mail/display/headers_flags", GCONF_VALUE_INT, NULL);
+	p = header_config_list;
+	q = bold_config_list;
+	/* iterate over both of these, stopping when either ends
+	   if the data is corrupt, we'll output as many valid entries as possible
+	*/
+	while (p && q) {
+		gint flags = (gboolean)q->data;
+		gchar *name = (gchar *)p->data;
+		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_BOLD_COLUMN, (flags & EM_MAILER_PREFS_FLAGS_BOLD), 
+				   -1);
+		p = g_slist_next(p);
+		q = g_slist_next(q);
+	}
+	g_slist_free(p);
+	g_slist_free(q);
+	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(prefs->header_list_store), &iter)) {
+		/* list is empty - disable the remove button*/
+		gtk_widget_set_sensitive(GTK_WIDGET(prefs->remove_header), FALSE);
+	}
 }
 
 
@@ -384,6 +612,9 @@
 	GSList *list, *l, *n;
 	guint32 rgb;
 	int i, val;
+	GtkTreeIter iter;
+	gboolean valid;
+	GSList *header_list, *header_flags_list;
 	
 	/* General tab */
 	
@@ -469,6 +700,29 @@
 		g_slist_free_1 (l);
 		l = n;
 	}
-	
+
+	/* Headers */
+	header_list = NULL;
+	header_flags_list = NULL;
+	valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(prefs->header_list_store), &iter);
+	while (valid) {
+		gchar *header_name;
+		gboolean header_bold;
+		gint flags = 0;
+		gtk_tree_model_get (GTK_TREE_MODEL(prefs->header_list_store), &iter, 
+				    HEADER_LIST_NAME_COLUMN, &header_name, 
+				    HEADER_LIST_BOLD_COLUMN, &header_bold, 
+				    -1);
+		header_list = g_slist_append(header_list, header_name);
+		if (header_bold) {
+			flags |= EM_MAILER_PREFS_FLAGS_BOLD;
+		}
+		header_flags_list = g_slist_append(header_flags_list, GINT_TO_POINTER(flags));
+		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);
+	gconf_client_set_list (prefs->gconf, "/apps/evolution/mail/display/headers_flags", GCONF_VALUE_INT, header_flags_list, NULL);
+	g_slist_free(header_list);
+	g_slist_free(header_flags_list);
 	gconf_client_suggest_sync (prefs->gconf, NULL);
 }
Index: mail/em-mailer-prefs.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-mailer-prefs.h,v
retrieving revision 1.2
diff -u -r1.2 em-mailer-prefs.h
--- mail/em-mailer-prefs.h	29 Oct 2003 17:49:55 -0000	1.2
+++ mail/em-mailer-prefs.h	27 Nov 2003 18:53:14 -0000
@@ -49,8 +49,10 @@
 typedef struct _EMMailerPrefs EMMailerPrefs;
 typedef struct _EMMailerPrefsClass EMMailerPrefsClass;
 
+#define EM_MAILER_PREFS_FLAGS_BOLD 0x01
+
 struct _EMMailerPrefs {
-	GtkVBox parent_object;
+        GtkVBox parent_object;
 	
 	GNOME_Evolution_Shell shell;
 	
@@ -98,6 +100,14 @@
 		GnomeColorPicker *color;
 	} labels[5];
 	GtkButton *restore_labels;
+
+	/* Headers tab */
+	GtkButton *add_header;
+	GtkButton *remove_header;
+	GtkTreeView *header_list;
+	GtkListStore *header_list_store;
+	GtkCellRenderer *header_list_name_renderer;
+	GtkCellRenderer *header_list_bold_renderer;
 };
 
 struct _EMMailerPrefsClass {
Index: mail/mail-config.glade
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-config.glade,v
retrieving revision 1.124
diff -u -r1.124 mail-config.glade
--- mail/mail-config.glade	11 Nov 2003 02:38:01 -0000	1.124
+++ mail/mail-config.glade	27 Nov 2003 18:53:31 -0000
@@ -4475,6 +4475,152 @@
 	  <property name="type">tab</property>
 	</packing>
       </child>
+
+      <child>
+	<widget class="GtkVBox" id="vboxHeaders">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkFrame" id="frameHeaders">
+	      <property name="border_width">6</property>
+	      <property name="visible">True</property>
+	      <property name="label_xalign">0</property>
+	      <property name="label_yalign">0.5</property>
+	      <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+	      <child>
+		<widget class="GtkVBox" id="vbox161">
+		  <property name="border_width">6</property>
+		  <property name="visible">True</property>
+		  <property name="homogeneous">False</property>
+		  <property name="spacing">6</property>
+
+		  <child>
+		    <widget class="GtkScrolledWindow" id="scrolledwindow49">
+		      <property name="visible">True</property>
+		      <property name="can_focus">True</property>
+		      <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		      <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</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">True</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>
+
+		  <child>
+		    <widget class="GtkHBox" id="hbox177">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">True</property>
+		      <property name="spacing">0</property>
+
+		      <child>
+			<widget class="GtkButton" id="cmdHeadersAdd">
+			  <property name="visible">True</property>
+			  <property name="tooltip" translatable="yes">Add a header to be shown in mail view</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">True</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkButton" id="cmdHeadersRemove">
+			  <property name="visible">True</property>
+			  <property name="tooltip" translatable="yes">Remove selected header</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">6</property>
+			  <property name="expand">False</property>
+			  <property name="fill">True</property>
+			</packing>
+		      </child>
+		    </widget>
+		    <packing>
+		      <property name="padding">0</property>
+		      <property name="expand">False</property>
+		      <property name="fill">True</property>
+		    </packing>
+		  </child>
+		</widget>
+	      </child>
+
+	      <child>
+		<widget class="GtkLabel" id="lblHeadersFrame">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Display Custom Mail Headers</property>
+		  <property name="use_underline">False</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">label_item</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>
     </widget>
   </child>
 </widget>


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