Patch: track number of messages in folders without opening summary



	Hi,

	This patch allows us to process folder_changed signals for knowing the
number of messages in folders, without opening their summary. This is
needed for some providers that update the number of messages at camel
side, without an event started in tinymail level.

	What we did is just tracking folder_opened in the CamelStore. So, if a
CamelFolder is opened without tinymail knowing about, we can at least
track their folder_changed events immediately, and while those instances
are still alive.

Changelog entry:
	* libtinymail-camel/tny-camel-folder.[ch], 
	libtinymail-camel/tny-camel-folder-priv.h
	(tny_camel_folder_track_folder_changed): added a method to add 
	a CamelFolder instance to track folder_changed event until it's
	finalized. This is useful to track only the number of messages 
	available.
  
	* libtinymail-camel/tny-camel-store-account.c: added handling of 
	folder_opened signal. When a folder is opened, we register it for
	tracking the number of messages. THis allows us to track the
	number of messages without opening the folder summary.

-- 
José Dapena Paz <jdapena igalia com>
Igalia
diff --git a/ChangeLog b/ChangeLog
index 9c40e3f..ade18d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2009-06-22  Jose Dapena Paz  <jdapena igalia com>
+
+	* libtinymail-camel/tny-camel-folder.[ch], 
+	libtinymail-camel/tny-camel-folder-priv.h
+	(tny_camel_folder_track_folder_changed): added a method to add 
+	a CamelFolder instance to track folder_changed event until it's
+	finalized. This is useful to track only the number of messages 
+	available.
+  
+	* libtinymail-camel/tny-camel-store-account.c: added handling of 
+	folder_opened signal. When a folder is opened, we register it for
+	tracking the number of messages. THis allows us to track the
+	number of messages without opening the folder summary.
+
 2009-06-19  Jose Dapena Paz  <jdapena igalia com>
 
 	* libtinymailui-gtk/tny-gtk-folder-list-store.c: delay refresh
diff --git a/libtinymail-camel/tny-camel-folder-priv.h b/libtinymail-camel/tny-camel-folder-priv.h
index 48bc5eb..692287d 100644
--- a/libtinymail-camel/tny-camel-folder-priv.h
+++ b/libtinymail-camel/tny-camel-folder-priv.h
@@ -36,6 +36,8 @@ struct _TnyCamelFolderPriv
 	GStaticRecMutex *reason_lock;
 	GStaticRecMutex *folder_lock, *obs_lock;
 	CamelFolder *folder;
+	CamelFolder *folder_tracking;
+	guint folder_tracking_id;
 	gchar *folder_name;
 	TnyAccount *account; CamelStore *store;
 	guint cached_length, unread_length, unread_sync, local_size;
@@ -84,6 +86,7 @@ void _tny_camel_folder_set_allow_external_images (TnyCamelFolder *self, const gc
 void _tny_camel_folder_remove_folder_actual (TnyFolderStore *self, TnyFolder *folder, TnyFolderStoreChange *change, GError **err);
 
 void _tny_camel_folder_freeup_observers (TnyCamelFolder *self, TnyCamelFolderPriv *priv);
+void _tny_camel_folder_track_folder_changed (TnyCamelFolder *self, CamelFolder *folder);
 
 CamelFolder* _tny_camel_folder_get_folder (TnyCamelFolder *self);
 
diff --git a/libtinymail-camel/tny-camel-folder.c b/libtinymail-camel/tny-camel-folder.c
index 4b1e507..7702146 100644
--- a/libtinymail-camel/tny-camel-folder.c
+++ b/libtinymail-camel/tny-camel-folder.c
@@ -326,6 +326,43 @@ _tny_camel_folder_check_unread_count (TnyCamelFolder *self)
 }
 
 static void 
