[evolution/wip/gsettings] Bug #641845 - Add default expansion variables to templates plugin



commit 2abbff465156c62c0825190a4408fe92b4d55bc1
Author: Dan VrÃtil <dvratil redhat com>
Date:   Wed Apr 27 17:10:14 2011 +0200

    Bug #641845 - Add default expansion variables to templates plugin
    
    Users can read values from original message in the template
    by $ORIG[header] and with a special value $ORIG[body].

 plugins/templates/org-gnome-templates.eplug.xml |    5 +-
 plugins/templates/templates.c                   |  545 +++++++++++++++++++----
 2 files changed, 452 insertions(+), 98 deletions(-)
---
diff --git a/plugins/templates/org-gnome-templates.eplug.xml b/plugins/templates/org-gnome-templates.eplug.xml
index 7c19a6e..5bfa8a1 100644
--- a/plugins/templates/org-gnome-templates.eplug.xml
+++ b/plugins/templates/org-gnome-templates.eplug.xml
@@ -5,9 +5,12 @@
         id="org.gnome.evolution.plugin.templates"
         location="@PLUGINDIR@/liborg-gnome-templates SOEXT@"
         _name="Templates">
-        <_description>Drafts based template plugin</_description>
+        <_description>Drafts based template plugin.
+        
+        You can use variables like $ORIG[subject], $ORIG[from], $ORIG[to] or $ORIG[body], which will be replaced by values from an email you are replying to.</_description>
         <author name="Bharath Acharya" email="abharath novell com"/>
         <author name="Diego Escalante Urrelo" email="diegoe gnome org"/>
+        <author name="Dan Vratil" email="dvratil redhat com"/>
 
         <hook class="org.gnome.evolution.ui:1.0">
           <ui-manager id="org.gnome.evolution.shell"
diff --git a/plugins/templates/templates.c b/plugins/templates/templates.c
index fd8f802..9fded58 100644
--- a/plugins/templates/templates.c
+++ b/plugins/templates/templates.c
@@ -84,6 +84,10 @@ static void  value_cell_edited_callback (GtkCellRendererText *cell, gchar *path_
 static gboolean clue_foreach_check_isempty (GtkTreeModel *model, GtkTreePath
 					*path, GtkTreeIter *iter, UIData *ui);
 
+static void templates_folder_msg_changed_cb (CamelFolder *folder,
+			      CamelFolderChangeInfo *change_info,
+			      EShellWindow *shell_window);
+
 static gboolean plugin_enabled;
 
 static void
@@ -465,46 +469,325 @@ e_plugin_lib_get_configure_widget (EPlugin *epl)
 	return hbox;
 }
 
