Experimental patch to implement sent and sending signal on tny-camel-send-queue



This patch implements two new signals to detect when a message is being 
processed into send queue and when its finally sent.


-- 
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-send-queue.c
===================================================================
--- libtinymail-camel/tny-camel-send-queue.c	(revision 2224)
+++ libtinymail-camel/tny-camel-send-queue.c	(working copy)
@@ -28,6 +28,8 @@
 #include <tny-folder.h>
 #include <tny-error.h>
 
+
+#include <tny-folder-observer.h>
 #include <tny-camel-folder.h>
 #include <tny-transport-account.h>
 
@@ -53,6 +55,14 @@
 	gint i, total;
 } ErrorInfo;
 
+typedef struct {
+	TnySendQueue *self;
+	TnyMsg *msg;
+	TnyHeader *header;
+	gint i, total;
+	guint signal_id;
+} ControlInfo;
+
 static gboolean 
 emit_error_on_mainloop (gpointer data)
 {
@@ -62,6 +72,15 @@
 	return FALSE;
 }
 
+static gboolean 
+emit_control_signals_on_mainloop (gpointer data)
+{
+	ControlInfo *info = data;
+	g_signal_emit (info->self, tny_send_queue_signals [info->signal_id], 
+				0, info->header, info->msg, info->i, info->total);
+	return FALSE;
+}
+
 static void
 destroy_error_info (gpointer data)
 {
@@ -78,6 +97,20 @@
 }
 
 static void
+destroy_control_info (gpointer data)
+{
+	ControlInfo *info = data;
+
+	if (info->msg)
+		g_object_unref (G_OBJECT (info->msg));
+	if (info->header)
+		g_object_unref (G_OBJECT (info->header));
+	if (info->self)
+		g_object_unref (G_OBJECT (info->self));
+
+	g_slice_free (ControlInfo, info);
+}
+
 emit_error (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *error, int i, int total)
 {
 	ErrorInfo *info = g_slice_new0 (ErrorInfo);
@@ -100,6 +133,28 @@
 	return;
 }
 
+static void
+emit_control (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, guint signal_id, int i, int total)
+{
+	ControlInfo *info = g_slice_new0 (ControlInfo);
+
+	if (self)
+		info->self = TNY_SEND_QUEUE (g_object_ref (G_OBJECT (self)));
+	if (msg)
+		info->msg = TNY_MSG (g_object_ref (G_OBJECT (msg)));
+	if (header)
+		info->header = TNY_HEADER (g_object_ref (G_OBJECT (header)));
+
+	info->signal_id = signal_id;
+	info->i = i;
+	info->total = total;
+
+	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+		emit_control_signals_on_mainloop, info, destroy_control_info);
+
+	return;
+}
+
 static gpointer
 thread_main (gpointer data)
 {
@@ -131,8 +186,9 @@
 			goto errorhandler;
 		}
 
+		/* I dont expect total is being changed  */
 		length = tny_list_get_length (list);
-		priv->total = length;
+/* 		priv->total = length; */
 	}
 	g_mutex_unlock (priv->todo_lock);
 
@@ -165,10 +221,10 @@
 				goto errorhandler;
 			}
 
+			/* I dont expect total is being changed  */
 			length = tny_list_get_length (headers);
+/* 			priv->total = length; */
 
-			priv->total = length;
-
 			if (length <= 0)
 			{
 				g_object_unref (G_OBJECT (headers));
@@ -185,7 +241,6 @@
 		}
 		g_mutex_unlock (priv->todo_lock);
 
-
 		if (header && TNY_IS_HEADER (header))
 		{
 			TnyList *hassent = tny_simple_list_new ();
@@ -194,6 +249,9 @@
 			tny_list_prepend (hassent, G_OBJECT (header));
 			msg = tny_folder_get_msg (outbox, header, &err);
 
+			/* Emits msg-sending signal to inform a new msg is being sent */
+			emit_control (self, header, msg, TNY_SEND_QUEUE_MSG_SENDING, i, priv->total);
+		
 			/* hassent is owner now */
 			g_object_unref (G_OBJECT (header)); 
 
@@ -222,9 +280,13 @@
 						priv->do_continue = FALSE;
 						g_error_free (newerr);
 					}
-					priv->total--;
+/* 					priv->total--; */
 				}
 			}