+folder_tracking_changed (CamelFolder *camel_folder, CamelFolderChangeInfo *info, gpointer user_data)
+{
+	TnyCamelFolder *self = user_data;
+	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+	TnyFolderChange *change = NULL;
+	CamelFolderSummary *summary;
+	gboolean old = priv->dont_fkill;
+	gint i = 0; gboolean urcnted = FALSE;
+
+	if (!priv->handle_changes)
+		return;
+
+	if (!change && info->uid_changed != NULL && info->uid_changed->len > 0) {
+		/* Commented because it seems to be the source of weird hangs */
+		priv->cached_length = (guint) camel_folder_get_message_count (camel_folder);
+		priv->unread_length = (guint) camel_folder_get_unread_message_count (camel_folder);
+		urcnted = TRUE;
+		change = tny_folder_change_new (TNY_FOLDER (self));
+	}
+
+	update_iter_counts (priv);
+
+	if (change)
+	{
+		tny_folder_change_set_new_unread_count (change, priv->unread_length);
+		tny_folder_change_set_new_all_count (change, priv->cached_length);
+		priv->dont_fkill = TRUE;
+		notify_folder_observers_about_in_idle (TNY_FOLDER (self), change,
+			TNY_FOLDER_PRIV_GET_SESSION (priv));
+		g_object_unref (change);
+		priv->dont_fkill = old;
+	}
+
+	return;
+}
+
+static void 
 folder_changed (CamelFolder *camel_folder, CamelFolderChangeInfo *info, gpointer user_data)
 {
 	TnyCamelFolderPriv *priv = (TnyCamelFolderPriv *) user_data;
@@ -1559,11 +1596,13 @@ _tny_camel_folder_set_account (TnyCamelFolder *self, TnyAccount *account)
 	priv->account = TNY_ACCOUNT (g_object_ref (account));
 #endif
 
-	if (priv->store)
+	if (priv->store) {
 		camel_object_unref (priv->store);
+	}
 	priv->store = (CamelStore*) _tny_camel_account_get_service (TNY_CAMEL_ACCOUNT (priv->account));
-	if (priv->store)
+	if (priv->store) {
 		camel_object_ref (priv->store);
+	}
 
 	return;
 }
@@ -4720,6 +4759,39 @@ tny_camel_folder_uncache_nl (TnyCamelFolder *self)
 	return;
 }
 
+static void 
+folder_tracking_finalize (CamelObject *folder, gpointer event_data, gpointer user_data)
+{
+	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (user_data);
+	if (priv->folder_tracking_id)
+		priv->folder_tracking_id = 0;
+
+	if (priv->folder_tracking)
+		priv->folder_tracking = NULL;
+}
+
+void
+_tny_camel_folder_track_folder_changed (TnyCamelFolder *self, 
+					CamelFolder *folder)
+{
+	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
+
+	if (priv->folder_tracking == folder)
+		return;
+
+	if (priv->folder_tracking) {
+		camel_object_remove_event (priv->folder_tracking, priv->folder_tracking_id);
+		camel_object_unhook_event (priv->folder_tracking, "finalize", folder_tracking_finalize, self);
+	}
+	priv->folder_tracking = folder;
+	if  (priv->folder_tracking != NULL) {
+		priv->folder_tracking_id = camel_object_hook_event (priv->folder_tracking, "folder_changed", folder_tracking_changed, self);
+		camel_object_hook_event (priv->folder_tracking, "finalize", folder_tracking_finalize, self);
+	}
+
+}
+
+
 
 void 
 _tny_camel_folder_unreason (TnyCamelFolderPriv *priv)
@@ -6331,8 +6403,9 @@ tny_camel_folder_dispose (GObject *object)
 	TnyCamelFolder *self = (TnyCamelFolder*) object;
 	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
 
