* Added asynchronous account update
authorSergio Villar Senin <svillar@igalia.com>
Mon, 14 May 2007 16:47:41 +0000 (16:47 +0000)
committerSergio Villar Senin <svillar@igalia.com>
Mon, 14 May 2007 16:47:41 +0000 (16:47 +0000)
* Replaced GtkTreeIter's by row references when the header is activated

pmo-trunk-r1859

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

index d8c84b4..c7a0bc6 100644 (file)
@@ -320,7 +320,7 @@ ModestWindow*
 modest_msg_view_window_new_with_header_model (TnyMsg *msg, 
                                              const gchar *account, 
                                              GtkTreeModel *model, 
-                                             GtkTreeIter iter)
+                                             GtkTreeRowReference *row_reference)
 {
        /* Currently we simply redirect to new constructor. It should store a
           reference to the header list model, to enable next/prev message
index f390ed0..4eb7754 100644 (file)
@@ -145,7 +145,7 @@ struct _ModestMsgViewWindowPrivate {
        gboolean optimized_view;
 
        GtkTreeModel *header_model;
-       GtkTreeIter   iter;
+       GtkTreeRowReference *row_reference;
 
        guint clipboard_change_handler;
        guint queue_change_handler;
@@ -436,6 +436,11 @@ modest_msg_view_window_finalize (GObject *obj)
                priv->progress_bar_timeout = 0;
        }
 
+       if (priv->row_reference) {
+               gtk_tree_row_reference_free (priv->row_reference);
+               priv->row_reference = NULL;
+       }
+
        G_OBJECT_CLASS(parent_class)->finalize (obj);
 }
 
@@ -450,7 +455,7 @@ on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgViewWindow *self)
 
 ModestWindow *
 modest_msg_view_window_new_with_header_model (TnyMsg *msg, const gchar *account_name,
-                                             GtkTreeModel *model, GtkTreeIter iter)
+                                             GtkTreeModel *model, GtkTreeRowReference *row_reference)
 {
        ModestMsgViewWindow *window = NULL;
        ModestMsgViewWindowPrivate *priv = NULL;
@@ -462,7 +467,7 @@ modest_msg_view_window_new_with_header_model (TnyMsg *msg, const gchar *account_
 
        g_object_ref (model);
        priv->header_model = model;
-       priv->iter = iter;
+       priv->row_reference = gtk_tree_row_reference_copy (row_reference);
 
        modest_msg_view_window_update_priority (window);
 
@@ -808,7 +813,7 @@ modest_msg_view_window_is_last_message (ModestMsgViewWindow *window)
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
 
        if (priv->header_model) {
-               path = gtk_tree_model_get_path (priv->header_model, &priv->iter);
+               path = gtk_tree_row_reference_get_path (priv->row_reference);
                if (!path)
                        return TRUE;
                while (!has_next) {
@@ -824,7 +829,6 @@ modest_msg_view_window_is_last_message (ModestMsgViewWindow *window)
                        }
                        
                }
-               gtk_tree_path_free (path);
                return !has_next;
        } else {
                return TRUE;
@@ -845,7 +849,7 @@ modest_msg_view_window_is_first_message (ModestMsgViewWindow *window)
 
        if (priv->header_model) {
                gchar * path_string;
-               path = gtk_tree_model_get_path (priv->header_model, &priv->iter);
+               path = gtk_tree_row_reference_get_path (priv->row_reference);
                if (!path)
                        return TRUE;
 
@@ -878,7 +882,6 @@ modest_msg_view_window_is_first_message (ModestMsgViewWindow *window)
                        }
                        g_free (path_string);
                }
-               gtk_tree_path_free (path);
                return result;
        } else {
                return TRUE;
@@ -898,19 +901,26 @@ modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
        priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
 
        if (priv->header_model) {
-               tmp_iter = priv->iter;
+               gtk_tree_model_get_iter (priv->header_model,
+                                        &tmp_iter,
+                                        gtk_tree_row_reference_get_path (priv->row_reference));
                while (gtk_tree_model_iter_next (priv->header_model, &tmp_iter)) {
                        TnyHeader *header;
-                       guint op_status;
+                       GtkTreePath *path;
 
-                       priv->iter = tmp_iter;
-                       gtk_tree_model_get (priv->header_model, &(priv->iter), TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
+                       gtk_tree_model_get (priv->header_model, &tmp_iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
                                            &header, -1);
                        if (!header)
                                break;
                        if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED)
                                continue;
 
+                       /* Update the row reference */
+                       gtk_tree_row_reference_free (priv->row_reference);
+                       path = gtk_tree_model_get_path (priv->header_model, &tmp_iter);
+                       priv->row_reference = gtk_tree_row_reference_new (priv->header_model, path);
+                       gtk_tree_path_free (path);
+
                        /* Mark as read */
                        flags = tny_header_get_flags (header);
                        if (!(flags & TNY_HEADER_FLAG_SEEN))
@@ -920,20 +930,12 @@ modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
                        mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(window));
                        modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
                        modest_mail_operation_get_msg (mail_op, header, view_msg_cb, NULL);
