* Created a new get_full_msgs mail operation to asynchronously receive several full...
authorSergio Villar Senin <svillar@igalia.com>
Fri, 18 May 2007 10:01:23 +0000 (10:01 +0000)
committerSergio Villar Senin <svillar@igalia.com>
Fri, 18 May 2007 10:01:23 +0000 (10:01 +0000)
pmo-trunk-r1905

src/maemo/modest-msg-view-window.c
src/modest-mail-operation.c
src/modest-mail-operation.h
src/modest-ui-actions.c

index 4503d96..3c6d2d0 100644 (file)
@@ -96,7 +96,7 @@ static void         on_queue_changed                     (ModestMailOperationQue
                                                          ModestMailOperationQueueNotification type,
                                                          ModestMsgViewWindow *self);
 
-static void view_msg_cb (const GObject *obj, const TnyMsg *msg, gpointer user_data);
+static void view_msg_cb (const GObject *obj, TnyMsg *msg, gpointer user_data);
 
 static void set_toolbar_mode (ModestMsgViewWindow *self, 
                              ModestToolBarModes mode);
@@ -1056,7 +1056,7 @@ modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
 }
 
 static void
-view_msg_cb(const GObject *obj, const TnyMsg *msg, gpointer user_data)
+view_msg_cb(const GObject *obj, TnyMsg *msg, gpointer user_data)
 {
        ModestMsgViewWindow *self = NULL;
        ModestMsgViewWindowPrivate *priv = NULL;
index 52f6bbd..33961a2 100644 (file)
@@ -56,9 +56,9 @@ static void modest_mail_operation_class_init (ModestMailOperationClass *klass);
 static void modest_mail_operation_init       (ModestMailOperation *obj);
 static void modest_mail_operation_finalize   (GObject *obj);
 
-static void     update_process_msg_status_cb (GObject *obj,
-                                             TnyStatus *status,  
-                                             gpointer user_data);
+/* static void     update_process_msg_status_cb (GObject *obj, */
+/*                                           TnyStatus *status,   */
+/*                                           gpointer user_data); */
 static void     get_msg_cb (TnyFolder *folder, 
                            gboolean cancelled, 
                            TnyMsg *msg, 
@@ -102,15 +102,6 @@ typedef struct _GetMsgAsyncHelper {
        gpointer user_data;
 } GetMsgAsyncHelper;
 
-typedef struct _RefreshFolderAsyncHelper
-{
-       ModestMailOperation *mail_op;
-       TnyIterator *iter;
-       guint failed;
-       guint canceled;
-
-} RefreshFolderAsyncHelper;
-
 typedef struct _XFerMsgAsyncHelper
 {
        ModestMailOperation *mail_op;
@@ -126,7 +117,6 @@ typedef struct _XFerFolderAsyncHelper
 
 } XFerFolderAsyncHelper;
 
-
 /* globals */
 static GObjectClass *parent_class = NULL;
 
@@ -423,8 +413,8 @@ recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all
 }
 
 /* 
- * Used by update_account_thread to emit the signal from the main
- * loop. We call it inside an idle call to achieve that 
+ * Used by update_account_thread to emit the "progress-changed" signal
+ * from the main loop. We call it inside an idle call to achieve that
  */
 static gboolean
 notify_update_account_observers (gpointer data)
@@ -540,13 +530,14 @@ update_account_thread (gpointer thr_user_data)
        }
 
  out:
-       /* Notify the queue */
-       g_idle_add (notify_update_account_queue, g_object_ref (info->mail_op));
+       /* Notify the queue. Note that the info could be freed before
+          this idle happens, but the mail operation will be still
+          alive */
+       g_idle_add (notify_update_account_queue, info->mail_op);
 
        /* Frees */
        g_object_unref (query);
        g_object_unref (all_folders);
-       g_object_unref (info->mail_op);
        g_object_unref (info->account);
        g_object_unref (info->transport_account);
        g_slice_free (UpdateAccountInfo, info);