-	if (priv->store)
+	if (priv->store) {
 		camel_object_unref (priv->store);
+	}
 
 	if (priv->account && TNY_IS_CAMEL_STORE_ACCOUNT (priv->account)) {
 		_tny_camel_store_account_remove_from_managed_folders (TNY_CAMEL_STORE_ACCOUNT (priv->account), 
@@ -6392,6 +6465,10 @@ tny_camel_folder_finalize (GObject *object)
 	TnyCamelFolder *self = (TnyCamelFolder*) object;
 	TnyCamelFolderPriv *priv = TNY_CAMEL_FOLDER_GET_PRIVATE (self);
 
+	if (priv->folder_tracking) {
+		camel_object_remove_event (priv->folder_tracking, priv->folder_tracking_id);
+		camel_object_unhook_event (priv->folder_tracking, "finalize", folder_tracking_finalize, self);
+	}
 
 #ifdef DEBUG
 	g_print ("Finalizing TnyCamelFolder: %s\n", 
@@ -6618,6 +6695,8 @@ tny_camel_folder_instance_init (GTypeInstance *instance, gpointer g_class)
 	priv->loaded = FALSE;
 	priv->folder_changed_id = 0;
 	priv->folder = NULL;
+	priv->folder_tracking = NULL;
+	priv->folder_tracking_id = 0;
 	priv->cached_name = NULL;
 	priv->cached_folder_type = TNY_FOLDER_TYPE_UNKNOWN;
 	priv->remove_strat = tny_camel_msg_remove_strategy_new ();
diff --git a/libtinymail-camel/tny-camel-store-account.c b/libtinymail-camel/tny-camel-store-account.c
index eb5254c..5ec73e1 100644
--- a/libtinymail-camel/tny-camel-store-account.c
+++ b/libtinymail-camel/tny-camel-store-account.c
@@ -75,6 +75,28 @@ typedef struct {
 } NotFolObInIdleInfo;
 
 static void 
+folder_opened (CamelStore *camel_store, CamelFolder *camel_folder, TnyCamelStoreAccount *self)
+{
+	GList *node;
+	TnyCamelStoreAccountPriv *priv = TNY_CAMEL_STORE_ACCOUNT_GET_PRIVATE (self);
+
+	if (camel_folder == NULL)
+		return;
+
+	for (node = priv->managed_folders; node != NULL; node = g_list_next (node)) {
+		TnyCamelFolder *folder = (TnyCamelFolder *) node->data;
+
+		if (TNY_IS_CAMEL_FOLDER (folder)) {
+			if (g_strcmp0 (tny_folder_get_id (TNY_FOLDER (folder)), camel_folder_get_name (camel_folder))==0) {
+				_tny_camel_folder_track_folder_changed (folder, camel_folder);
+				break;
+			}
+		}
+	}
+	
+}
+
+static void 
 do_notify_in_idle_destroy (gpointer user_data)
 {
 	NotFolObInIdleInfo *info = (NotFolObInIdleInfo *) user_data;
@@ -489,6 +511,7 @@ tny_camel_store_account_prepare (TnyCamelAccount *self, gboolean recon_if, gbool
 
 		if (apriv->service && CAMEL_IS_SERVICE (apriv->service) && 
 		  new_service && !camel_exception_is_set (apriv->ex)) {
+			camel_object_unhook_event (apriv->service, "folder_opened", folder_opened, self);
 			camel_object_unref (apriv->service);
 			apriv->service = NULL;
 		}
@@ -521,8 +544,10 @@ tny_camel_store_account_prepare (TnyCamelAccount *self, gboolean recon_if, gbool
 				g_free (str);
 			}
 
-			if (apriv->service && CAMEL_IS_SERVICE (apriv->service))
+			if (apriv->service && CAMEL_IS_SERVICE (apriv->service)) {
+				camel_object_unhook_event (new_service, "folder_opened", folder_opened, self);
 				camel_object_unref (apriv->service);
+			}
 
 			apriv->service = new_service;
 			apriv->service->data = self;
@@ -531,9 +556,14 @@ tny_camel_store_account_prepare (TnyCamelAccount *self, gboolean recon_if, gbool
 			apriv->service->reconnecter = (con_op) reconnecting;
 			apriv->service->reconnection = (con_op) reconnection;
 
+			if (new_service)
+				camel_object_hook_event (new_service, "folder_opened", folder_opened, self);
+
 		} else if (camel_exception_is_set (apriv->ex) && new_service) {
-			if (CAMEL_IS_OBJECT (new_service))
+			if (CAMEL_IS_OBJECT (new_service)) {
+				camel_object_unhook_event (new_service, "folder_opened", folder_opened, self);
 				camel_object_unref (new_service);
+			}
 		}
 	  }
 	} else {
@@ -899,6 +929,12 @@ tny_camel_store_account_finalize (GObject *object)
 	TnyCamelStoreAccount *self = (TnyCamelStoreAccount *)object;
 	TnyCamelStoreAccountPriv *priv = TNY_CAMEL_STORE_ACCOUNT_GET_PRIVATE (self);
 
+	TnyCamelAccountPriv *apriv = TNY_CAMEL_ACCOUNT_GET_PRIVATE (self);
+
+	if (apriv->service) {
+		camel_object_unhook_event (apriv->service, "folder_opened", folder_opened, self);
+	}
+
 	/* g_static_rec_mutex_free (priv->factory_lock); */
 	g_free (priv->factory_lock);
 	priv->factory_lock = NULL;


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