-                       op_status = modest_mail_operation_get_status (mail_op);
-
                        g_object_unref (mail_op);
 
-                       if (op_status == MODEST_MAIL_OPERATION_STATUS_FAILED) 
-                               return FALSE;
-                       else 
-                               return TRUE;
+                       return TRUE;
                }
-
-               return FALSE;
-       } else {
-               return FALSE;
        }
+       return FALSE;           
 }
 
 gboolean        
@@ -949,18 +951,22 @@ modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
        if (priv->header_model) {
                GtkTreePath *path;
 
-               path = gtk_tree_model_get_path (priv->header_model, &(priv->iter));
+               path = gtk_tree_row_reference_get_path (priv->row_reference);
                while (gtk_tree_path_prev (path)) {
                        TnyHeader *header;
-                       guint op_status;
+                       GtkTreeIter iter;
 
-                       gtk_tree_model_get_iter (priv->header_model, &(priv->iter), path);
-                       gtk_tree_model_get (priv->header_model, &(priv->iter), TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
+                       gtk_tree_model_get_iter (priv->header_model, &iter, path);
+                       gtk_tree_model_get (priv->header_model, &iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
                                            &header, -1);
                        if (!header)
                                break;
                        if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED)
                                continue;
+
+                       /* Update the row reference */
+                       gtk_tree_row_reference_free (priv->row_reference);
+                       priv->row_reference = gtk_tree_row_reference_new (priv->header_model, path);
                        
                        /* Mark as read */
                        flags = tny_header_get_flags (header);
@@ -970,18 +976,10 @@ modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
                        /* New mail operation */
                        mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(window));
                        modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
-                       modest_mail_operation_get_msg (mail_op, header, view_msg_cb, NULL);
-                       
-                       gtk_tree_path_free (path);
+                       modest_mail_operation_get_msg (mail_op, header, view_msg_cb, NULL);             
 
-                       op_status = modest_mail_operation_get_status (mail_op);
-                       if (op_status == MODEST_MAIL_OPERATION_STATUS_FAILED) 
-                               return FALSE;
-                       else 
-                               return TRUE;
+                       return TRUE;
                }
-       } else {
-               return FALSE;
        }
 
        return FALSE;