+/* Case insensitive version of strstr */
+static gchar *
+strstr_nocase (const gchar* haystack, const gchar *needle)
+{
+/* When _GNU_SOURCE is available, use the nonstandard extension of libc */
+#ifdef _GNU_SOURCE
+	g_return_val_if_fail (haystack, NULL);
+	g_return_Val_if_fail (needle, NULL);
+
+	return strcasestr (haystack, needle)
+#else
+/* Otherwise convert both, haystack and needle to lowercase and use good old strstr */
+	gchar *l_haystack;
+	gchar *l_needle;
+	gchar *pos;
+
+	g_return_val_if_fail (haystack, NULL);
+	g_return_val_if_fail (needle, NULL);
+
+	l_haystack = g_ascii_strdown (haystack, -1);
+	l_needle = g_ascii_strdown (needle, -1);
+	pos = strstr (l_haystack, l_needle);
+
+	/* Get actual position of the needle in the haystack instead of l_haystack or
+	   leave it NULL */
+	if (pos)
+		pos = (gchar *)(haystack + (pos - l_haystack));
+
+	g_free (l_haystack);
+	g_free (l_needle);
+
+	return pos;
+#endif
+}
+
+/* Replaces $ORIG[variable] in given template by given replacement from the original message */
+static void
+replace_template_variable (GString *text, const gchar *variable, const gchar *replacement)
+{
+	const gchar *p, *next;
+	GString *str;
+	gint find_len;
+	gchar *find;
+
+	g_return_if_fail (text != NULL);
+	g_return_if_fail (variable != NULL);
+	g_return_if_fail (*variable);
+
+	find = g_strconcat ("$ORIG[", variable, "]", NULL);
+
+	find_len = strlen (find);
+	str = g_string_new ("");
+	p = text->str;
+	while (next = strstr_nocase (p, find), next) {
+		if (p < next)
+			g_string_append_len (str, p, next - p);
+		if (replacement && *replacement)
+			g_string_append (str, replacement);
+		p = next + find_len;
+	}
+	g_string_append (str, p);
+
+	g_string_assign (text, str->str);
+
+	g_string_free (str, TRUE);
+	g_free (find);
+}
+
+static void
+replace_email_addresses (GString *template, CamelInternetAddress *internet_address, const gchar *variable)
+{
+	gint address_index = 0;
+	GString *emails = g_string_new ("");
+	const gchar *address_name, *address_email;
+
+	g_return_if_fail (template);
+	g_return_if_fail (internet_address);
+	g_return_if_fail (variable);
+
+	while (camel_internet_address_get (internet_address, address_index, &address_name, &address_email)) {
+		gchar *address = camel_internet_address_format_address (address_name, address_email);
+
+		if (address_index > 0)
+			g_string_append_printf (emails, ", %s", address);
+		else
+			g_string_append_printf (emails, "%s", address);
+
+		address_index++;
+		g_free (address);
+	}
+	replace_template_variable (template, variable, emails->str);
+	g_string_free (emails, TRUE);
+}
+
+static CamelMimePart*
+fill_template (CamelMimeMessage *message, CamelMimePart *template)
+{
+	struct _camel_header_raw *header;
+	CamelContentType *ct;
+	CamelStream *stream;
+	CamelMimePart *return_part;
+	CamelMimePart *message_part = NULL;
+	CamelDataWrapper *dw;
+
+	CamelInternetAddress *internet_address;
+
+	GString *template_body;
+	GByteArray *byte_array;
+
+	gint i;
+	gboolean message_html, template_html;
+
+	ct = camel_mime_part_get_content_type (template);
+	template_html = ct && camel_content_type_is (ct, "text", "html");
+
+	message_html = FALSE;
+	/* When template is html, then prefer HTML part of the original message. Otherwise go for plaintext */
+	dw = camel_medium_get_content (CAMEL_MEDIUM (message));
+	if (CAMEL_IS_MULTIPART (dw)) {
+		CamelMultipart *multipart = CAMEL_MULTIPART (dw);
+
+		for (i = 0; i < camel_multipart_get_number (multipart); i++) {
+			CamelMimePart *part = camel_multipart_get_part (multipart, i);
+			CamelContentType *ct = camel_mime_part_get_content_type (part);
+
+			if (!ct)
+				continue;
+
+			if (camel_content_type_is (ct, "text", "html") && template_html) {
+				message_part = camel_multipart_get_part (multipart, i);
+				message_html = TRUE;
+				break;
+			} else if (camel_content_type_is (ct, "text", "plain") && message_html == FALSE) {
+				message_part = camel_multipart_get_part (multipart, i);
+			}
+		}
+	 } else
+	 	message_part  = CAMEL_MIME_PART (message);
+
+	/* Get content of the template */
+	stream = camel_stream_mem_new ();
+	camel_data_wrapper_decode_to_stream_sync (camel_medium_get_content (CAMEL_MEDIUM (template)), stream, NULL, NULL);
+	camel_stream_flush (stream, NULL, NULL);
+	byte_array = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (stream));
+	template_body = g_string_new_len ((gchar *) byte_array->data, byte_array->len);
+	g_object_unref (stream);
+
+	/* Replace all $ORIG[header_name] by respective values */
+	header = CAMEL_MIME_PART (message)->headers;
+	while (header) {
+		if (g_ascii_strncasecmp (header->name, "content-", 8) != 0 &&
+		    g_ascii_strncasecmp (header->name, "to", 2) != 0 &&
+		    g_ascii_strncasecmp (header->name, "cc", 2) != 0 &&
+		    g_ascii_strncasecmp (header->name, "bcc", 3) != 0 &&
+		    g_ascii_strncasecmp (header->name, "from", 4) != 0 &&
+		    g_ascii_strncasecmp (header->name, "subject", 7) != 0)
+			replace_template_variable (template_body, header->name, header->value);
+
+		header = header->next;
+	}
+
+	/* Now manually replace the *subject* header. The header->value for subject header could be
+	   base64 encoded, so let camel_mime_message to decode it for us if needed */
+	replace_template_variable (template_body, "subject", camel_mime_message_get_subject (message));
+
+	/* Replace TO and FROM modifiers. */
+	internet_address = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_TO);
+	replace_email_addresses (template_body, internet_address, "to");
+
+	internet_address = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_CC);
+	replace_email_addresses (template_body, internet_address, "cc");
+
+	internet_address = camel_mime_message_get_recipients (message, CAMEL_RECIPIENT_TYPE_BCC);
+	replace_email_addresses (template_body, internet_address, "bcc");
+
+	internet_address = camel_mime_message_get_from (message);
+	replace_email_addresses (template_body, internet_address, "from");
+
+	/* Now extract body of the original message and replace the $ORIG[body] modifier in template */
+	if (message_part && strstr_nocase (template_body->str, "$ORIG[body]")) {
+		GString *message_body;
+
+		stream = camel_stream_mem_new ();
+		camel_data_wrapper_decode_to_stream_sync (camel_medium_get_content (CAMEL_MEDIUM (message_part)), stream, NULL, NULL);
+		camel_stream_flush (stream, NULL, NULL);
+		byte_array = camel_stream_mem_get_byte_array (CAMEL_STREAM_MEM (stream));
+		message_body = g_string_new_len ((gchar*)byte_array->data, byte_array->len);
+		g_object_unref (stream);
+
+		if (template_html && !message_html) {
+			gchar *html = camel_text_to_html (message_body->str, CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
+									     CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES |
+									     CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
+									     CAMEL_MIME_FILTER_TOHTML_MARK_CITATION |
+									     CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES, 0);
+			g_string_assign (message_body, html);
+			g_free (html);
+		} else if (!template_html && message_html) {
+			g_string_prepend (message_body, "<pre>");
+			g_string_append (message_body, "</pre>");
+		} /* Other cases should not occur. And even if they happen to do, there's nothing we can really do about it */
+
+		replace_template_variable (template_body, "body", message_body->str);
+		g_string_free (message_body, TRUE);
+	} else {
+		replace_template_variable (template_body, "body", "");
+	}
+
+	return_part = camel_mime_part_new ();
+
+	if (template_html)
+		camel_mime_part_set_content (return_part, template_body->str, template_body->len, "text/html");
+	else
+		camel_mime_part_set_content (return_part, template_body->str, template_body->len, "text/plain");
+
+	g_string_free (template_body, TRUE);
+
+	return return_part;
+}
+
 static void
 create_new_message (CamelFolder *folder, const gchar *uid, CamelMimeMessage *message, gpointer data)
 {
-	GtkAction *action = data;
-	CamelMimeMessage *new, *template;
+	CamelMimeMessage *new;
+	CamelMimeMessage *template = CAMEL_MIME_MESSAGE (data);
+	CamelMultipart *new_multipart;
+	CamelContentType *new_content_type = NULL;
+	CamelDataWrapper *dw;
 	struct _camel_header_raw *header;
-	CamelStream *mem;
 	EShell *shell;
+	gint i;
+
+	CamelMimePart *template_part = NULL;
+	CamelMimePart *out_part = NULL;
 
-	g_return_if_fail (data != NULL);
+	g_return_if_fail (template != NULL);
 	g_return_if_fail (message != NULL);
 
 	/* FIXME Pass this in somehow. */
 	shell = e_shell_get_default ();
 
 	folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES);