@@ -608,7 +599,7 @@ modest_mail_operation_update_account (ModestMailOperation *self,
 
        /* Create the helper object */
        info = g_slice_new (UpdateAccountInfo);
-       info->mail_op = g_object_ref (self);
+       info->mail_op = self;
        info->account = modest_account;
        info->transport_account = transport_account;
 
@@ -1008,10 +999,10 @@ modest_mail_operation_xfer_folder_async (ModestMailOperation *self,
 /* **************************  MSG  ACTIONS  ************************* */
 /* ******************************************************************* */
 
-void          modest_mail_operation_get_msg     (ModestMailOperation *self,
-                                                TnyHeader *header,
-                                                GetMsgAsynUserCallback user_callback,
-                                                gpointer user_data)
+void modest_mail_operation_get_msg (ModestMailOperation *self,
+                                   TnyHeader *header,
+                                   GetMsgAsynUserCallback user_callback,
+                                   gpointer user_data)
 {
        GetMsgAsyncHelper *helper = NULL;
        TnyFolder *folder;
@@ -1128,97 +1119,171 @@ get_msg_status_cb (GObject *obj,
        g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
 }
 
+/****************************************************/
+typedef struct {
+       ModestMailOperation *mail_op;
+       TnyList *headers;
+       GetMsgAsynUserCallback user_callback;
+       gpointer user_data;
+       GDestroyNotify notify;
+} GetFullMsgsInfo;
+
+/* 
+ * Used by get_msgs_full_thread to emit the "progress-changed" signal
+ * from the main loop. We call it inside an idle call to achieve that
+ */
+static gboolean
+notify_get_msgs_full_observers (gpointer data)
+{
+       ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
+
+       g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
+
+       g_object_unref (mail_op);
+
+       return FALSE;
+}
+
+typedef struct {
+       GetMsgAsynUserCallback user_callback;
+       TnyMsg *msg;
+       gpointer user_data;
+       GObject *source;
+} NotifyGetMsgsInfo;
+
+static gboolean
+notify_get_msgs_full (gpointer data)
+{
+       NotifyGetMsgsInfo *info;
+
+       info = (NotifyGetMsgsInfo *) data;      
+
+       /* Call the user callback */
+       info->user_callback (info->source, info->msg, info->user_data);
+
+       g_slice_free (NotifyGetMsgsInfo, info);
+
+       return FALSE;
+}
+
+static gboolean
+get_msgs_full_destroyer (gpointer data)
+{
+       GetFullMsgsInfo *info;
+
+       info = (GetFullMsgsInfo *) data;
+
+       if (info->notify)
+               info->notify (info->user_data);
+
+       /* free */
+       g_object_unref (info->headers);
+       g_slice_free (GetFullMsgsInfo, info);
+
+       return FALSE;
+}
 
-void          modest_mail_operation_process_msg     (ModestMailOperation *self,
-                                                    TnyList *header_list, 
-                                                    GetMsgAsynUserCallback user_callback,
-                                                    gpointer user_data)
+static gpointer
+get_msgs_full_thread (gpointer thr_user_data)
 {
+       GetFullMsgsInfo *info;
        ModestMailOperationPrivate *priv = NULL;
-       GetMsgAsyncHelper *helper = NULL;
-       TnyHeader *header = NULL;
-       TnyFolder *folder = NULL;
        TnyIterator *iter = NULL;
        
-       g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
-       
-       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
-       priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
-
-       iter = tny_list_create_iterator (header_list); 
-       priv->done = 1;
-       priv->total = tny_list_get_length(header_list);
-
-       helper = g_slice_new0 (GetMsgAsyncHelper);
-       helper->mail_op = self;
-       helper->user_callback = user_callback;
-       helper->pending_ops = priv->total;
-       helper->user_data = user_data;
+       info = (GetFullMsgsInfo *) thr_user_data;       
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (info->mail_op);
 
-       while (!tny_iterator_is_done (iter)) { 
+       iter = tny_list_create_iterator (info->headers);
+       while (!tny_iterator_is_done (iter) && !priv->error) { 
+               TnyHeader *header;
+               TnyFolder *folder;
                
-               header = TNY_HEADER (tny_iterator_get_current (iter));          
+               header = TNY_HEADER (tny_iterator_get_current (iter));
                folder = tny_header_get_folder (header);
                                
                /* Get message from folder */
                if (folder) {
+                       TnyMsg *msg;
                        /* The callback will call it per each header */
-                       tny_folder_get_msg_async (folder, header, get_msg_cb, update_process_msg_status_cb, helper);
-                       g_object_unref (G_OBJECT (folder));
-               } else {                        
+                       msg = tny_folder_get_msg (folder, header, &(priv->error));
+
+                       if (msg) {
+                               priv->done++;
+
+                               /* notify progress */
+                               g_idle_add_full (G_PRIORITY_HIGH_IDLE,
+                                                notify_get_msgs_full_observers, 
+                                                g_object_ref (info->mail_op), NULL);
+
+                               /* The callback is the responsible for
+                                  freeing the message */
+                               if (info->user_callback) {
+                                       NotifyGetMsgsInfo *info_notify;
+                                       info_notify = g_slice_new0 (NotifyGetMsgsInfo);
+                                       info_notify->user_callback = info->user_callback;
+                                       info_notify->source = priv->source;
+                                       info_notify->msg = msg;
+                                       info_notify->user_data = info->user_data;
+                                       g_idle_add_full (G_PRIORITY_HIGH_IDLE,
+                                                        notify_get_msgs_full, 
+                                                        info_notify, NULL);
+                               } else {
+                                       g_object_unref (msg);
+                               }
+                       }
+               } else {
                        /* Set status failed and set an error */
                        priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                        g_set_error (&(priv->error), MODEST_MAIL_OPERATION_ERROR,
                                     MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
-                                    _("Error trying to get a message. No folder found for header"));
-
-                       /* Notify the queue */
-                       modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
-
-                       /* free */
-                       g_slice_free (GetMsgAsyncHelper, helper);
-                       break;
+                                    "Error trying to get a message. No folder found for header");
                }
 
                g_object_unref (header);                
                tny_iterator_next (iter);
        }
-}
 
-static void     
-update_process_msg_status_cb (GObject *obj,
-                             TnyStatus *status,  
-                             gpointer user_data)
-{
-       GetMsgAsyncHelper *helper = NULL;
-       ModestMailOperation *self;
-       ModestMailOperationPrivate *priv;
-
-       g_return_if_fail (status != NULL);
-       g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_GET_MSG);
+       /* Notify the queue */
+       g_idle_add (notify_update_account_queue, info->mail_op);
 
-       helper = (GetMsgAsyncHelper *) user_data;
-       g_return_if_fail (helper != NULL);       
+       /* Free thread resources. Will be called after all previous idles */
+       g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 1, get_msgs_full_destroyer, info, NULL);
 
-       /* Temporary FIX: useful when tinymail send us status
-          information *after* calling the function callback */
-       if (!MODEST_IS_MAIL_OPERATION (helper->mail_op))
-               return;
-
-       self = helper->mail_op;
-       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
+       return NULL;
+}
 
-       if ((status->position == 1) && (status->of_total == 100))
-               return;
+void 
+modest_mail_operation_get_msgs_full (ModestMailOperation *self,
+                                    TnyList *header_list, 
+                                    GetMsgAsynUserCallback user_callback,
+                                    gpointer user_data,
+                                    GDestroyNotify notify)
+{
+       GThread *thread;
+       ModestMailOperationPrivate *priv = NULL;
+       GetFullMsgsInfo *info = NULL;
+       
+       g_return_if_fail (MODEST_IS_MAIL_OPERATION (self));
+       
+       /* Init mail operation */
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
+       priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
+       priv->done = 0;
+       priv->total = tny_list_get_length(header_list);
 
-       if (status->of_total > 0)
-               priv->done += status->position/status->of_total;
+       /* Create the info */
+       info = g_slice_new0 (GetFullMsgsInfo);
+       info->mail_op = self;
+       info->user_callback = user_callback;
+       info->user_data = user_data;
+       info->headers = g_object_ref (header_list);
+       info->notify = notify;
 
-       g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
+       /* Call the thread */
+       thread = g_thread_create (get_msgs_full_thread, info, FALSE, NULL);
 }
 
 
-
 void 
 modest_mail_operation_remove_msg (ModestMailOperation *self,
                                  TnyHeader *header,
index bf10382..77cbb83 100644 (file)
@@ -98,7 +98,7 @@ struct _ModestMailOperationClass {
  * used as tinymail operation callback. The private function fills private 
  * fields of mail operation and calls user defined callback if it exists.
  */
-typedef void (*GetMsgAsynUserCallback) (const GObject *obj, const TnyMsg *msg, gpointer user_data);
+typedef void (*GetMsgAsynUserCallback) (const GObject *obj, TnyMsg *msg, gpointer user_data);
 
 /**
  * XferMsgAsynUserCallback:
@@ -406,7 +406,7 @@ void          modest_mail_operation_get_msg     (ModestMailOperation *self,
                                                 GetMsgAsynUserCallback user_callback,
                                                 gpointer user_data);
 /**
- * modest_mail_operation_process_msg:
+ * modest_mail_operation_get_msgs_full:
  * @self: a #ModestMailOperation
  * @header_list: a #TnyList of #TnyHeader objects to get and process
  * @user_callback: a #TnyGetMsgCallback function to call after tinymail operation execution.
@@ -416,10 +416,11 @@ void          modest_mail_operation_get_msg     (ModestMailOperation *self,
  * pased as argument. This operation is asynchronous, so the
  * #ModestMailOperation should be added to #ModestMailOperationQueue
  **/
-void          modest_mail_operation_process_msg     (ModestMailOperation *self,
+void          modest_mail_operation_get_msgs_full   (ModestMailOperation *self,
                                                     TnyList *headers_list,
                                                     GetMsgAsynUserCallback user_callback,
-                                                    gpointer user_data);
+                                                    gpointer user_data,
+                                                    GDestroyNotify notify);
 
 /* Functions to control mail operations */
 /**
index 5f0bfba..9dfd9ee 100644 (file)
@@ -86,10 +86,9 @@ typedef enum _ReplyForwardAction {
 } ReplyForwardAction;
 
 typedef struct _ReplyForwardHelper {
-guint reply_forward_type;
+       guint reply_forward_type;
        ReplyForwardAction action;
        gchar *account_name;
-       guint pending_ops;
 } ReplyForwardHelper;
 
 typedef struct _HeaderActivatedHelper {
@@ -111,9 +110,9 @@ do_headers_action (ModestWindow *win,
                   gpointer user_data);
 
 
-static void     open_msg_func          (const GObject *obj, const TnyMsg *msg, gpointer user_data);
+static void     open_msg_func          (const GObject *obj, TnyMsg *msg, gpointer user_data);
 
-static void     reply_forward_func     (const GObject *obj, const TnyMsg *msg, gpointer user_data);
+static void     reply_forward_func     (const GObject *obj, TnyMsg *msg, gpointer user_data);
 
 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
 
@@ -513,7 +512,7 @@ modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
 
 
 static void
-open_msg_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
+open_msg_func (const GObject *obj, TnyMsg *msg, gpointer user_data)
 {
        ModestWindowMgr *mgr = NULL;
        ModestWindow *parent_win = NULL;
@@ -573,7 +572,17 @@ open_msg_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
 }
 
 static void
-reply_forward_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
+free_reply_forward_helper (gpointer data)
+{
+       ReplyForwardHelper *helper;
+
+       helper = (ReplyForwardHelper *) data;
+       g_free (helper->account_name);
+       g_slice_free (ReplyForwardHelper, helper);
+}
+
+static void
+reply_forward_func (const GObject *obj, TnyMsg *msg, gpointer user_data)
 {
        TnyMsg *new_msg;
        ReplyForwardHelper *rf_helper;
@@ -589,8 +598,6 @@ reply_forward_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
        g_return_if_fail (user_data != NULL);
        rf_helper = (ReplyForwardHelper *) user_data;
 
-       rf_helper->pending_ops--;
-
        from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
                                                   rf_helper->account_name);
        if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
@@ -647,6 +654,7 @@ reply_forward_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
        }
        
        tny_folder_add_msg (folder, (TnyMsg *) msg, &err);
+       g_object_unref (msg);
        if (err) {
                g_printerr ("modest: error adding msg to Drafts folder: %s",
                            err->message);
@@ -668,13 +676,9 @@ cleanup:
        if (folder)
                g_object_unref (G_OBJECT (folder));
        if (account)
-               g_object_unref (G_OBJECT (account));
-       
-       if (rf_helper->pending_ops == 0) {
-               g_free (rf_helper->account_name);
-               g_slice_free (ReplyForwardHelper, rf_helper);
-       }
+               g_object_unref (G_OBJECT (account));    
 }
+
 /*
  * Common code for the reply and forward actions
  */
@@ -704,7 +708,6 @@ reply_forward (ReplyForwardAction action, ModestWindow *win)
        rf_helper = g_slice_new0 (ReplyForwardHelper);
        rf_helper->reply_forward_type = reply_forward_type;
        rf_helper->action = action;
-       rf_helper->pending_ops = tny_list_get_length (header_list);
        rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
        if (!rf_helper->account_name)
                rf_helper->account_name =
@@ -717,12 +720,16 @@ reply_forward (ReplyForwardAction action, ModestWindow *win)
                        g_printerr ("modest: no message found\n");
                        return;
                } else
-                       reply_forward_func (G_OBJECT(win), msg, rf_helper);
+                       reply_forward_func (G_OBJECT(win), g_object_ref (msg), rf_helper);
        } else {
                                
                mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
                modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
-               modest_mail_operation_process_msg (mail_op, header_list, reply_forward_func, rf_helper);
+               modest_mail_operation_get_msgs_full (mail_op, 
+                                                    header_list, 
+                                                    reply_forward_func, 
+                                                    rf_helper, 
+                                                    free_reply_forward_helper);
 
                /* Clean */
                g_object_unref(mail_op);