+
+			/* Emits msg-sent signal to inform msg has been sent */
+			emit_control (self, header, msg, TNY_SEND_QUEUE_MSG_SENT, i, priv->total);
+
 			g_mutex_unlock (priv->todo_lock);
 
 			g_object_unref (G_OBJECT (hassent));
@@ -352,61 +414,128 @@
 static void
 tny_camel_send_queue_add_default (TnySendQueue *self, TnyMsg *msg, GError **err)
 {
-	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self);
+	TnyFolder *outbox = tny_send_queue_get_outbox (self);
 
 	g_assert (TNY_IS_CAMEL_MSG (msg));
 
-	g_mutex_lock (priv->todo_lock);
-	{
-		TnyFolder *outbox;
-		TnyList *headers = tny_simple_list_new ();
+	if (!outbox || !TNY_IS_FOLDER (outbox)) {
+		g_set_error (err, TNY_SEND_QUEUE_ERROR,
+			     TNY_SEND_QUEUE_ERROR_ADD,
+			     "Operating can't continue: send queue not ready "
+			     "because it does not have a valid outbox. "
+			     "This problem indicates a bug in the software.");
+		return;
+	}
 
-		outbox = tny_send_queue_get_outbox (self);
+	tny_folder_add_msg (outbox, msg, err);
 
-		if (!outbox || !TNY_IS_FOLDER (outbox))
-		{
-			g_set_error (err, TNY_SEND_QUEUE_ERROR, 
-				TNY_SEND_QUEUE_ERROR_ADD,
-				"Operating can't continue: send queue not ready "
-				"because it does not have a valid outbox. "
-				"This problem indicates a bug in the software.");
-			g_object_unref (headers);
-			g_mutex_unlock (priv->todo_lock);
-			return;
-		}
+	g_object_unref (outbox);
+	return;
+}
 
-		tny_folder_get_headers (outbox, headers, TRUE, err);
+/* static void */
+/* tny_camel_send_queue_add_default (TnySendQueue *self, TnyMsg *msg, GError **err) */
+/* { */
+/* 	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self); */
 
-		if (err!= NULL && *err != NULL)
-		{
-			g_object_unref (G_OBJECT (headers));
-			g_object_unref (G_OBJECT (outbox));
-			g_mutex_unlock (priv->todo_lock);
-			return;
-		}
+/* 	g_assert (TNY_IS_CAMEL_MSG (msg)); */
 
-		priv->total = tny_list_get_length (headers);
-		g_object_unref (G_OBJECT (headers));
+/* 	g_mutex_lock (priv->todo_lock); */
+/* 	{ */
+/* 		TnyFolder *outbox; */
+/* 		TnyList *headers = tny_simple_list_new (); */
 
-		tny_folder_add_msg (outbox, msg, err);
+/* 		outbox = tny_send_queue_get_outbox (self); */
 
-		if (err!= NULL && *err != NULL)
-		{
-			g_object_unref (G_OBJECT (outbox));
-			g_mutex_unlock (priv->todo_lock);
-			return;
-		}
+/* 		if (!outbox || !TNY_IS_FOLDER (outbox)) */
+/* 		{ */
+/* 			g_set_error (err, TNY_SEND_QUEUE_ERROR,  */
+/* 				TNY_SEND_QUEUE_ERROR_ADD, */
+/* 				"Operating can't continue: send queue not ready " */
+/* 				"because it does not have a valid outbox. " */
+/* 				"This problem indicates a bug in the software."); */
+/* 			g_object_unref (headers); */
+/* 			g_mutex_unlock (priv->todo_lock); */
+/* 			return; */
+/* 		} */
 
-		priv->total++;
+/* 		tny_folder_get_headers (outbox, headers, TRUE, err); */
 
