* Fixes NB#83513, modest no longer hungs when deleting mails while the connection...
authorSergio Villar Senin <svillar@igalia.com>
Wed, 2 Apr 2008 14:38:04 +0000 (14:38 +0000)
committerSergio Villar Senin <svillar@igalia.com>
Wed, 2 Apr 2008 14:38:04 +0000 (14:38 +0000)
* Replaced the sync version of remove_msgs by the async one
* Fixed the D-Bus delete method that was incorrectly implemented

pmo-trunk-r4362

src/dbus_api/modest-dbus-callbacks.c
src/modest-mail-operation.c
src/modest-mail-operation.h

index 2a6f156..b62e9c3 100644 (file)
@@ -627,10 +627,43 @@ on_open_message (GArray * arguments, gpointer data, osso_rpc_t * retval)
        return osso_retval;
 }
 
+static void 
+on_remove_msgs_finished (ModestMailOperation *mail_op,
+                        gpointer user_data)
+{      
+       TnyHeader *header;
+       ModestWindow *main_win = NULL, *msg_view = NULL;
+       ModestHeaderView *header_view;
+
+       header = (TnyHeader *) user_data;
+
+       /* Get the main window if exists */
+       main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
+                                                     FALSE); /* don't create */
+       if (!main_win) {
+               g_object_unref (header);
+               return;
+       }
+
+       if (modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr(),
+                                                     header, &msg_view)) {
+               if (MODEST_IS_MSG_VIEW_WINDOW (msg_view))
+                       modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (msg_view));
+       }       
+       g_object_unref (header);
+
+       /* Refilter the header view explicitly */
+       header_view = (ModestHeaderView *)
+               modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(main_win),
+                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
+       if (header_view && MODEST_IS_HEADER_VIEW (header_view))
+               modest_header_view_refilter (header_view);
+}
+
 static gboolean
 on_idle_delete_message (gpointer user_data)
 {
-       TnyList *headers = NULL;
+       TnyList *headers = NULL, *tmp_headers = NULL;
        TnyFolder *folder = NULL;
        TnyIterator *iter = NULL; 
        TnyHeader *header = NULL, *msg_header = NULL;
@@ -638,38 +671,41 @@ on_idle_delete_message (gpointer user_data)
        TnyAccount *account = NULL;
        const char *uri = NULL;
        gchar *uid = NULL;
-       gint res = 0;
        ModestMailOperation *mail_op = NULL;
-       ModestWindow *main_win = NULL, *msg_view = NULL;
+       ModestWindow *main_win = NULL;
 
        uri = (char *) user_data;
        
        msg = find_message_by_url (uri, &account);
+       if (account)
+               g_object_unref (account);
 
        if (!msg) {
                g_warning ("%s: Could not find message '%s'", __FUNCTION__, uri);
                g_idle_add (notify_error_in_dbus_callback, NULL);
-               return OSSO_ERROR; 
+               return FALSE; 
        }
        
        main_win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
                                                      FALSE); /* don't create */
        
-       msg_header = tny_msg_get_header (msg);
        folder = tny_msg_get_folder (msg);
-
        if (!folder) {
                g_warning ("%s: Could not find folder (uri:'%s')", __FUNCTION__, uri);
                g_object_unref (msg);
                g_idle_add (notify_error_in_dbus_callback, NULL);
-               return OSSO_ERROR; 
+               return FALSE; 
        }
 
+       /* Get UID */
+       msg_header = tny_msg_get_header (msg);
        uid = tny_header_dup_uid (msg_header);
+       g_object_unref (msg);
+       g_object_unref (msg_header);
+
        headers = tny_simple_list_new ();
        tny_folder_get_headers (folder, headers, TRUE, NULL);
        iter = tny_list_create_iterator (headers);
-       header = NULL;
 
        while (!tny_iterator_is_done (iter)) {
                gchar *cur_id = NULL;
@@ -693,80 +729,42 @@ on_idle_delete_message (gpointer user_data)
                tny_iterator_next (iter);
        }
        g_free (uid);