-	template = g_object_get_data (G_OBJECT (action), "template");
 
-	/* The new message we are creating */
 	new = camel_mime_message_new ();
+	new_multipart = camel_multipart_new ();
+	camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (new_multipart), "multipart/alternative");
+	camel_multipart_set_boundary (new_multipart, NULL);
+
+	dw = camel_medium_get_content (CAMEL_MEDIUM (template));
+	/* If template is a multipart, then try to use HTML. When no HTML part is available, use plaintext. Every other
+	   add as an attachment */
+	if (CAMEL_IS_MULTIPART (dw)) {
+		for (i = 0; i < camel_multipart_get_number (CAMEL_MULTIPART (dw)); i++) {
+			CamelMimePart *part = camel_multipart_get_part (CAMEL_MULTIPART (dw), i);
+			CamelContentType *ct = camel_mime_part_get_content_type (part);
+
+			if (ct && camel_content_type_is (ct, "text", "html")) {
+				new_content_type = ct;
+				template_part = camel_multipart_get_part (CAMEL_MULTIPART (dw), i);
+			} else if (ct && camel_content_type_is (ct, "text", "plain") && new_content_type == NULL) {
+				new_content_type = ct;
+				template_part = camel_multipart_get_part (CAMEL_MULTIPART (dw), i);
+			} else {
+				/* Copy any other parts (attachments...) to the output message */
+				camel_mime_part_set_disposition (part, "attachment");
+				camel_multipart_add_part (new_multipart, part);
+			}
+		}
+	} else {
+		CamelContentType *ct = camel_mime_part_get_content_type (CAMEL_MIME_PART (template));
 
-	/* make the exact copy of the template message, with all
-	   its attachments and message structure */
-	mem = camel_stream_mem_new ();
-	camel_data_wrapper_write_to_stream_sync (
-		CAMEL_DATA_WRAPPER (template), mem, NULL, NULL);
-	camel_stream_reset (mem, NULL);
-	camel_data_wrapper_construct_from_stream_sync (
-		CAMEL_DATA_WRAPPER (new), mem, NULL, NULL);
-	g_object_unref (mem);
+		if (ct && (camel_content_type_is (ct, "text", "html") ||
+		    camel_content_type_is (ct, "text", "plain"))) {
+		    	template_part = CAMEL_MIME_PART (template);
+			new_content_type = ct;
+		}
+	}
+
+	/* Here replace all the modifiers in template body by values from message and return the newly created part */
+	out_part = fill_template (message, template_part);
+
+	/* Assigning part directly to mime_message causes problem with "Content-type" header displaying
+	   in the HTML message (camel parsing bug?) */
+	camel_multipart_add_part (new_multipart, out_part);
+	g_object_unref (out_part);
+	camel_medium_set_content (CAMEL_MEDIUM (new), CAMEL_DATA_WRAPPER (new_multipart));
 
 	/* Add the headers from the message we are replying to, so CC and that
-	 * stuff is preserved. */
-	header = ((CamelMimePart *)message)->headers;
+	   stuff is preserved. Also replace any $ORIG[header-name] modifiers ignoring
+	   'content-*' headers */
+	header = CAMEL_MIME_PART (message)->headers;
 	while (header) {
 		if (g_ascii_strncasecmp (header->name, "content-", 8) != 0) {
-			camel_medium_add_header ((CamelMedium *) new,
-					header->name,
-					header->value);
+
+			/* Some special handling of the 'subject' header */
+			if (g_ascii_strncasecmp (header->name, "subject", 7) == 0) {
+				GString *subject = g_string_new (camel_mime_message_get_subject (template));
+
+				/* Now replace all possible $ORIG[]s in the subject line by values from original message */
+				struct _camel_header_raw *m_header = CAMEL_MIME_PART (message)->headers;
+				while (m_header) {
+					if (g_ascii_strncasecmp (m_header->name, "content-", 8) != 0 &&
+					    g_ascii_strncasecmp (m_header->name, "subject", 7) !=0)
+						replace_template_variable (subject, m_header->name, m_header->value);
+
+					m_header = m_header->next;
+				}
+				/* Now replace $ORIG[subject] variable, handling possible base64 encryption */
+				replace_template_variable (subject, "subject",
+					camel_mime_message_get_subject (message));
+				header->value = g_strdup (subject->str);
+				g_string_free (subject, TRUE);
+			}
+
+			camel_medium_add_header (CAMEL_MEDIUM (new),
+						 header->name,
+						 header->value);
 		}
+
 		header = header->next;
 	}
 
