Re: Patch: transfer_msg_async update_callback function



On Tue, May 08, 2007 at 08:47:22PM +0200, Javier Fernandez wrote:
> On Tue, May 08, 2007 at 06:50:45PM +0200, Javier Fernandez wrote:
> > On Tue, May 08, 2007 at 06:19:32PM +0200, Javier Fernandez wrote:
> > > Hi all,
> > > 
> > > This is an experimental patch to allow tny_camel_transfer_msgs_async 
> > > function to send back progress information, by calling update_callback 
> > > function.
> > 
> > I added a new status code: 
> >         TNY_FOLDER_STATUS_CODE_XFER_MSGS = 4,
> > 
> 
> Use idl_stopper to prevent calls of update_callback after callback
> execution.
> 

Last patch does not work, sorry.
This is the correct patch.

--
Javier Fernández García-Boente
Ingeniero en Informática                 
mailto:jfernandez igalia com                    
Igalia http://www.igalia.com
Telf. +34 981 91 39 91  
Fax.  +34 981 91 39 49
 
Index: libtinymail-camel/tny-camel-folder.c
===================================================================
--- libtinymail-camel/tny-camel-folder.c	(revision 1922)
+++ libtinymail-camel/tny-camel-folder.c	(working copy)
@@ -1764,6 +1764,8 @@
 	GError *err;
 	TnyFolder *self;
 	TnyTransferMsgsCallback callback;
+	TnyStatusCallback status_callback;
+	TnyIdleStopper *stopper;
 	gpointer user_data;
 	guint depth;
 	TnyList *header_list;
@@ -1774,6 +1776,7 @@
 	gint to_all;
 	gint from_unread;
 	gint to_unread;
+	gboolean cancelled;
 } TransferMsgsInfo;
 
 static void 
@@ -1833,6 +1836,9 @@
 
 	_tny_session_stop_operation (info->session);
 
+	tny_idle_stopper_destroy (info->stopper);
+	info->stopper = NULL;
+
 	g_slice_free (TransferMsgsInfo, info);
 
 	return;
@@ -1844,8 +1850,13 @@
 	TransferMsgsInfo *info = thr_user_data;
 
 	if (info->callback)
-		info->callback (info->self, &info->err, info->user_data);
+		info->callback (info->self, info->cancelled, &info->err, info->user_data);
 
+	/* Prevent status callbacks from being called after this
+	 * (can happen because the 2 idle callbacks have different priorities)
+	 * by causing tny_idle_stopper_is_stopped() to return TRUE. */
+	tny_idle_stopper_stop (info->stopper);
+
 	return FALSE;
 }
 
@@ -1951,16 +1962,41 @@
 	return;
 }
 
+static void
+tny_camel_folder_transfer_msgs_async_status (struct _CamelOperation *op, const char *what, int sofar, int oftotal, void *thr_user_data)
+{
+	TransferMsgsInfo *oinfo = thr_user_data;
+	TnyProgressInfo *info = NULL;
+
+	info = tny_progress_info_new (G_OBJECT (oinfo->self), oinfo->status_callback, 
+		TNY_FOLDER_STATUS, TNY_FOLDER_STATUS_CODE_XFER_MSGS, what, sofar, 
+		oftotal, oinfo->stopper, oinfo->user_data);
+
+	if (oinfo->depth > 0)
+	{
+		g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+			tny_progress_info_idle_func, info, 
+			tny_progress_info_destroy);
+	} else {
+		tny_progress_info_idle_func (info);
+		tny_progress_info_destroy (info);
+	}
+
+	return;
+}
+
 static gpointer 
 tny_camel_folder_transfer_msgs_async_thread (gpointer thr_user_data)
 {
 	TransferMsgsInfo *info = (TransferMsgsInfo*) thr_user_data;
-	TnyCamelFolderPriv *priv_src, *priv_dst;
+	TnyCamelFolderPriv *priv_src = NULL, *priv_dst = NULL;
+	TnyCamelAccountPriv *apriv = NULL;
 	GError *err = NULL;
 
 	priv_src = TNY_CAMEL_FOLDER_GET_PRIVATE (info->self);
 	priv_dst = TNY_CAMEL_FOLDER_GET_PRIVATE (info->folder_dst);
 
+
 	if (!priv_src->folder || !priv_src->loaded || !CAMEL_IS_FOLDER (priv_src->folder))
 		if (!load_folder_no_lock (priv_src)) 
 			return NULL;
@@ -1969,19 +2005,34 @@
 		if (!load_folder_no_lock (priv_dst)) 
 			return NULL;
 
+	info->cancelled = FALSE;
+	apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (priv_src->account);
+	
+	/* Start operation */
+	_tny_camel_account_start_camel_operation (TNY_CAMEL_ACCOUNT (priv_src->account), 
+		tny_camel_folder_transfer_msgs_async_status, info, 
+		"Transfer messages between two folders");
+
 	transfer_msgs_thread_clean (info->self, info->header_list, info->folder_dst, 
 			info->delete_originals, &err);
 
+	/* Check cancelation and stop operation */
+	info->cancelled = camel_operation_cancel_check (apriv->cancel);
+	_tny_camel_account_stop_camel_operation (TNY_CAMEL_ACCOUNT (priv_src->account));
+
+	/* Get data */
 	info->from_all = camel_folder_get_message_count (priv_src->folder);
 	info->to_all = camel_folder_get_message_count (priv_dst->folder);
 	info->from_unread = camel_folder_get_unread_message_count (priv_src->folder);
 	info->to_unread = camel_folder_get_unread_message_count (priv_dst->folder);
 
+	/* Check errors */
 	if (err != NULL)
 		info->err = g_error_copy ((const GError *) err);
 	else
 		info->err = NULL;
 
+	/* Call callback function, if it exists */
 	if (info->callback)
 	{
 		if (info->depth > 0)
@@ -1994,7 +2045,7 @@
 			tny_camel_folder_transfer_msgs_async_destroyer (info);
 		}
 	} else { 
-		/* thread reference (TNY TODO: inform observer?) */
+		/* Thread reference */
 		_tny_camel_folder_unreason (priv_src);
 		g_object_unref (G_OBJECT (info->self));
 		g_object_unref (G_OBJECT (info->header_list));
@@ -2028,21 +2079,29 @@
 			TNY_FOLDER_ERROR, TNY_FOLDER_ERROR_TRANSFER_MSGS))
 	{
 		if (callback)
-			callback (self, &err, user_data);
+			callback (self, TRUE, &err, user_data);
 		g_error_free (err);
 		return;
 	}
 
 	info = g_slice_new (TransferMsgsInfo);
