[evolution] Bug 788730 - Offer Edit Message/Open Outbox Folder when Send fails



commit ebb63fb37912d547157da81c87277f5b195dde81
Author: Milan Crha <mcrha redhat com>
Date:   Tue Oct 10 15:33:26 2017 +0200

    Bug 788730 - Offer Edit Message/Open Outbox Folder when Send fails

 src/libemail-engine/mail-ops.c |   23 +++++-
 src/libemail-engine/mail-ops.h |    3 +-
 src/mail/mail-send-recv.c      |  176 +++++++++++++++++++++++++++++++++++-----
 3 files changed, 176 insertions(+), 26 deletions(-)
---
diff --git a/src/libemail-engine/mail-ops.c b/src/libemail-engine/mail-ops.c
index 4237b39..04ea234 100644
--- a/src/libemail-engine/mail-ops.c
+++ b/src/libemail-engine/mail-ops.c
@@ -557,7 +557,9 @@ struct _send_queue_msg {
        CamelFilterStatusFunc status;
        gpointer status_data;
 
-       void (*done)(gpointer data);
+       GPtrArray *failed_uids;
+
+       gboolean (* done)(gpointer data, const GError *error, const GPtrArray *failed_uids);
        gpointer data;
 };
 
@@ -1000,6 +1002,7 @@ send_queue_exec (struct _send_queue_msg *m,
                mail_send_message (
                        m, m->queue, send_uids->pdata[i],
                        m->driver, cancellable, &local_error);
+
                if (local_error != NULL) {
                        if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
                                /* merge exceptions into one */
@@ -1022,6 +1025,11 @@ send_queue_exec (struct _send_queue_msg *m,
                                        local_error = NULL;
                                }
 
+                               if (!m->failed_uids)
+                                       m->failed_uids = g_ptr_array_new_with_free_func ((GDestroyNotify) 
camel_pstring_free);
+
+                               g_ptr_array_add (m->failed_uids, (gpointer) camel_pstring_strdup 
(send_uids->pdata[i]));
+
                                /* keep track of the number of failures */
                                j++;
                        } else {
@@ -1075,8 +1083,13 @@ send_queue_exec (struct _send_queue_msg *m,
 static void
 send_queue_done (struct _send_queue_msg *m)
 {
-       if (m->done)
-               m->done (m->data);
+       if (m->done) {
+               if (g_error_matches (m->base.error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+                       m->done (m->data, NULL, NULL);
+               } else if (m->done (m->data, m->base.error, m->failed_uids)) {
+                       g_clear_error (&m->base.error);
+               }
+       }
 }
 
 static gchar *
@@ -1094,6 +1107,8 @@ send_queue_free (struct _send_queue_msg *m)
                g_object_unref (m->driver);
        if (m->transport != NULL)
                g_object_unref (m->transport);
+       if (m->failed_uids)
+               g_ptr_array_unref (m->failed_uids);
        g_object_unref (m->queue);
 }
 
@@ -1118,7 +1133,7 @@ mail_send_queue (EMailSession *session,
                  gpointer get_data,
                  CamelFilterStatusFunc status,
                  gpointer status_data,
-                 void (*done)(gpointer data),
+                 gboolean (* done)(gpointer data, const GError *error, const GPtrArray *failed_uids),
                  gpointer data)
 {
        struct _send_queue_msg *m;
diff --git a/src/libemail-engine/mail-ops.h b/src/libemail-engine/mail-ops.h
index 35b971b..7d7c744 100644
--- a/src/libemail-engine/mail-ops.h
+++ b/src/libemail-engine/mail-ops.h
@@ -62,7 +62,8 @@ void          mail_send_queue                 (EMailSession *session,
                                                 gpointer get_data,
                                                 CamelFilterStatusFunc status,
                                                 gpointer status_data,
-                                                void (*done)(gpointer data),
+                                                 /* Return %TRUE, when the error had been reported to the 
user */
+                                                gboolean (* done)(gpointer data, const GError *error, const 
GPtrArray *failed_uids),
                                                 gpointer data);
 
 typedef void   (*MailProviderFetchLockFunc)    (const gchar *source);
diff --git a/src/mail/mail-send-recv.c b/src/mail/mail-send-recv.c
index 4ffe1f9..42adbc6 100644
--- a/src/mail/mail-send-recv.c
+++ b/src/mail/mail-send-recv.c
@@ -32,6 +32,7 @@
 #include <e-util/e-util.h>
 
 #include "e-mail-account-store.h"
+#include "e-mail-reader-utils.h"
 #include "e-mail-ui-session.h"
 #include "em-event.h"
 #include "em-filter-rule.h"
@@ -124,7 +125,7 @@ static CamelFolder *
                                                 const gchar *uri,
                                                 gpointer data,
                                                 GError **error);
-static void    send_done (gpointer data);
+static gboolean        send_done (gpointer data, const GError *error, const GPtrArray *failed_uids);
 
 static struct _send_data *send_data = NULL;
 static GtkWidget *send_recv_dialog = NULL;
@@ -435,24 +436,11 @@ format_service_name (CamelService *service)
        return pretty_url;
 }
 
-struct ReportErrorToUIData
+static EShellView *
+mail_send_receive_get_mail_shell_view (void)
 {
-       gchar *display_name;
-       gchar *error_ident;
-       GError *error;
-};
-
-static gboolean
-report_error_to_ui_cb (gpointer user_data)
-{
-       struct ReportErrorToUIData *data = user_data;
        EShellView *shell_view = NULL;
 
-       g_return_val_if_fail (data != NULL, FALSE);
-       g_return_val_if_fail (data->display_name != NULL, FALSE);
-       g_return_val_if_fail (data->error_ident != NULL, FALSE);
-       g_return_val_if_fail (data->error != NULL, FALSE);
-
        if (send_recv_dialog) {
                GtkWidget *parent;
 
@@ -478,6 +466,97 @@ report_error_to_ui_cb (gpointer user_data)
                }
        }
 
+       return shell_view;
+}
+
+static void
+mail_send_recv_send_fail_alert_response_cb (EAlert *alert,
+                                           gint response_id,
+                                           gpointer user_data)
+{
+       EShellView *shell_view;
+       EShellContent *shell_content;
+       EShellSidebar *shell_sidebar;
+       EMFolderTree *folder_tree = NULL;
+       EMailSession *session;
+       CamelFolder *outbox;
+       GPtrArray *uids;
+
+       if (response_id != GTK_RESPONSE_APPLY && response_id != GTK_RESPONSE_REJECT)
+               return;
+
+       shell_view = mail_send_receive_get_mail_shell_view ();
+       if (!shell_view)
+               return;
+
+       shell_content = e_shell_view_get_shell_content (shell_view);
+       shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
+
+       g_object_get (G_OBJECT (shell_sidebar), "folder-tree", &folder_tree, NULL);
+       g_return_if_fail (folder_tree != NULL);
+
+       session = em_folder_tree_get_session (folder_tree);
+       outbox = e_mail_session_get_local_folder (session, E_MAIL_LOCAL_FOLDER_OUTBOX);
+
+       uids = g_object_get_data (G_OBJECT (alert), "message-uids");
+
+       if (uids && response_id == GTK_RESPONSE_APPLY) {
+               e_mail_reader_edit_messages (E_MAIL_READER (shell_content), outbox, uids, TRUE, TRUE);
+       } else if (folder_tree) {
+               gchar *folder_uri;
+
+               folder_uri = e_mail_folder_uri_from_folder (outbox);
+               g_warn_if_fail (folder_uri != NULL);
+
+               if (folder_uri) {
+                       CamelFolder *selected_folder;
+
+                       em_folder_tree_set_selected (folder_tree, folder_uri, FALSE);
+
+                       selected_folder = e_mail_reader_ref_folder (E_MAIL_READER (shell_content));
+
+                       /* This makes sure the Outbox folder content is shown even
+                          when the On This Computer account is disabled */
+                       if (selected_folder != outbox) {
+                               GtkTreeSelection *selection;
+
+                               selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_tree));
+                               gtk_tree_selection_unselect_all (selection);
+
+                               em_folder_tree_set_selected (folder_tree, folder_uri, FALSE);
+                               e_mail_reader_set_folder (E_MAIL_READER (shell_content), outbox);
+                       }
+
+                       g_clear_object (&selected_folder);
+               }
+
+               g_free (folder_uri);
+       }
+
+       g_clear_object (&folder_tree);
+}
+
+struct ReportErrorToUIData
+{
+       gchar *display_name;
+       gchar *error_ident;
+       GError *error;
+       GPtrArray *send_failed_uids;
+};
+
+static gboolean
+report_error_to_ui_cb (gpointer user_data)
+{
+       struct ReportErrorToUIData *data = user_data;
+       EShellView *shell_view;
+
+       g_return_val_if_fail (data != NULL, FALSE);
+       g_return_val_if_fail (data->display_name != NULL, FALSE);
+       g_return_val_if_fail (data->error_ident != NULL, FALSE);
+       g_return_val_if_fail (data->error != NULL, FALSE);
+
+       shell_view = mail_send_receive_get_mail_shell_view ();
+
        if (shell_view) {
                EShellContent *shell_content;
                EAlertSink *alert_sink;
@@ -489,6 +568,29 @@ report_error_to_ui_cb (gpointer user_data)
                alert = e_alert_new (data->error_ident, data->display_name,
                        data->error->message ? data->error->message : _("Unknown error"), NULL);
 
+               if (data->send_failed_uids) {
+                       GtkAction *action;
+
+                       if (data->send_failed_uids->len == 1) {
+                               g_object_set_data_full (G_OBJECT (alert), "message-uids",
+                                       g_ptr_array_ref (data->send_failed_uids),
+                                       (GDestroyNotify) g_ptr_array_unref);
+                       }
+
+                       if (data->send_failed_uids->len == 1) {
+                               action = gtk_action_new ("send-failed-edit-action", _("Edit Message"), NULL, 
NULL);
+                               e_alert_add_action (alert, action, GTK_RESPONSE_APPLY);
+                               g_object_unref (action);
+                       }
+
+                       action = gtk_action_new ("send-failed-outbox-action", _("Open Outbox Folder"), NULL, 
NULL);
+                       e_alert_add_action (alert, action, GTK_RESPONSE_REJECT);
+                       g_object_unref (action);
+
+                       g_signal_connect (alert, "response",
+                               G_CALLBACK (mail_send_recv_send_fail_alert_response_cb), NULL);
+               }
+
                e_alert_sink_submit_alert (alert_sink, alert);
 
                g_object_unref (alert);
@@ -500,6 +602,8 @@ report_error_to_ui_cb (gpointer user_data)
        g_free (data->display_name);
        g_free (data->error_ident);
        g_error_free (data->error);
+       if (data->send_failed_uids)
+               g_ptr_array_unref (data->send_failed_uids);
        g_free (data);
 
        return FALSE;
@@ -508,7 +612,8 @@ report_error_to_ui_cb (gpointer user_data)
 static void
 report_error_to_ui (CamelService *service,
                    const gchar *folder_name,
-                   const GError *error)
+                   const GError *error,
+                   const GPtrArray *send_failed_uids)
 {
        gchar *tmp = NULL;
        const gchar *display_name, *ident;
@@ -527,6 +632,9 @@ report_error_to_ui (CamelService *service,
                        folder_name);
                display_name = tmp;
                ident = "mail:no-refresh-folder";
+       } else if (send_failed_uids) {
+               display_name = _("Sending message");
+               ident = "mail:async-error";
        } else {
                display_name = camel_service_get_display_name (service);
                ident = "mail:failed-connect";
@@ -537,6 +645,18 @@ report_error_to_ui (CamelService *service,
        data->error_ident = g_strdup (ident);
        data->error = g_error_copy (error);
 
+       if (send_failed_uids) {
+               gint ii;
+
+               data->send_failed_uids = g_ptr_array_new_full (send_failed_uids->len + 1, (GDestroyNotify) 
camel_pstring_free);
+
+               for (ii = 0; ii < send_failed_uids->len; ii++) {
+                       g_ptr_array_add (data->send_failed_uids, (gpointer) camel_pstring_strdup 
(g_ptr_array_index (send_failed_uids, ii)));
+               }
+       } else {
+               data->send_failed_uids = NULL;
+       }
+
        g_idle_add_full (G_PRIORITY_DEFAULT, report_error_to_ui_cb, data, NULL);
 
        g_free (tmp);
@@ -1004,10 +1124,24 @@ receive_done (gpointer data)
        free_send_info (info);
 }
 
-static void
-send_done (gpointer data)
+static gboolean
+send_done (gpointer data,
+          const GError *error,
+          const GPtrArray *failed_uids)
 {
+       gboolean res = FALSE;
+
+       if (error && failed_uids) {
+               struct _send_info *info = data;
+
+               res = TRUE;
+
+               report_error_to_ui (info->service, NULL, error, failed_uids);
+       }
+
        receive_done (data);
+
+       return res;
 }
 /* although we dont do anythign smart here yet, there is no need for this interface to
  * be available to anyone else.
@@ -1305,7 +1439,7 @@ refresh_folders_exec (struct _refresh_folders_msg *m,
                                        full_name = (const gchar *) m->folders->pdata[i];
                                }
 
-                               report_error_to_ui (CAMEL_SERVICE (store), full_name, local_error);
+                               report_error_to_ui (CAMEL_SERVICE (store), full_name, local_error, NULL);
 
                                /* To not report one error for multiple folders multiple times */
                                g_hash_table_insert (known_errors, g_strdup (error_message), GINT_TO_POINTER 
(1));
@@ -1384,7 +1518,7 @@ receive_update_got_folderinfo (GObject *source_object,
        /* XXX Need to hand this off to an EAlertSink. */
        } else if (local_error != NULL) {
                g_warn_if_fail (info == NULL);
-               report_error_to_ui (send_info->service, NULL, local_error);
+               report_error_to_ui (send_info->service, NULL, local_error, NULL);
                g_error_free (local_error);
 
                receive_done (send_info);


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