-
        g_object_unref (iter);
-       iter = NULL;
        g_object_unref (headers);
-       headers = NULL;
-       
-       g_object_unref (msg_header);
-       msg_header = NULL;
-       g_object_unref (msg);
-       msg = NULL;
 
        if (header == NULL) {
                if (folder)
                        g_object_unref (folder);
                g_idle_add (notify_error_in_dbus_callback, NULL);                       
-               return OSSO_ERROR;
+               return FALSE;
        }
                
-       res = OSSO_OK;
-
        /* This is a GDK lock because we are an idle callback and
         * the code below is or does Gtk+ code */
        gdk_threads_enter (); /* CHECKED */
 
        mail_op = modest_mail_operation_new (main_win ? G_OBJECT(main_win) : NULL);
        modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
-       modest_mail_operation_remove_msg (mail_op, header, FALSE);
+
+       g_signal_connect (G_OBJECT (mail_op),
+                         "operation-finished",
+                         G_CALLBACK (on_remove_msgs_finished),
+                         g_object_ref (header));
+
+       tmp_headers = tny_simple_list_new ();
+       tny_list_append (tmp_headers, (GObject *) header);
+
+       modest_mail_operation_remove_msgs (mail_op, tmp_headers, FALSE);
+
+       g_object_unref (tmp_headers);
        g_object_unref (G_OBJECT (mail_op));
-       
-       if (main_win) { /* no need if there's no window */ 
-               if (modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr(),
-                                                             header, &msg_view)) {
-                       if (MODEST_IS_MSG_VIEW_WINDOW (msg_view))
-                               modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (msg_view));
-               }
-       }
        gdk_threads_leave (); /* CHECKED */
        
+       /* Clean */
        if (header)
                g_object_unref (header);
        
-       if (folder) {
-               /* Trick: do a poke status in order to speed up the signaling
-                  of observers.
-                  A delete via the menu does this, in do_headers_action(), 
-                  though I don't know why.
-                */
-               tny_folder_poke_status (folder);
-       
-               g_object_unref (folder);
-       }
-       
-       if (account)
-               g_object_unref (account);
-               
-       /* Refilter the header view explicitly, to make sure that 
-        * deleted emails are really removed from view. 
-        * (They are not really deleted until contact is made with the server, 
-        * so they would appear with a strike-through until then):
-        */
-       if (main_win) { /* only needed when there's a mainwindow / UI */
-
-               /* This is a GDK lock because we are an idle callback and
-                * the code below is or does Gtk+ code */
-               gdk_threads_enter (); /* CHECKED */
-               ModestHeaderView *header_view = (ModestHeaderView *)
-                       modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(main_win),
-                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
-               if (header_view && MODEST_IS_HEADER_VIEW (header_view))
-                       modest_header_view_refilter (header_view);
-               gdk_threads_leave ();
-       }
-       
-       return res;
+       return FALSE;
 }
 
 
index b5289b1..4839f04 100644 (file)
@@ -102,6 +102,11 @@ static guint    compute_message_array_size (GPtrArray *headers);
 static int      compare_headers_by_date   (gconstpointer a,
                                           gconstpointer b);
 