@@ -1121,8 +1119,13 @@ modest_msg_view_window_update_priority (ModestMsgViewWindow *window)
 
        if (priv->header_model) {
                TnyHeader *header;
+               GtkTreeIter iter;
+
+               gtk_tree_model_get_iter (priv->header_model, 
+                                        &iter, 
+                                        gtk_tree_row_reference_get_path (priv->row_reference));
 
-               gtk_tree_model_get (priv->header_model, &(priv->iter), TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
+               gtk_tree_model_get (priv->header_model, &iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
                                    &header, -1);
                flags = tny_header_get_flags (header);
        }
index 5ae5707..ce8808e 100644 (file)
@@ -194,9 +194,9 @@ modest_mail_operation_queue_remove (ModestMailOperationQueue *self,
        g_queue_remove (priv->op_queue, mail_op);
        g_mutex_unlock (priv->queue_lock);
 
-       /* HACK see the documentation of the function. Remove this
-          call when tinymail provides accurate progress values */
-       _modest_mail_operation_notify_end (mail_op);
+/*     /\* HACK see the documentation of the function. Remove this */
+/*        call when tinymail provides accurate progress values *\/ */
+/*     _modest_mail_operation_notify_end (mail_op); */
 
        /* Notify observers */
        g_signal_emit (self, signals[QUEUE_CHANGED_SIGNAL], 0,
index 96403f3..ed98947 100644 (file)
@@ -56,14 +56,6 @@ 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_folders_cb    (TnyFolderStore *self, 
-                                     TnyList *list, 
-                                     GError **err, 
-                                     gpointer user_data);
-static void     update_folders_status_cb (GObject *obj,
-                                         TnyStatus *status,  
-                                         gpointer user_data);
-
 static void     update_process_msg_status_cb (GObject *obj,
                                              TnyStatus *status,  
                                              gpointer user_data);
@@ -399,6 +391,13 @@ cleanup:
                g_object_unref (G_OBJECT(folder));
 }
 
+typedef struct 
+{
+       ModestMailOperation *mail_op;
+       TnyStoreAccount *account;
+       gpointer user_data;
+} UpdateAccountInfo;
+
 static void
 recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all_folders)
 {
@@ -413,9 +412,7 @@ recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all
                TnyFolderStore *folder = (TnyFolderStore*) tny_iterator_get_current (iter);
 
                tny_list_prepend (all_folders, G_OBJECT (folder));
-
-               recurse_folders (folder, query, all_folders);
-           
+               recurse_folders (folder, query, all_folders);    
                g_object_unref (G_OBJECT (folder));
 
                tny_iterator_next (iter);
@@ -424,131 +421,144 @@ recurse_folders (TnyFolderStore *store, TnyFolderStoreQuery *query, TnyList *all
         g_object_unref (G_OBJECT (folders));
 }
 
-static void
-update_folders_status_cb (GObject *obj,
-                         TnyStatus *status,  
-                         gpointer user_data)
+/* 
+ * Used by update_account_thread to emit the signal from the main
+ * loop. We call it inside an idle call to achieve that 
+ */
+static gboolean
+notify_update_account_observers (gpointer data)
 {
-       ModestMailOperation *self;
-       ModestMailOperationPrivate *priv;
+       ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
 
-       g_return_if_fail (status != NULL);
-       g_return_if_fail (status->code == TNY_FOLDER_STATUS_CODE_REFRESH);
+       g_signal_emit (G_OBJECT (mail_op), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
+       g_object_unref (mail_op);
 
-       /* Temporary FIX: useful when tinymail send us status
-          information *after* calling the function callback */
-       if (!MODEST_IS_MAIL_OPERATION (user_data))
-               return;
-
-       self = MODEST_MAIL_OPERATION (user_data);
-       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
+       return FALSE;
+}
 
-       if ((status->position == 1) && (status->of_total == 100))
-               return;
+/* 
+ * Used by update_account_thread to notify the queue from the main
+ * loop. We call it inside an idle call to achieve that
+ */
+static gboolean
+notify_update_account_queue (gpointer data)
+{
+       ModestMailOperation *mail_op = MODEST_MAIL_OPERATION (data);
 
-       priv->done = status->position;
-       priv->total = status->of_total;
+       modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), 
+                                           mail_op);
+       g_object_unref (mail_op);
 
-       g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
+       return FALSE;
 }
 
-static void
-update_folders_cb (TnyFolderStore *folder_store, TnyList *list, GError **err, gpointer user_data)
+static gpointer
+update_account_thread (gpointer thr_user_data)
 {
-       ModestMailOperation *self;
+       UpdateAccountInfo *info;
+       TnyList *all_folders = NULL;
+       TnyIterator *iter = NULL;
+       TnyFolderStoreQuery *query = NULL;
        ModestMailOperationPrivate *priv;
-       TnyIterator *iter;
-       TnyList *all_folders;
-       
-       self  = MODEST_MAIL_OPERATION (user_data);
-       priv  = MODEST_MAIL_OPERATION_GET_PRIVATE (self);
 
-       /* g_message (__FUNCTION__); */
-       
-       if (*err) {
-               priv->error = g_error_copy (*err);
+       info = (UpdateAccountInfo *) thr_user_data;
+       priv = MODEST_MAIL_OPERATION_GET_PRIVATE(info->mail_op);
+
+       /* Get all the folders We can do it synchronously because
+          we're already running in a different thread than the UI */
+       all_folders = tny_simple_list_new ();
+       query = tny_folder_store_query_new ();
+       tny_folder_store_query_add_item (query, NULL, TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
+       tny_folder_store_get_folders (TNY_FOLDER_STORE (info->account),
+                                     all_folders,
+                                     query,
+                                     &(priv->error));
+       if (priv->error) {
                priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
                goto out;
        }
 
-       /* Get all the folders We can do it synchronously because
-          we're already running in a different thread than the UI */
-       all_folders = tny_list_copy (list);
        iter = tny_list_create_iterator (all_folders);
        while (!tny_iterator_is_done (iter)) {
                TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
 
-               recurse_folders (folder, NULL, all_folders);
+               recurse_folders (folder, query, all_folders);
                tny_iterator_next (iter);
        }
        g_object_unref (G_OBJECT (iter));
 
-       /* Refresh folders */
-       iter = tny_list_create_iterator (all_folders);
        priv->total = tny_list_get_length (all_folders);
+       priv->done = 0;
 
+       /* Refresh folders */
+       iter = tny_list_create_iterator (all_folders);
        while (!tny_iterator_is_done (iter) && !priv->error) {
 
                TnyFolderStore *folder = TNY_FOLDER_STORE (tny_iterator_get_current (iter));
 
                /* Refresh the folder */
                tny_folder_refresh (TNY_FOLDER (folder), &(priv->error));
+               priv->done++;
 
                if (priv->error) {
                        priv->status = MODEST_MAIL_OPERATION_STATUS_FAILED;
-               } else {        
-                       /* Update status and notify */
+               } else {
+                       /* Update status and notify. We need to call
+                          the notification with an idle in order to
+                          call it from the main loop. We need that in
+                          order not to get into trouble with Gtk+ */
                        priv->done++;
-                       g_signal_emit (G_OBJECT (self), signals[PROGRESS_CHANGED_SIGNAL], 0, NULL);
+                       g_idle_add (notify_update_account_observers, g_object_ref (info->mail_op));
                }
-    
+
                g_object_unref (G_OBJECT (folder));
-           
                tny_iterator_next (iter);
        }
-
        g_object_unref (G_OBJECT (iter));
- out:
-       g_object_unref (G_OBJECT (list));
 
        /* Check if the operation was a success */
        if (priv->done == priv->total && !priv->error)
                priv->status = MODEST_MAIL_OPERATION_STATUS_SUCCESS;
 
-       /* Free */
-       g_object_unref (G_OBJECT (folder_store));
-
+ out:
        /* Notify the queue */
-       modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), self);
+       g_idle_add (notify_update_account_queue, g_object_ref (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_slice_free (UpdateAccountInfo, info);
+
+       return NULL;
 }
 
 gboolean
 modest_mail_operation_update_account (ModestMailOperation *self,
                                      TnyStoreAccount *store_account)
 {
+       GThread *thread;
+       UpdateAccountInfo *info;
        ModestMailOperationPrivate *priv;
-       TnyList *folders;
 
        g_return_val_if_fail (MODEST_IS_MAIL_OPERATION (self), FALSE);
        g_return_val_if_fail (TNY_IS_STORE_ACCOUNT(store_account), FALSE);
 
-       /* Pick async call reference */
-       g_object_ref (store_account);
-
+       /* Init mail operation */
        priv = MODEST_MAIL_OPERATION_GET_PRIVATE(self);
-
        priv->total = 0;
        priv->done  = 0;
        priv->status = MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS;
        
-       /* Get subscribed folders & refresh them */
-       folders = TNY_LIST (tny_simple_list_new ());
+       /* Create the helper object */
+       info = g_slice_new (UpdateAccountInfo);
+       info->mail_op = g_object_ref (self);
+       info->account = g_object_ref (store_account);
+       info->user_data = NULL;
+
+       thread = g_thread_create (update_account_thread, info, FALSE, NULL);
 
-       /* g_message ("tny_folder_store_get_folders_async"); */
-       tny_folder_store_get_folders_async (TNY_FOLDER_STORE (store_account),
-                                           folders, update_folders_cb, NULL, 
-                                           update_folders_status_cb, self);
-       
        return TRUE;
 }
 
index da776d5..2a55307 100644 (file)
@@ -93,7 +93,7 @@ guint reply_forward_type;
 
 typedef struct _HeaderActivatedHelper {
        GtkTreeModel *model;
-       GtkTreeIter iter;
+       GtkTreeRowReference *row_reference;
        TnyFolder *folder;
 } HeaderActivatedHelper;
 
@@ -470,7 +470,7 @@ open_msg_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
                break;
        default:
                if (helper->model != NULL)
-                       win = modest_msg_view_window_new_with_header_model ((TnyMsg *) msg, account, helper->model, helper->iter);
+                       win = modest_msg_view_window_new_with_header_model ((TnyMsg *) msg, account, helper->model, helper->row_reference);
                else
                        win = modest_msg_view_window_new ((TnyMsg *) msg, account);
        }
@@ -487,6 +487,7 @@ open_msg_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
        g_free(account);
 /*     g_object_unref (G_OBJECT(msg)); */
        g_object_unref (G_OBJECT(helper->folder));
+       gtk_tree_row_reference_free (helper->row_reference);
        g_slice_free (HeaderActivatedHelper, helper);
 }
 
@@ -992,11 +993,10 @@ modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
        sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
        sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
        if (sel_list != NULL) {
-               gtk_tree_model_get_iter (model, &iter, (GtkTreePath *) sel_list->data);
                
                /* Fill helpers */
                helper->model = model;
-               helper->iter = iter;
+               helper->row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
 
                /* Mark as read */
                for (tmp=sel_list; tmp; tmp=g_list_next(tmp)) {
index 90b578f..e74482b 100644 (file)
@@ -91,7 +91,10 @@ ModestWindow*   modest_msg_view_window_new         (TnyMsg *msg, const gchar *ac
  *
  * Returns: a new #ModestMsgViewWindow, or NULL in case of error
  */
-ModestWindow*   modest_msg_view_window_new_with_header_model (TnyMsg *msg, const gchar *account, GtkTreeModel *model, GtkTreeIter iter);
+ModestWindow*   modest_msg_view_window_new_with_header_model (TnyMsg *msg, 
+                                                             const gchar *account, 
+                                                             GtkTreeModel *model, 
+                                                             GtkTreeRowReference *row_reference);
 
 
 /**