@@ -522,38 +805,55 @@ create_new_message (CamelFolder *folder, const gchar *uid, CamelMimeMessage *mes
 	/* Create the composer */
 	em_utils_edit_message (shell, folder, new);
 
+	g_object_unref (template);
+	g_object_unref (new_multipart);
 	g_object_unref (new);
 }
 
 static void
 action_reply_with_template_cb (GtkAction *action,
-                               const gchar *message_uid)
+				EShellView *shell_view)
 {
-	CamelFolder *folder;
+	CamelFolder *folder, *template_folder;
+	EShellContent *shell_content;
+	EMailReader *reader;
+	GPtrArray *uids;
+	const gchar *uid;
+	CamelMimeMessage *template;
 
-	g_return_if_fail (message_uid != NULL);
+	shell_content = e_shell_view_get_shell_content (shell_view);
+	reader = E_MAIL_READER (shell_content);
+	folder = e_mail_reader_get_folder (reader);
+	uids = e_mail_reader_get_selected_uids (reader);
 
-	folder = CAMEL_FOLDER (g_object_get_data (G_OBJECT (action), "message_folder"));
-	g_return_if_fail (folder != NULL);
+	if (!uids->len || !folder)
+		return;
 
 	g_object_ref (G_OBJECT (action));
 
-	mail_get_message (folder, message_uid, create_new_message, action, mail_msg_unordered_push);
+	template_folder = g_object_get_data (G_OBJECT (action), "template-folder");
+	uid = g_object_get_data (G_OBJECT (action), "template-uid");
+	template = camel_folder_get_message_sync (template_folder, uid, NULL, NULL);
+
+	mail_get_message (folder, uids->pdata[0], create_new_message,
+		(gpointer)template, mail_msg_unordered_push);
 
 	g_object_unref (G_OBJECT (action));
+
+	em_utils_uids_free (uids);
 }
 
 static void
 build_template_menus_recurse (GtkUIManager *ui_manager,
-                              GtkActionGroup *action_group,
+			       GtkActionGroup *action_group,
                               const gchar *menu_path,
                               guint *action_count,
                               guint merge_id,
                               CamelFolderInfo *folder_info,
-                              CamelFolder *message_folder,
-                              const gchar *message_uid)
+			       EShellView *shell_view)
 {
 	CamelStore *store;
+	EShellWindow *shell_window = e_shell_view_get_shell_window (shell_view);
 
 	store = e_mail_local_get_store ();
 
@@ -591,6 +891,12 @@ build_template_menus_recurse (GtkUIManager *ui_manager,
 			ui_manager, merge_id, menu_path, action_name,
 			action_name, GTK_UI_MANAGER_MENU, FALSE);
 
+		/* Disconnect previous connection to avoid possible multiple calls because
+		   folder is a persistent structure */
+		g_signal_handlers_disconnect_by_func (folder, G_CALLBACK (templates_folder_msg_changed_cb), shell_window);
+		g_signal_connect (folder, "changed",
+			G_CALLBACK (templates_folder_msg_changed_cb), shell_window);
+
 		path = g_strdup_printf ("%s/%s", menu_path, action_name);
 
 		g_object_unref (action);
@@ -601,7 +907,7 @@ build_template_menus_recurse (GtkUIManager *ui_manager,
 			build_template_menus_recurse (
 				ui_manager, action_group,
 				path, action_count, merge_id,
-				folder_info->child, message_folder, message_uid);
+				folder_info->child, shell_view);
 
 		if (!folder) {
 			g_free (path);
@@ -613,7 +919,7 @@ build_template_menus_recurse (GtkUIManager *ui_manager,
 		uids = camel_folder_get_uids (folder);
 		for (ii = 0; uids && ii < uids->len; ii++) {
 			CamelMimeMessage *template;
-			const gchar *uid = uids->pdata[ii], *muid;
+			const gchar *uid = uids->pdata[ii];
 			guint32 flags;
 
 			/* If the UIDs is marked for deletion, skip it. */
@@ -641,25 +947,14 @@ build_template_menus_recurse (GtkUIManager *ui_manager,
 			action = gtk_action_new (
 				action_name, action_label, NULL, NULL);
 
-			muid = camel_pstring_strdup (message_uid);
-			g_object_ref (message_folder);
-
-			g_object_set_data_full (
-				G_OBJECT (action), "message_uid", (gpointer) muid,
-				(GDestroyNotify) camel_pstring_free);
-
-			g_object_set_data_full (
-				G_OBJECT (action), "message_folder", message_folder,
-				(GDestroyNotify) g_object_unref);
+			g_object_set_data(G_OBJECT (action), "template-uid", (gpointer) uid);
 
-			g_object_set_data_full (
-				G_OBJECT (action), "template", template,
-				(GDestroyNotify) g_object_unref);
+			g_object_set_data(G_OBJECT (action), "template-folder", folder);
 
 			g_signal_connect (
 				action, "activate",
 				G_CALLBACK (action_reply_with_template_cb),
-				(gpointer) muid);
+				shell_view);
 
 			gtk_action_group_add_action (action_group, action);
 
@@ -669,6 +964,7 @@ build_template_menus_recurse (GtkUIManager *ui_manager,
 
 			g_object_unref (action);
 			g_free (action_name);
+			g_object_unref (template);
 		}
 
 		camel_folder_free_uids (folder, uids);
@@ -750,52 +1046,28 @@ static GtkActionEntry composer_entries[] = {
 };
 
 static void
-update_actions_cb (EShellView *shell_view)
+build_menu (EShellWindow *shell_window,
+	    GtkActionGroup *action_group)
 {
-	EShellContent *shell_content;
-	EShellWindow *shell_window;
-	GtkActionGroup *action_group;
-	GtkUIManager *ui_manager;
-	CamelFolderInfo *folder_info;
-	CamelFolder *templates_folder;
+	EShellView *shell_view;
 	CamelFolder *folder;
 	CamelStore *store;
-	EMailReader *reader;
-	GPtrArray *uids;
-	const gchar *full_name;
-	guint action_count = 0;
+	CamelFolderInfo *folder_info;
+	GtkUIManager *ui_manager;
 	guint merge_id;
-	gpointer data;
-
-	shell_content = e_shell_view_get_shell_content (shell_view);
-	shell_window = e_shell_view_get_shell_window (shell_view);
+	guint action_count = 0;
+	const gchar *full_name;
 
 	ui_manager = e_shell_window_get_ui_manager (shell_window);
-	action_group = e_lookup_action_group (ui_manager, "templates");
-	data = g_object_get_data (G_OBJECT (action_group), "merge-id");
-	merge_id = GPOINTER_TO_UINT (data);
-	g_return_if_fail (merge_id > 0);
+	shell_view = e_shell_window_get_shell_view (shell_window, "mail");
 
-	gtk_ui_manager_remove_ui (ui_manager, merge_id);
-	e_action_group_remove_all_actions (action_group);
-	gtk_ui_manager_ensure_update (ui_manager);
-
-	if (!plugin_enabled)
-		return;
-
-	reader = E_MAIL_READER (shell_content);
-	folder = e_mail_reader_get_folder (reader);
-	uids = e_mail_reader_get_selected_uids (reader);
-
-	if (uids->len != 1)
-		goto exit;
+	merge_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (action_group), "merge-id"));
 
 	/* Now recursively build template submenus in the pop-up menu. */
-
 	store = e_mail_local_get_store ();
-	templates_folder = e_mail_local_get_folder (
+	folder = e_mail_local_get_folder (
 		E_MAIL_LOCAL_FOLDER_TEMPLATES);
-	full_name = camel_folder_get_full_name (templates_folder);
+	full_name = camel_folder_get_full_name (folder);
 
 	/* FIXME Not passing a GCancellable or GError here. */
 	folder_info = camel_store_get_folder_info_sync (
@@ -807,11 +1079,32 @@ update_actions_cb (EShellView *shell_view)
 		ui_manager, action_group,
 		"/mail-message-popup/mail-message-templates",
 		&action_count, merge_id, folder_info,
-		folder, uids->pdata[0]);
+		shell_view);
 
 	camel_store_free_folder_info (store, folder_info);
-exit:
-	em_utils_uids_free (uids);
+}
+
+static void
+update_actions_cb (EShellView *shell_view, GtkActionGroup *action_group)
+{
+	GList *list;
+	gint length;
+
+	if (!plugin_enabled)
+		return;
+
+	list = gtk_action_group_list_actions (action_group);
+	length = g_list_length (list);
+
+	if (!length) {
+		EShellWindow *shell_window  = e_shell_view_get_shell_window (shell_view);
+		build_menu (shell_window, action_group);
+	}
+
+	gtk_action_group_set_sensitive (action_group, TRUE);
+	gtk_action_group_set_visible (action_group, TRUE);
+
+	g_list_free (list);
 }
 
 gboolean
@@ -831,31 +1124,89 @@ init_composer_actions (GtkUIManager *ui_manager,
 }
 
 static void
-mail_shell_view_created_cb (EShellWindow *shell_window,
-                            EShellView *shell_view)
+rebuild_template_menu (EShellWindow *shell_window)
+{
+	GtkUIManager *ui_manager;
+	GtkActionGroup *action_group;
+	guint merge_id;
+
+	ui_manager = e_shell_window_get_ui_manager (shell_window);
+
+	action_group = e_lookup_action_group (ui_manager, "templates");
+	merge_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (action_group), "merge-id"));
+
+	gtk_ui_manager_remove_ui (ui_manager, merge_id);
+	e_action_group_remove_all_actions (action_group);
+	gtk_ui_manager_ensure_update (ui_manager);
+
+	build_menu (shell_window, action_group);
+}
+
+static void
+templates_folder_msg_changed_cb (CamelFolder *folder,
+			      	 CamelFolderChangeInfo *change_info,
+			      	 EShellWindow *shell_window)
 {
-	g_signal_connect (
-		shell_view, "update-actions",
-		G_CALLBACK (update_actions_cb), NULL);
+	rebuild_template_menu (shell_window);
 }
 