+static void     sync_folder_finish_callback (TnyFolder *self, 
+                                            gboolean cancelled, 
+                                            GError *err, 
+                                            gpointer user_data);
+
 enum _ModestMailOperationSignals 
 {
        PROGRESS_CHANGED_SIGNAL,
@@ -2386,81 +2391,64 @@ modest_mail_operation_get_msgs_full (ModestMailOperation *self,
 }
 
 
-void 
-modest_mail_operation_remove_msg (ModestMailOperation *self,  
-                                 TnyHeader *header,
-                                 gboolean remove_to_trash /*ignored*/)
-{
-       TnyFolder *folder;
+static void
+remove_msgs_async_cb (TnyFolder *folder, 
+                     gboolean canceled, 
+                     GError *err, 
+                     gpointer user_data)
+{
+       gboolean expunge, leave_on_server;
+       const gchar *account_name;
+       const gchar *proto;
+       TnyAccount *account;
+       ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
+       ModestMailOperation *self;
        ModestMailOperationPrivate *priv;
 
-       g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
-       g_return_if_fail (TNY_IS_HEADER (header));
-
-       if (remove_to_trash)
-               g_warning ("remove to trash is not implemented");
-
+       self = (ModestMailOperation *) user_data;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
-       folder = tny_header_get_folder (header);
-
-       /* Get account and set it into mail_operation */
-       priv->account = modest_tny_folder_get_account (TNY_FOLDER(folder));
-       priv->op_type = MODEST_MAIL_OPERATION_TYPE_DELETE;
-       priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
-
-       /* remove message from folder */
-       tny_folder_remove_msg (folder, header, &(priv->error));
-       if (!priv->error) {
-               gboolean expunge, leave_on_server;
-               const gchar *account_name;
-               TnyAccount *account;
-               ModestTransportStoreProtocol account_proto;
-
-               tny_header_set_flag (header, TNY_HEADER_FLAG_DELETED);
-               tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
-
-               modest_mail_operation_notify_start (self);
-
-               /* Get leave on server setting */
-               account = tny_folder_get_account (folder);
-               account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
-               leave_on_server =
-                       modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
-                                                               account_name);
-
-               account_proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
 
-               if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
-                   modest_tny_folder_is_remote_folder (folder) == FALSE)
-                       expunge = TRUE;
-               else
-                       expunge = FALSE;
+       if (canceled || err) {
+               /* If canceled by the user, ignore the error given by Tinymail */
+               if (canceled) {
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
+               } else if (err) {
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
+                       priv->error = g_error_copy ((const GError *) err);
+                       priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
+               }
+               /* Exit */
+               modest_mail_operation_notify_end (self);
+               g_object_unref (self);
+               return;
+       }
 
-               /* Sync folder */
-               tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
+       account = tny_folder_get_account (folder);
+       account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
+       leave_on_server =
+               modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
+                                                       account_name);  
+       proto = tny_account_get_proto (account);
+       g_object_unref (account);
 
-               /* Unref */
-               g_object_unref (account);
-       }
+       if (proto)
+               account_proto = modest_protocol_info_get_transport_store_protocol (proto);
        
-       
-       /* Set status */
-       if (!priv->error)
-               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
+       if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
+                   modest_tny_folder_is_remote_folder (folder) == FALSE)
+               expunge = TRUE;
        else
