aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Vrátil <dvratil@redhat.com>2011-04-27 23:10:14 +0800
committerMilan Crha <mcrha@redhat.com>2011-04-27 23:10:14 +0800
commit5fcaadbc9a16f711c0fe81933ec9615f289c8fa8 (patch)
treee408c4ac2fc02e184b2a7fadb92c248de3f9f7cb
parent81270ea009bdca0a9527737efa7ecb27a6260bff (diff)
downloadgsoc2013-evolution-5fcaadbc9a16f711c0fe81933ec9615f289c8fa8.tar
gsoc2013-evolution-5fcaadbc9a16f711c0fe81933ec9615f289c8fa8.tar.gz
gsoc2013-evolution-5fcaadbc9a16f711c0fe81933ec9615f289c8fa8.tar.bz2
gsoc2013-evolution-5fcaadbc9a16f711c0fe81933ec9615f289c8fa8.tar.lz
gsoc2013-evolution-5fcaadbc9a16f711c0fe81933ec9615f289c8fa8.tar.xz
gsoc2013-evolution-5fcaadbc9a16f711c0fe81933ec9615f289c8fa8.tar.zst
gsoc2013-evolution-5fcaadbc9a16f711c0fe81933ec9615f289c8fa8.zip
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].
-rw-r--r--plugins/templates/org-gnome-templates.eplug.xml5
-rw-r--r--plugins/templates/templates.c545
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 7c19a6ea23..5bfa8a1e2b 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 fd8f8021f7..9fded58413 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");