+/* 		if (err!= NULL && *err != NULL) */
+/* 		{ */
+/* 			g_object_unref (G_OBJECT (headers)); */
+/* 			g_object_unref (G_OBJECT (outbox)); */
+/* 			g_mutex_unlock (priv->todo_lock); */
+/* 			return; */
+/* 		} */
+
+/* 		priv->total = tny_list_get_length (headers); */
+/* 		g_object_unref (G_OBJECT (headers)); */
+
+/* 		tny_folder_add_msg (outbox, msg, err); */
+
+/* 		if (err!= NULL && *err != NULL) */
+/* 		{ */
+/* 			g_object_unref (G_OBJECT (outbox)); */
+/* 			g_mutex_unlock (priv->todo_lock); */
+/* 			return; */
+/* 		} */
+
+/* 		priv->total++; */
+
+/* 		if (priv->total >= 1 && !priv->thread && !priv->creating_spin) */
+/* 			create_worker (self); */
+
+/* 		g_object_unref (G_OBJECT (outbox)); */
+/* 	} */
+
+/* 	g_mutex_unlock (priv->todo_lock); */
+
+/* 	return; */
+/* } */
+
+static void
+tny_camel_send_queue_update (TnyFolderObserver *self, TnyFolderChange *change)
+{
+	TNY_CAMEL_SEND_QUEUE_GET_CLASS (self)->update_func (self, change);
+	return;
+}
+
+static void
+tny_camel_send_queue_update_default (TnyFolderObserver *self, TnyFolderChange *change)
+{
+	TnyCamelSendQueuePriv *priv = TNY_CAMEL_SEND_QUEUE_GET_PRIVATE (self);
+	TnyFolder *outbox;
+	TnyFolderChangeChanged changed;
+	ErrorInfo *info;
+	TnyList *headers; 
+	gint i = 0;
+
+	g_mutex_lock (priv->todo_lock);
+
+	changed = tny_folder_change_get_changed (change);
+
+	if (changed & TNY_FOLDER_CHANGE_CHANGED_ADDED_HEADERS) {
+		outbox = tny_send_queue_get_outbox (TNY_SEND_QUEUE (self));
+
+		/* The added headers */
+		headers = tny_simple_list_new ();
+		tny_folder_change_get_added_headers (change, headers);
+
+		priv->total = tny_list_get_length (headers);
+		g_object_unref (G_OBJECT (headers));
+
 		if (priv->total >= 1 && !priv->thread && !priv->creating_spin)
-			create_worker (self);
+			create_worker (TNY_SEND_QUEUE(self));
 
 		g_object_unref (G_OBJECT (outbox));
 	}
+
 	g_mutex_unlock (priv->todo_lock);
-
+	
 	return;
+	
+	
 }
 
 
@@ -684,9 +813,9 @@
 	class->get_outbox_func = tny_camel_send_queue_get_outbox_default;
 	class->get_sentbox_func = tny_camel_send_queue_get_sentbox_default;
 	class->cancel_func = tny_camel_send_queue_cancel_default;
+	class->update_func = tny_camel_send_queue_update_default;
 
 	object_class->finalize = tny_camel_send_queue_finalize;
-
 	g_type_class_add_private (object_class, sizeof (TnyCamelSendQueuePriv));
 
 	return;
@@ -710,6 +839,12 @@
 	return;
 }
 
+static void
+tny_folder_observer_init (TnyFolderObserverIface *klass)
+{
+	klass->update_func = tny_camel_send_queue_update;
+}
+
 /**
  * tny_camel_send_queue_get_type:
  *
@@ -754,6 +889,13 @@
 		  NULL          /* interface_data */
 		};
 
+		static const GInterfaceInfo tny_folder_observer_info = {
+			(GInterfaceInitFunc) tny_folder_observer_init,
+			NULL,
+			NULL
+		};
+
+
 		type = g_type_register_static (G_TYPE_OBJECT,
 			"TnyCamelSendQueue",
 			&info, 0);
@@ -761,6 +903,9 @@
 		g_type_add_interface_static (type, TNY_TYPE_SEND_QUEUE,
 			&tny_send_queue_info);
 
+
+		g_type_add_interface_static (type, TNY_TYPE_FOLDER_OBSERVER,
+			&tny_folder_observer_info);
 	}
 
 	return type;
Index: libtinymail-camel/tny-camel-send-queue.h
===================================================================
--- libtinymail-camel/tny-camel-send-queue.h	(revision 2224)
+++ libtinymail-camel/tny-camel-send-queue.h	(working copy)
@@ -53,6 +53,7 @@
 	TnyFolder* (*get_sentbox_func) (TnySendQueue *self);
 	TnyFolder* (*get_outbox_func) (TnySendQueue *self);
 	void (*cancel_func) (TnySendQueue *self, gboolean remove, GError **err);
+	void (*update_func) (TnyFolderObserver *self, TnyFolderChange *change);
 };
 
 GType tny_camel_send_queue_get_type (void);