-               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-
-       /* Free */
-       g_object_unref (G_OBJECT (folder));
-
-       /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
+               expunge = FALSE;
+       
+       /* Sync folder */
+       tny_folder_sync_async(folder, expunge, sync_folder_finish_callback, 
+                             NULL, self);
 }
 
 void 
 modest_mail_operation_remove_msgs (ModestMailOperation *self,  
                                   TnyList *headers,
-                                 gboolean remove_to_trash /*ignored*/)
+                                  gboolean remove_to_trash /*ignored*/)
 {
        TnyFolder *folder = NULL;
        ModestMailOperationPrivate *priv;
@@ -2531,46 +2519,9 @@ modest_mail_operation_remove_msgs (ModestMailOperation *self,
 
        /* remove message from folder */
        modest_mail_operation_notify_start (self);
+       tny_folder_remove_msgs_async (folder, remove_headers, remove_msgs_async_cb, 
+                                     NULL, g_object_ref (self));
 
-       tny_folder_remove_msgs (folder, remove_headers, &(priv->error));
-       if (!priv->error) {
-               gboolean expunge, leave_on_server;
-               const gchar *account_name;
-               const gchar *proto;
-               TnyAccount *account;
-               ModestTransportStoreProtocol account_proto = MODEST_PROTOCOL_TRANSPORT_STORE_UNKNOWN;
-               
-               account = tny_folder_get_account (folder);
-               account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
-               leave_on_server =
-                       modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
-                                                               account_name);
-               
-               proto = tny_account_get_proto (account);
-               if (proto) {
-                       account_proto = modest_protocol_info_get_transport_store_protocol (proto);
-               }
-               
-               if (((account_proto == MODEST_PROTOCOL_STORE_POP) && !leave_on_server) ||
-                   modest_tny_folder_is_remote_folder (folder) == FALSE)
-                       expunge = TRUE;
-               else
-                       expunge = FALSE;
-
-               /* Sync folder */
-               tny_folder_sync_async(folder, expunge, NULL, NULL, NULL);
-               
-               g_object_unref (account);
-       }
-       
-       
-       /* Set status */
-       if (!priv->error)
-               priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
-       else
-               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-
-       /* Free */
 cleanup:
        if (remove_headers)
                g_object_unref (remove_headers);
@@ -2580,9 +2531,6 @@ cleanup:
                g_object_unref (iter);
        if (folder)
                g_object_unref (folder);
-
-       /* Notify about operation end */
-       modest_mail_operation_notify_end (self);
 }
 
 static void
@@ -3076,19 +3024,35 @@ modest_mail_operation_run_queue (ModestMailOperation *self,
 }
 
 static void
-sync_folder_finish_callback (TnyFolder *self, gboolean cancelled, GError *err, ModestMailOperation *mail_op)
+sync_folder_finish_callback (TnyFolder *self, 
+                            gboolean cancelled, 
+                            GError *err, 
+                            gpointer user_data)
+
 {
+       ModestMailOperation *mail_op;
        ModestMailOperationPrivate *priv;
 
+       mail_op = (ModestMailOperation *) user_data;
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE (mail_op);
-       if (err != NULL) {
-               g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
-                            MODEST_MAIL_OPERATION_ERROR_OPERATION_CANCELED,
-                            err->message);
-               priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+
+       /* If canceled by the user, ignore the error given by Tinymail */
+       if (cancelled) {
+               priv->status = MODEST_MAIL_OPERATION_STATUS_CANCELED;
+       } else if (err) {
+               /* If the operation was a sync then the status is
+                  failed, but if it's part of another operation then
+                  just set it as finished with errors */
+               if (priv->op_type == MODEST_MAIL_OPERATION_TYPE_SYNC_FOLDER)
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
+               else
+                       priv->status = MODEST_MAIL_OPERATION_STATUS_FINISHED_WITH_ERRORS;
+               priv->error = g_error_copy ((const GError *) err);
+               priv->error->domain = MODEST_MAIL_OPERATION_ERROR;
        } else {
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
        }
+
        modest_mail_operation_notify_end (mail_op);
        g_object_unref (mail_op);
 }
index f646929..1e44cf5 100644 (file)
@@ -576,21 +576,6 @@ void          modest_mail_operation_xfer_msgs      (ModestMailOperation *self,
 /**
  * modest_mail_operation_remove_msg:
  * @self: a #ModestMailOperation
- * @header: the #TnyHeader of the message to move
- * @remove_to_trash: TRUE to move it to trash or FALSE to delete it
- * permanently
- * 
- * Deletes a message. This operation is synchronous, so the
- * #ModestMailOperation should not be added to any
- * #ModestMailOperationQueue
- **/
-void          modest_mail_operation_remove_msg     (ModestMailOperation *self,
-                                                   TnyHeader *header,
-                                                   gboolean remove_to_trash);
-
-/**
- * modest_mail_operation_remove_msg:
- * @self: a #ModestMailOperation
  * @headers: the #TnyList of the messages to delete
  * @remove_to_trash: TRUE to move it to trash or FALSE to delete it
  * permanently