-gboolean
-init_shell_actions (GtkUIManager *ui_manager,
-                    EShellWindow *shell_window)
+static void
+templates_folder_changed_cb (CamelStore *store,
+			     CamelFolderInfo *folder_info,
+			     EShellWindow *shell_window)
 {
-	EShellView *shell_view;
+	if (folder_info->full_name && strstr (folder_info->full_name, _("Templates")) != NULL)
+		rebuild_template_menu (shell_window);
+}
+
+static void
+templates_folder_renamed_cb (CamelStore *store,
+			     const gchar *old_name,
+			     CamelFolderInfo *folder_info,
+			     EShellWindow *shell_window)
+{
+	if (folder_info->full_name && strstr (folder_info->full_name, _("Templates")) != NULL)
+		rebuild_template_menu (shell_window);
+}
+
+static void
+mail_shell_view_created_cb (EShellWindow *shell_window,
+                            EShellView *shell_view)
+{
+	GtkUIManager *ui_manager;
 	GtkActionGroup *action_group;
+	CamelFolder *folder;
+	CamelStore *store;
 	guint merge_id;
 
-	/* This is where we keep dynamically-built menu items. */
+	ui_manager = e_shell_window_get_ui_manager (shell_window);
 	e_shell_window_add_action_group (shell_window, "templates");
 	action_group = e_lookup_action_group (ui_manager, "templates");
-
 	merge_id = gtk_ui_manager_new_merge_id (ui_manager);
+	g_object_set_data (G_OBJECT (action_group), "merge-id",
+			   GUINT_TO_POINTER (merge_id));
 
-	g_object_set_data (
-		G_OBJECT (action_group), "merge-id",
-		GUINT_TO_POINTER (merge_id));
+	folder = e_mail_local_get_folder (E_MAIL_LOCAL_FOLDER_TEMPLATES);
+	store = e_mail_local_get_store ();
+
+	g_signal_connect (folder, "changed",
+		G_CALLBACK (templates_folder_msg_changed_cb), shell_window);
+	g_signal_connect (store, "folder-created",
+		G_CALLBACK (templates_folder_changed_cb), shell_window);
+	g_signal_connect (store, "folder-deleted",
+		G_CALLBACK (templates_folder_changed_cb), shell_window);
+	g_signal_connect (store, "folder-renamed",
+		G_CALLBACK (templates_folder_renamed_cb), shell_window);
+
+	g_signal_connect (shell_view, "update-actions",
+		G_CALLBACK (update_actions_cb), action_group);
+}
+
+gboolean
+init_shell_actions (GtkUIManager *ui_manager,
+                    EShellWindow *shell_window)
+{
+	EShellView *shell_view;
 
 	/* Be careful not to instantiate the mail view ourselves. */
 	shell_view = e_shell_window_peek_shell_view (shell_window, "mail");



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