Index: tests/c-demo/tny-demoui-summary-view.c
===================================================================
--- tests/c-demo/tny-demoui-summary-view.c	(revision 2224)
+++ tests/c-demo/tny-demoui-summary-view.c	(working copy)
@@ -111,6 +111,10 @@
 	(G_TYPE_INSTANCE_GET_PRIVATE ((o), TNY_TYPE_DEMOUI_SUMMARY_VIEW, TnyDemouiSummaryViewPriv))
 
 
+static gboolean     filter_row             (GtkTreeModel *model,
+					    GtkTreeIter *iter,
+					    gpointer data);
+
 static gboolean
 cleanup_statusbar (gpointer data)
 {
@@ -759,7 +763,7 @@
 	GtkTreeModel *model;
 	GtkTreeModel *hmodel;
 	GtkTreeView *header_view = GTK_TREE_VIEW (priv->header_view);
-	GtkTreeModel *sortable;
+	GtkTreeModel *sortable, *filter_model;
 	GtkSelectionMode mode;
 
 	mode = gtk_tree_selection_get_mode (selection);
@@ -825,13 +829,25 @@
 				tny_gtk_header_list_model_sent_date_sort_func, 
 				NULL, NULL);
 
-			set_header_view_model (header_view, sortable);
+			/* Create a tree model filter to hide and show rows for cut operations  */
+			filter_model = gtk_tree_model_filter_new (sortable, NULL);
+			gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model),
+								filter_row,
+								self,
+								NULL);
 
+			/* Hide headers with attachment */
+			gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter_model));
+
+			set_header_view_model (header_view, filter_model);
+/* 			set_header_view_model (header_view, sortable); */
+
 			tny_folder_refresh_async (folder, 
 				refresh_current_folder, 
 				status_update, self);
 
 			g_object_unref (G_OBJECT (folder));
+
 		}
 	  }
 	} else {
@@ -1900,3 +1916,23 @@
 
 	return type;
 }
+
+static gboolean
+filter_row (GtkTreeModel *model,
+	    GtkTreeIter *iter,
+	    gpointer user_data)
+{
+
+	TnyHeaderFlags flags;
+
+	/* Get header from model */
+	gtk_tree_model_get (model, iter,
+			    TNY_GTK_HEADER_LIST_MODEL_FLAGS_COLUMN, &flags,
+			    -1);
+
+	/* Set visibility */
+	if (flags & TNY_HEADER_FLAG_ATTACHMENTS) 
+		return FALSE;
+
+	return TRUE;
+}
Index: libtinymail-queues/tny-generic-send-queue.c
===================================================================
--- libtinymail-queues/tny-generic-send-queue.c	(revision 2224)
+++ libtinymail-queues/tny-generic-send-queue.c	(working copy)
@@ -182,6 +182,10 @@
 		info->self = TNY_GENERIC_SEND_QUEUE (g_object_ref (self));
 		info->msg = tny_folder_get_msg (outbox, header, &err);
 