+	info->cancelled = FALSE;
 	info->session = TNY_FOLDER_PRIV_GET_SESSION (priv);
 	info->self = self;
 	info->header_list = header_list; 
 	info->folder_dst = folder_dst;
 	info->callback = callback;
+	info->status_callback = status_callback;
 	info->user_data = user_data;
 	info->delete_originals = delete_originals;
 	info->depth = g_main_depth ();
 
+	/* Use a ref count because we do not know which of the 2 idle callbacks 
+	 * will be the last, and we can only unref self in the last callback:
+	 * This is destroyed in the idle GDestroyNotify callback. */
+
+	info->stopper = tny_idle_stopper_new();
+
 	/* thread reference */
 	g_object_ref (G_OBJECT (info->header_list));
 	_tny_camel_folder_reason (priv_src);
Index: libtinymail/tny-status.h
===================================================================
--- libtinymail/tny-status.h	(revision 1922)
+++ libtinymail/tny-status.h	(working copy)
@@ -43,6 +43,7 @@
 	TNY_FOLDER_STATUS_CODE_REFRESH = 1,
 	TNY_FOLDER_STATUS_CODE_GET_MSG = 2,
 	TNY_GET_MSG_QUEUE_STATUS_GET_MSG = 3,
+	TNY_FOLDER_STATUS_CODE_XFER_MSGS = 4,
 };
 
 struct _TnyStatus 
Index: libtinymail/tny-shared.h
===================================================================
--- libtinymail/tny-shared.h	(revision 1922)
+++ libtinymail/tny-shared.h	(working copy)
@@ -54,7 +54,7 @@
 typedef void (*TnyForgetPassFunc) (TnyAccount *self);
 typedef void (*TnyRefreshFolderCallback) (TnyFolder *self, gboolean cancelled, GError **err, gpointer user_data);
 typedef void (*TnyGetMsgCallback) (TnyFolder *folder, gboolean cancelled, TnyMsg *msg, GError **err, gpointer user_data);
-typedef void (*TnyTransferMsgsCallback) (TnyFolder *folder, GError **err, gpointer user_data);
+typedef void (*TnyTransferMsgsCallback) (TnyFolder *folder, gboolean cancelled, GError **err, gpointer user_data);
 typedef void (*TnyStatusCallback) (GObject *self, TnyStatus *status, gpointer user_data);
 typedef enum _TnyHeaderFlags TnyHeaderFlags;
 typedef enum _TnyHeaderPriorityFlags TnyHeaderPriorityFlags;
Index: libtinymail/tny-merge-folder.c
===================================================================
--- libtinymail/tny-merge-folder.c	(revision 1922)
+++ libtinymail/tny-merge-folder.c	(working copy)
@@ -691,8 +691,8 @@
 {
 	TransferMsgsInfo *info = thr_user_data;
 
-	if (info->callback)
-		info->callback (info->self, &info->err, info->user_data);
+	if (info->callback) /* TODO: the cancelled field */
+		info->callback (info->self, FALSE, &info->err, info->user_data);
 
 	return FALSE;
 }


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