[evolution] Bug 790020 - Use original location when composing new message in Search Folder



commit a6a451ab876d491d7db593340e07a22f64db8965
Author: Milan Crha <mcrha redhat com>
Date:   Fri Nov 24 12:25:54 2017 +0100

    Bug 790020 - Use original location when composing new message in Search Folder

 src/mail/e-mail-display.c                          |    7 +-
 src/mail/e-mail-reader.c                           |   24 +++-
 src/mail/em-composer-utils.c                       |  160 +++++++++++++++++++-
 src/mail/em-composer-utils.h                       |    9 +
 src/modules/mail/e-mail-shell-backend.c            |   58 +++++---
 .../mailing-list-actions/mailing-list-actions.c    |    6 +-
 6 files changed, 230 insertions(+), 34 deletions(-)
---
diff --git a/src/mail/e-mail-display.c b/src/mail/e-mail-display.c
index f9befc8..0e68e8d 100644
--- a/src/mail/e-mail-display.c
+++ b/src/mail/e-mail-display.c
@@ -322,14 +322,13 @@ mail_display_process_mailto (EWebView *web_view,
        if (g_ascii_strncasecmp (mailto_uri, "mailto:";, 7) == 0) {
                EShell *shell;
                EMailPartList *part_list;
-               CamelFolder *folder;
 
                part_list = E_MAIL_DISPLAY (web_view)->priv->part_list;
-               folder = e_mail_part_list_get_folder (part_list);
 
                shell = e_shell_get_default ();
-               em_utils_compose_new_message_with_mailto (
-                       shell, mailto_uri, folder);
+               em_utils_compose_new_message_with_mailto_and_selection (shell, mailto_uri,
+                       e_mail_part_list_get_folder (part_list),
+                       e_mail_part_list_get_message_uid (part_list));
 
                handled = TRUE;
        }
diff --git a/src/mail/e-mail-reader.c b/src/mail/e-mail-reader.c
index 733d91a..2de0eb2 100644
--- a/src/mail/e-mail-reader.c
+++ b/src/mail/e-mail-reader.c
@@ -965,6 +965,7 @@ typedef struct _CreateComposerData {
        EMailReader *reader;
        CamelMimeMessage *message;
        CamelFolder *folder;
+       const gchar *message_uid; /* In the Camel string pool */
        gboolean is_redirect;
 } CreateComposerData;
 
@@ -987,7 +988,7 @@ mail_reader_new_composer_created_cb (GObject *source_object,
                if (ccd->is_redirect)
                        em_utils_redirect_message (composer, ccd->message);
                else
-                       em_utils_compose_new_message (composer, ccd->folder);
+                       em_utils_compose_new_message_with_selection (composer, ccd->folder, ccd->message_uid);
 
                e_mail_reader_composer_created (ccd->reader, composer, ccd->message);
        }
@@ -995,6 +996,7 @@ mail_reader_new_composer_created_cb (GObject *source_object,
        g_clear_object (&ccd->reader);
        g_clear_object (&ccd->message);
        g_clear_object (&ccd->folder);
+       camel_pstring_free (ccd->message_uid);
        g_free (ccd);
 }
 
@@ -1007,19 +1009,37 @@ action_mail_message_new_cb (GtkAction *action,
        EShellBackend *shell_backend;
        CamelFolder *folder;
        CreateComposerData *ccd;
+       GPtrArray *selected_uids = NULL;
+       const gchar *selected_uid = NULL;
 
        folder = e_mail_reader_ref_folder (reader);
        backend = e_mail_reader_get_backend (reader);
 
+       selected_uids = e_mail_reader_get_selected_uids (reader);
+       if (selected_uids && selected_uids->len > 0)
+               selected_uid = g_ptr_array_index (selected_uids, 0);
+
+       if (!selected_uid) {
+               GtkWidget *message_list;
+
+               message_list = e_mail_reader_get_message_list (reader);
+               if (message_list)
+                       selected_uid = MESSAGE_LIST (message_list)->cursor_uid;
+       }
+
        shell_backend = E_SHELL_BACKEND (backend);
        shell = e_shell_backend_get_shell (shell_backend);
 
        ccd = g_new0 (CreateComposerData, 1);
        ccd->reader = g_object_ref (reader);
        ccd->folder = folder;
+       ccd->message_uid = camel_pstring_strdup (selected_uid);
        ccd->is_redirect = FALSE;
 
        e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
+
+       if (selected_uids)
+               g_ptr_array_unref (selected_uids);
 }
 
 static void
@@ -1255,6 +1275,7 @@ mail_reader_redirect_cb (CamelFolder *folder,
        ccd = g_new0 (CreateComposerData, 1);
        ccd->reader = g_object_ref (closure->reader);
        ccd->message = message;
+       ccd->message_uid = camel_pstring_strdup (closure->message_uid);
        ccd->is_redirect = TRUE;
 
        e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
@@ -1285,6 +1306,7 @@ action_mail_redirect_cb (GtkAction *action,
        closure = g_slice_new0 (EMailReaderClosure);
        closure->activity = activity;
        closure->reader = g_object_ref (reader);
+       closure->message_uid = g_strdup (message_uid);
 
        folder = e_mail_reader_ref_folder (reader);
 
diff --git a/src/mail/em-composer-utils.c b/src/mail/em-composer-utils.c
index d48eb55..0296976 100644
--- a/src/mail/em-composer-utils.c
+++ b/src/mail/em-composer-utils.c
@@ -1402,6 +1402,8 @@ sort_sources_by_ui (GList **psources,
 
 /* Composing messages... */
 
+static CamelMimeMessage *em_utils_get_composer_recipients_as_message (EMsgComposer *composer);
+
 static void
 set_up_new_composer (EMsgComposer *composer,
                     const gchar *subject,
@@ -1425,15 +1427,107 @@ set_up_new_composer (EMsgComposer *composer,
                GList *list;
 
                if (message) {
+                       g_object_ref (message);
+               } else if (message_uid) {
+                       message = em_utils_get_composer_recipients_as_message (composer);
+               }
+
+               if (message) {
                        EShell *shell;
 
                        shell = e_msg_composer_get_shell (composer);
+
+                       /* Check send account override for the passed-in folder */
                        source = em_utils_check_send_account_override (shell, message, folder, 
&identity_name, &identity_address);
-                       if (!source)
+
+                       /* If not set and it's a search folder, then check the original folder */
+                       if (!source && message_uid && CAMEL_IS_VEE_FOLDER (folder)) {
+                               CamelMessageInfo *mi = camel_folder_get_message_info (folder, message_uid);
+                               if (mi) {
+                                       CamelFolder *location;
+
+                                       location = camel_vee_folder_get_location (CAMEL_VEE_FOLDER (folder), 
(CamelVeeMessageInfo *) mi, NULL);
+                                       if (location)
+                                               source = em_utils_check_send_account_override (shell, 
message, location, &identity_name, &identity_address);
+                                       g_clear_object (&mi);
+                               }
+                       }
+
+                       /* If no send account override, then guess */
+                       if (!source) {
                                source = em_utils_guess_mail_identity_with_recipients_and_sort (
                                        registry, message, folder, message_uid, &identity_name, 
&identity_address, sort_sources_by_ui, shell);
+                       }
+               }
+
+               /* In case of search folder, try to guess the store from
+                  the internal folders of it. If they are all from the same
+                  store, then use that store. */
+               if (!source && CAMEL_IS_VEE_FOLDER (folder)) {
+                       GHashTable *stores, *done_folders;
+                       GSList *todo;
+
+                       stores = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
+                       done_folders = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+                       todo = g_slist_prepend (NULL, g_object_ref (folder));
+
+                       while (todo) {
+                               CamelVeeFolder *vfolder = todo->data;
+
+                               todo = g_slist_remove (todo, vfolder);
+                               if (!g_hash_table_contains (done_folders, vfolder)) {
+                                       GList *folders, *llink;
+
+                                       g_hash_table_insert (done_folders, vfolder, NULL);
+
+                                       folders = camel_vee_folder_ref_folders (vfolder);
+                                       for (llink = folders; llink; llink = g_list_next (llink)) {
+                                               CamelFolder *subfolder = llink->data;
+
+                                               if (!g_hash_table_contains (done_folders, subfolder)) {
+                                                       if (CAMEL_IS_VEE_FOLDER (subfolder)) {
+                                                               todo = g_slist_prepend (todo, g_object_ref 
(subfolder));
+                                                       } else {
+                                                               CamelStore *store = 
camel_folder_get_parent_store (subfolder);
+
+                                                               g_hash_table_insert (done_folders, subfolder, 
NULL);
+
+                                                               if (store) {
+                                                                       g_hash_table_insert (stores, 
g_object_ref (store), NULL);
+
+                                                                       if (g_hash_table_size (stores) > 1) {
+                                                                               g_slist_free_full (todo, 
g_object_unref);
+                                                                               todo = NULL;
+                                                                               break;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+
+                                       g_list_free_full (folders, g_object_unref);
+                               }
+
+                               g_object_unref (vfolder);
+                       }
+
+                       if (g_hash_table_size (stores) == 1) {
+                               GHashTableIter iter;
+                               gpointer store;
+
+                               g_hash_table_iter_init (&iter, stores);
+                               if (g_hash_table_iter_next (&iter, &store, NULL) && store)
+                                       source = em_utils_ref_mail_identity_for_store (registry, store);
+                       }
+
+                       g_slist_free_full (todo, g_object_unref);
+                       g_hash_table_destroy (done_folders);
+                       g_hash_table_destroy (stores);
                }
 
+               g_clear_object (&message);
+
                if (!source) {
                        CamelStore *store;
 
@@ -1455,7 +1549,8 @@ set_up_new_composer (EMsgComposer *composer,
                g_object_unref (source);
        }
 
-       e_composer_header_table_set_subject (table, subject);
+       if (subject)
+               e_composer_header_table_set_subject (table, subject);
        e_composer_header_table_set_identity_uid (table, identity, identity_name, identity_address);
 
        em_utils_apply_send_account_override_to_composer (composer, folder);
@@ -1475,18 +1570,40 @@ set_up_new_composer (EMsgComposer *composer,
  *
  * Sets up a new @composer window.
  *
+ * See: em_utils_compose_new_message_with_selection()
+ *
  * Since: 3.22
  **/
 void
 em_utils_compose_new_message (EMsgComposer *composer,
                               CamelFolder *folder)
 {
+       em_utils_compose_new_message_with_selection (composer, folder, NULL);
+}
+
+/**
+ * em_utils_compose_new_message_with_selection:
+ * @composer: an #EMsgComposer
+ * @folder: (nullable): a #CamelFolder, or %NULL
+ * @message_uid: (nullable): a UID of the selected message, or %NULL
+ *
+ * Sets up a new @composer window, similar to em_utils_compose_new_message(),
+ * but also tries to identify From account more precisely, when the @folder
+ * is a search folder.
+ *
+ * Since: 3.28
+ **/
+void
+em_utils_compose_new_message_with_selection (EMsgComposer *composer,
+                                            CamelFolder *folder,
+                                            const gchar *message_uid)
+{
        g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
-       if (folder != NULL)
+       if (folder)
                g_return_if_fail (CAMEL_IS_FOLDER (folder));
 
-       set_up_new_composer (composer, "", folder, NULL, NULL);
+       set_up_new_composer (composer, "", folder, NULL, message_uid);
        composer_set_no_change (composer);
 
        gtk_widget_show (GTK_WIDGET (composer));
@@ -1570,8 +1687,9 @@ em_utils_get_composer_recipients_as_message (EMsgComposer *composer)
 }
 
 typedef struct _CreateComposerData {
-       gchar *mailto;
        CamelFolder *folder;
+       const gchar *message_uid; /* In the Camel string pool */
+       gchar *mailto;
 } CreateComposerData;
 
 static void
@@ -1581,6 +1699,7 @@ create_composer_data_free (gpointer ptr)
 
        if (ccd) {
                g_clear_object (&ccd->folder);
+               camel_pstring_free (ccd->message_uid);
                g_free (ccd->mailto);
                g_free (ccd);
        }
@@ -1612,7 +1731,7 @@ msg_composer_created_with_mailto_cb (GObject *source_object,
        if (ccd->mailto)
                e_msg_composer_setup_from_url (composer, ccd->mailto);
 
-       em_utils_apply_send_account_override_to_composer (composer, ccd->folder);
+       set_up_new_composer (composer, NULL, ccd->folder, NULL, ccd->message_uid);
 
        table = e_msg_composer_get_header_table (composer);
 
@@ -1655,21 +1774,48 @@ msg_composer_created_with_mailto_cb (GObject *source_object,
  * Opens a new composer window as a child window of @parent's toplevel
  * window. If @mailto is non-NULL, the composer fields will be filled in
  * according to the values in the mailto URL.
+ *
+ * See: em_utils_compose_new_message_with_mailto_and_selection()
  **/
 void
 em_utils_compose_new_message_with_mailto (EShell *shell,
                                           const gchar *mailto,
                                           CamelFolder *folder)
 {
+       em_utils_compose_new_message_with_mailto_and_selection (shell, mailto, folder, NULL);
+}
+
+/**
+ * em_utils_compose_new_message_with_mailto_and_selection:
+ * @shell: an #EShell
+ * @mailto: a mailto URL
+ * @folder: a #CamelFolder, or %NULL
+ * @message_uid: (nullable): a UID of the selected message, or %NULL
+ *
+ * similarly to em_utils_compose_new_message_with_mailto(), opens a new composer
+ * window as a child window of @parent's toplevel window. If @mailto is non-NULL,
+ * the composer fields will be filled in according to the values in the mailto URL.
+ * It also tries to identify From account more precisely, when the @folder
+ * is a search folder.
+ *
+ * Since: 3.28
+ **/
+void
+em_utils_compose_new_message_with_mailto_and_selection (EShell *shell,
+                                                       const gchar *mailto,
+                                                       CamelFolder *folder,
+                                                       const gchar *message_uid)
+{
        CreateComposerData *ccd;
 
        g_return_if_fail (E_IS_SHELL (shell));
 
-       if (folder != NULL)
+       if (folder)
                g_return_if_fail (CAMEL_IS_FOLDER (folder));
 
        ccd = g_new0 (CreateComposerData, 1);
        ccd->folder = folder ? g_object_ref (folder) : NULL;
+       ccd->message_uid = camel_pstring_strdup (message_uid);
        ccd->mailto = g_strdup (mailto);
 
        e_msg_composer_new (shell, msg_composer_created_with_mailto_cb, ccd);
diff --git a/src/mail/em-composer-utils.h b/src/mail/em-composer-utils.h
index d9035ea..91471bc 100644
--- a/src/mail/em-composer-utils.h
+++ b/src/mail/em-composer-utils.h
@@ -35,10 +35,19 @@ G_BEGIN_DECLS
 
 void           em_utils_compose_new_message    (EMsgComposer *composer,
                                                 CamelFolder *folder);
+void           em_utils_compose_new_message_with_selection
+                                               (EMsgComposer *composer,
+                                                CamelFolder *folder,
+                                                const gchar *message_uid);
 void           em_utils_compose_new_message_with_mailto
                                                (EShell *shell,
                                                 const gchar *mailto,
                                                 CamelFolder *folder);
+void           em_utils_compose_new_message_with_mailto_and_selection
+                                               (EShell *shell,
+                                                const gchar *mailto,
+                                                CamelFolder *folder,
+                                                const gchar *message_uid);
 void           em_utils_edit_message           (EMsgComposer *composer,
                                                 CamelFolder *folder,
                                                 CamelMimeMessage *message,
diff --git a/src/modules/mail/e-mail-shell-backend.c b/src/modules/mail/e-mail-shell-backend.c
index 0187868..99e5aae 100644
--- a/src/modules/mail/e-mail-shell-backend.c
+++ b/src/modules/mail/e-mail-shell-backend.c
@@ -40,6 +40,7 @@
 #include <mail/mail-vfolder-ui.h>
 #include <mail/importers/mail-importer.h>
 #include <mail/e-mail-ui-session.h>
+#include <mail/message-list.h>
 
 #include <em-format/e-mail-parser.h>
 #include <em-format/e-mail-formatter.h>
@@ -298,46 +299,54 @@ action_mail_account_new_cb (GtkAction *action,
                GTK_WINDOW (shell_window));
 }
 
+typedef struct _NewComposerData
+{
+       CamelFolder *folder;
+       const gchar *message_uid; /* In the Camel string pool */
+} NewComposerData;
+
 static void
 action_mail_message_new_composer_created_cb (GObject *source_object,
                                             GAsyncResult *result,
                                             gpointer user_data)
 {
-       CamelFolder *folder = user_data;
+       NewComposerData *ncd = user_data;
        EMsgComposer *composer;
        GError *error = NULL;
 
-       if (folder)
-               g_return_if_fail (CAMEL_IS_FOLDER (folder));
+       g_return_if_fail (ncd != NULL);
+
+       if (ncd->folder)
+               g_return_if_fail (CAMEL_IS_FOLDER (ncd->folder));
 
        composer = e_msg_composer_new_finish (result, &error);
        if (error) {
                g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
                g_clear_error (&error);
        } else {
-               em_utils_compose_new_message (composer, folder);
+               em_utils_compose_new_message_with_selection (composer, ncd->folder, ncd->message_uid);
        }
 
-       g_clear_object (&folder);
+       g_clear_object (&ncd->folder);
+       camel_pstring_free (ncd->message_uid);
+       g_free (ncd);
 }
 
 static void
 action_mail_message_new_cb (GtkAction *action,
                             EShellWindow *shell_window)
 {
-       EMailShellSidebar *mail_shell_sidebar;
-       EShellSidebar *shell_sidebar;
        EShellView *shell_view;
        EShell *shell;
        ESourceRegistry *registry;
-       EMFolderTree *folder_tree;
        CamelFolder *folder = NULL;
-       CamelStore *store;
        GList *list;
        const gchar *extension_name;
        const gchar *view_name;
        gboolean no_transport_defined;
-       gchar *folder_name;
+       const gchar *message_uid = NULL;
+       GtkWidget *message_list;
+       NewComposerData *ncd;
 
        shell = e_shell_window_get_shell (shell_window);
        registry = e_shell_get_registry (shell);
@@ -356,24 +365,31 @@ action_mail_message_new_cb (GtkAction *action,
                goto exit;
 
        shell_view = e_shell_window_get_shell_view (shell_window, view_name);
-       shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
 
-       mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar);
-       folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar);
+       message_list = e_mail_reader_get_message_list (E_MAIL_READER (e_shell_view_get_shell_content 
(shell_view)));
+       if (message_list) {
+               MessageList *ml = MESSAGE_LIST (message_list);
+               GPtrArray *selected_uids;
+
+               folder = message_list_ref_folder (ml);
 
-       if (em_folder_tree_get_selected (folder_tree, &store, &folder_name)) {
+               selected_uids = message_list_get_selected (ml);
+               if (selected_uids && selected_uids->len > 0)
+                       message_uid = camel_pstring_strdup (g_ptr_array_index (selected_uids, 0));
 
-               /* FIXME This blocks and is not cancellable. */
-               folder = camel_store_get_folder_sync (
-                       store, folder_name, 0, NULL, NULL);
+               if (!message_uid)
+                       message_uid = camel_pstring_strdup (ml->cursor_uid);
 
-               g_object_unref (store);
-               g_free (folder_name);
+               if (selected_uids)
+                       g_ptr_array_unref (selected_uids);
        }
 
  exit:
-       e_msg_composer_new (shell, action_mail_message_new_composer_created_cb,
-               folder ? g_object_ref (folder) : NULL);
+       ncd = g_new0 (NewComposerData, 1);
+       ncd->folder = folder;
+       ncd->message_uid = message_uid;
+
+       e_msg_composer_new (shell, action_mail_message_new_composer_created_cb, ncd);
 }
 
 static GtkActionEntry item_entries[] = {
diff --git a/src/plugins/mailing-list-actions/mailing-list-actions.c 
b/src/plugins/mailing-list-actions/mailing-list-actions.c
index fcad750..c9be893 100644
--- a/src/plugins/mailing-list-actions/mailing-list-actions.c
+++ b/src/plugins/mailing-list-actions/mailing-list-actions.c
@@ -100,6 +100,7 @@ struct _AsyncContext {
        EActivity *activity;
        EMailReader *reader;
        EmlaAction action;
+       const gchar *message_uid; /* In the Camel string pool */
 };
 
 static void
@@ -111,6 +112,8 @@ async_context_free (AsyncContext *context)
        if (context->reader != NULL)
                g_object_unref (context->reader);
 
+       camel_pstring_free (context->message_uid);
+
        g_slice_free (AsyncContext, context);
 }
 
@@ -283,7 +286,7 @@ emla_list_action_cb (CamelFolder *folder,
                                e_msg_composer_new (shell, send_message_composer_created_cb, smd);
                        } else if (send_message_response == GTK_RESPONSE_NO) {
                                /* show composer */
-                               em_utils_compose_new_message_with_mailto (shell, url, folder);
+                               em_utils_compose_new_message_with_mailto_and_selection (shell, url, folder, 
context->message_uid);
                        }
 
                        goto exit;
@@ -344,6 +347,7 @@ emla_list_action (EMailReader *reader,
        context->activity = activity;
        context->reader = g_object_ref (reader);
        context->action = action;
+       context->message_uid = camel_pstring_strdup (message_uid);
 
        folder = e_mail_reader_ref_folder (reader);
 


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