+		/* Emits msg-sending signal to inform a new msg is being sent */
+		g_signal_emit (self, tny_send_queue_signals [TNY_SEND_QUEUE_MSG_SENDING], 
+			       0, info->msg, err, i, total);
+		
 		if (err != NULL)
 		{
 			emit_error (TNY_SEND_QUEUE (self), NULL, err, info->i, info->total);
@@ -205,7 +209,11 @@
 		tny_queue_task_set_callback (task, generic_send_callback);
 
 		item = tny_queue_add_task (priv->queue, task);
-
+		
+		/* Emits msg-sent signal to inform msg has been sent */
+		g_signal_emit (self, tny_send_queue_signals [TNY_SEND_QUEUE_MSG_SENT], 
+			       0, info->msg, err, i, total);
+		
 		g_object_unref (header);
 		tny_iterator_next (iter); 
 		i++;
Index: libtinymail/tny-signals-marshal.list
===================================================================
--- libtinymail/tny-signals-marshal.list	(revision 2224)
+++ libtinymail/tny-signals-marshal.list	(working copy)
@@ -1 +1,2 @@
 VOID:OBJECT,OBJECT,POINTER
+VOID:OBJECT,OBJECT,INT,INT
Index: libtinymail/tny-send-queue.c
===================================================================
--- libtinymail/tny-send-queue.c	(revision 2224)
+++ libtinymail/tny-send-queue.c	(working copy)
@@ -143,6 +143,27 @@
 	if (!initialized) 
 	{
 /**
+ * TnySendQueue::msg-sending
+ * @self: the object on which the signal is emitted
+ * @arg1: The message that is being 
+ * @arg2: The current nth number of the message that is being sending
+ * @arg3: The total amount of messages currently being processed
+ *
+ * API WARNING: This API might change
+ *
+ * Emitted when a message is being proccessed to sending it
+ **/
+		tny_send_queue_signals[TNY_SEND_QUEUE_MSG_SENDING] =
+			g_signal_new ("msg_sending",
+				      TNY_TYPE_SEND_QUEUE,
+				      G_SIGNAL_RUN_FIRST,
+				      G_STRUCT_OFFSET (TnySendQueueIface, msg_sending),
+				      NULL, NULL,
+				      g_cclosure_marshal_VOID__POINTER,
+				      tny_marshal_VOID__OBJECT_OBJECT_INT_INT,
+				      G_TYPE_NONE, 4, TNY_TYPE_HEADER, TNY_TYPE_MSG, G_TYPE_UINT, G_TYPE_UINT);
+		
+/**
  * TnySendQueue::msg-sent
  * @self: the object on which the signal is emitted
  * @arg1: The message that got sent
@@ -151,13 +172,13 @@
  * Emitted when a message got sent
  **/
 		tny_send_queue_signals[TNY_SEND_QUEUE_MSG_SENT] =
-		   g_signal_new ("msg_sent",
-			TNY_TYPE_SEND_QUEUE,
-			G_SIGNAL_RUN_FIRST,
-			G_STRUCT_OFFSET (TnySendQueueIface, msg_sent),
-			NULL, NULL,
-			g_cclosure_marshal_VOID__POINTER,
-			G_TYPE_NONE, 1, TNY_TYPE_MSG);
+			g_signal_new ("msg_sent",
+				      TNY_TYPE_SEND_QUEUE,
+				      G_SIGNAL_RUN_FIRST,
+				      G_STRUCT_OFFSET (TnySendQueueIface, msg_sent),
+				      NULL, NULL,
+				      tny_marshal_VOID__OBJECT_OBJECT_INT_INT,
+				      G_TYPE_NONE, 4, TNY_TYPE_HEADER, TNY_TYPE_MSG, G_TYPE_UINT, G_TYPE_UINT);
 
 /**
  * TnySendQueue::error-happened
@@ -171,14 +192,14 @@
  * Emitted when a message didn't get sent because of an error
  **/
 		tny_send_queue_signals[TNY_SEND_QUEUE_ERROR_HAPPENED] =
-		   g_signal_new ("error_happened",
-			TNY_TYPE_SEND_QUEUE,
-			G_SIGNAL_RUN_FIRST,
-			G_STRUCT_OFFSET (TnySendQueueIface, error_happened),
-			NULL, NULL,
-			tny_marshal_VOID__OBJECT_OBJECT_POINTER,
-			G_TYPE_NONE, 3, TNY_TYPE_HEADER, TNY_TYPE_MSG, G_TYPE_POINTER);
-
+			g_signal_new ("error_happened",
+				      TNY_TYPE_SEND_QUEUE,
+				      G_SIGNAL_RUN_FIRST,
+				      G_STRUCT_OFFSET (TnySendQueueIface, error_happened),
+				      NULL, NULL,
+				      tny_marshal_VOID__OBJECT_OBJECT_POINTER,
+				      G_TYPE_NONE, 3, TNY_TYPE_HEADER, TNY_TYPE_MSG, G_TYPE_POINTER);
+		
 		initialized = TRUE;
 	}
 }
Index: libtinymail/tny-send-queue.h
===================================================================
--- libtinymail/tny-send-queue.h	(revision 2224)
+++ libtinymail/tny-send-queue.h	(working copy)
@@ -40,6 +40,7 @@
 
 enum _TnySendQueueSignal
 {
+	TNY_SEND_QUEUE_MSG_SENDING,
 	TNY_SEND_QUEUE_MSG_SENT,
 	TNY_SEND_QUEUE_ERROR_HAPPENED,
 	TNY_SEND_QUEUE_LAST_SIGNAL
@@ -53,7 +54,8 @@
 	GTypeInterface parent;
 	
 	/* Signals */
-	void (*msg_sent) (TnySendQueue *self, TnyMsg *msg, gpointer user_data);
+	void (*msg_sending) (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, guint nth, guint total);
+	void (*msg_sent) (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, guint nth, guint total);
 	void (*error_happened) (TnySendQueue *self, TnyHeader *header, TnyMsg *msg, GError *err, gpointer user_data);
 
 	/* methods */


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