[evolution-mapi] Bug #612395 - Folder unread count disappears



commit 3a1045dec046573c76975f453569fbaa741dbee5
Author: Milan Crha <mcrha redhat com>
Date:   Wed Jun 9 18:03:22 2010 +0200

    Bug #612395 - Folder unread count disappears

 src/camel/camel-mapi-folder.c                  |  151 ++++++++++++------------
 src/camel/camel-mapi-store.c                   |    3 +
 src/camel/camel-mapi-summary.c                 |   39 ++++++
 src/camel/camel-mapi-summary.h                 |    1 +
 src/libexchangemapi/exchange-mapi-connection.c |    8 +-
 src/libexchangemapi/exchange-mapi-connection.h |    1 +
 6 files changed, 125 insertions(+), 78 deletions(-)
---
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index 8428539..a544714 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -105,47 +105,45 @@ mapi_folder_search_by_uids (CamelFolder *folder, const gchar *expression, GPtrAr
 	return matches;
 }
 
-static gboolean
-mapi_refresh_info(CamelFolder *folder, CamelException *ex)
+static void
+update_store_summary (CamelFolder *folder, CamelException *ex)
 {
 	CamelStore *parent_store;
+	CamelStoreSummary *store_summary;
 	CamelStoreInfo *si;
 	const gchar *full_name;
 
 	full_name = camel_folder_get_full_name (folder);
 	parent_store = camel_folder_get_parent_store (folder);
+	store_summary = (CamelStoreSummary *)((CamelMapiStore *)parent_store)->summary;
 
-	/*
-	 * Checking for the summary->time_string here since the first the a
-	 * user views a folder, the read cursor is in progress, and the getQM
-	 * should not interfere with the process
-	 */
-	//	if (summary->time_string && (strlen (summary->time_string) > 0))  {
-	if (1) {
-		mapi_refresh_folder(folder, ex);
-		si = camel_store_summary_path ((CamelStoreSummary *)((CamelMapiStore *)parent_store)->summary, full_name);
-
-		if (si) {
-			guint32 unread, total;
-
-			unread = folder->summary->unread_count;
-			total = camel_folder_summary_count (folder->summary);
-			if (si->total != total || si->unread != unread) {
-				si->total = total;
-				si->unread = unread;
-				camel_store_summary_touch ((CamelStoreSummary *)((CamelMapiStore *)parent_store)->summary);
-			}
-			camel_store_summary_info_free ((CamelStoreSummary *)((CamelMapiStore *)parent_store)->summary, si);
+	si = camel_store_summary_path (store_summary, full_name);
+
+	if (si) {
+		guint32 unread, total;
+
+		unread = folder->summary->unread_count;
+		total = camel_folder_summary_count (folder->summary);
+
+		if (si->total != total || si->unread != unread) {
+			si->total = total;
+			si->unread = unread;
+			camel_store_summary_touch (store_summary);
 		}
-		camel_folder_summary_save_to_db (folder->summary, ex);
-		camel_store_summary_save ((CamelStoreSummary *)((CamelMapiStore *)parent_store)->summary);
-	} else {
-		/* We probably could not get the messages the first time. (get_folder) failed???!
-		 * so do a get_folder again. And hope that it works
-		 */
-		g_print("Reloading folder...something wrong with the summary....\n");
+		camel_store_summary_info_free (store_summary, si);
 	}
-	//#endif
+	camel_folder_summary_save_to_db (folder->summary, ex);
+	camel_store_summary_save (store_summary);
+}
+
+static gboolean
+mapi_refresh_info (CamelFolder *folder, CamelException *ex)
+{
+	mapi_refresh_folder (folder, ex);
+	if (camel_exception_is_set (ex))
+		return FALSE;
+
+	update_store_summary (folder, ex);
 
 	return !camel_exception_is_set (ex);
 }
@@ -521,18 +519,6 @@ mapi_update_cache (CamelFolder *folder, GSList *list, CamelFolderChangeInfo **ch
 }
 
 static void
-mapi_sync_summary (CamelFolder *folder, CamelException *ex)
-{
-	CamelStore *parent_store;
-
-	parent_store = camel_folder_get_parent_store (folder);
-
-	camel_folder_summary_save_to_db (folder->summary, ex);
-	camel_store_summary_touch ((CamelStoreSummary *)((CamelMapiStore *)parent_store)->summary);
-	camel_store_summary_save ((CamelStoreSummary *)((CamelMapiStore *)parent_store)->summary);
-}
-
-static void
 mapi_utils_do_flags_diff (flags_diff_t *diff, guint32 old, guint32 _new)
 {
 	diff->changed = old ^ _new;
@@ -550,11 +536,17 @@ struct mapi_update_deleted_msg {
 static gboolean
 deleted_items_sync_cb (FetchItemsCallbackData *item_data, gpointer data)
 {
-	GSList **uid_list = (GSList **) data;
+	guint32 msg_flags = CAMEL_MESSAGE_FOLDER_FLAGGED; /* to not have 0 in the hash table */
+	GHashTable *uids = data;
 	gchar *msg_uid = exchange_mapi_util_mapi_ids_to_uid (item_data->fid,
 							     item_data->mid);
 
-	*uid_list = g_slist_prepend (*uid_list, msg_uid);
+	if ((item_data->msg_flags & MSGFLAG_READ) != 0)
+		msg_flags |= CAMEL_MESSAGE_SEEN;
+	if ((item_data->msg_flags & MSGFLAG_HASATTACH) != 0)
+		msg_flags |= CAMEL_MESSAGE_ATTACHMENTS;
+
+	g_hash_table_insert (uids, msg_uid, GINT_TO_POINTER (msg_flags));
 
 	/* Progress update */
 	if (item_data->total > 0)
@@ -567,18 +559,6 @@ deleted_items_sync_cb (FetchItemsCallbackData *item_data, gpointer data)
 	return TRUE;
 }
 
-static gboolean
-mapi_camel_get_last_modif_list (ExchangeMapiConnection *conn, mapi_id_t fid, TALLOC_CTX *mem_ctx, struct SPropTagArray *props, gpointer data)
-{
-	static const uint32_t prop_list[] = {
-		PR_LAST_MODIFICATION_TIME
-	};
-
-	g_return_val_if_fail (props != NULL, FALSE);
-
-	return exchange_mapi_utils_add_props_to_props_array (mem_ctx, props, prop_list, G_N_ELEMENTS (prop_list));
-}
-
 static void
 mapi_sync_deleted (CamelSession *session, CamelSessionThreadMsg *msg)
 {
@@ -591,8 +571,9 @@ mapi_sync_deleted (CamelSession *session, CamelSessionThreadMsg *msg)
 	CamelStore *parent_store;
 
 	guint32 index, count, options = 0;
-	GSList *server_uid_list = NULL;
+	GHashTable *server_messages = NULL;
 	const gchar *uid = NULL;
+	gboolean flags_changed = FALSE;
 
 	parent_store = camel_folder_get_parent_store (m->folder);
 
@@ -614,10 +595,12 @@ mapi_sync_deleted (CamelSession *session, CamelSessionThreadMsg *msg)
 	if (mapi_folder->type & CAMEL_MAPI_FOLDER_PUBLIC)
 		options |= MAPI_OPTIONS_USE_PFSTORE;
 
+	server_messages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
 	/*Get the UID list from server.*/
 	exchange_mapi_connection_fetch_items  (camel_mapi_store_get_exchange_connection (mapi_store), m->folder_id, NULL, NULL,
-					       mapi_camel_get_last_modif_list, NULL,
-					       deleted_items_sync_cb, &server_uid_list,
+					       NULL, NULL,
+					       deleted_items_sync_cb, server_messages,
 					       options | MAPI_OPTIONS_DONT_OPEN_MESSAGE);
 
 	camel_operation_end (NULL);
@@ -625,8 +608,10 @@ mapi_sync_deleted (CamelSession *session, CamelSessionThreadMsg *msg)
 	camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	/* Check if we have to stop */
-	if (camel_operation_cancel_check(NULL))
+	if (camel_operation_cancel_check(NULL)) {
+		g_hash_table_destroy (server_messages);
 		return;
+	}
 
 	changes = camel_folder_change_info_new ();
 
@@ -637,34 +622,47 @@ mapi_sync_deleted (CamelSession *session, CamelSessionThreadMsg *msg)
 
 	/* Iterate over cache and check if the UID is in server*/
 	for (index = 0; index < count; index++) {
-		GSList *tmp_list_item = NULL;
+		guint32 msg_flags;
 
 		/* Iterate in a reverse order, thus removal will not hurt */
 		info = camel_folder_summary_index (m->folder->summary, count - index - 1);
 		if (!info) continue; /*This is bad. *Should* not happen*/
 
 		uid = camel_message_info_uid (info);
-
-		if (server_uid_list) {
-			/* TODO : Find a better way and avoid this linear search */
-			tmp_list_item = g_slist_find_custom (server_uid_list, (gconstpointer) uid,
-						  (GCompareFunc) g_strcmp0);
+		if (!uid) {
+			camel_message_info_free (info);
+			continue;
 		}
 
+		msg_flags = GPOINTER_TO_INT (g_hash_table_lookup (server_messages, uid));
+
 		/* If it is not in server list, clean our cache */
-		if ((!tmp_list_item || !tmp_list_item->data) && uid) {
+		if (!msg_flags) {
 			CAMEL_MAPI_FOLDER_REC_LOCK (m->folder, cache_lock);
 			camel_folder_summary_remove_uid (m->folder->summary, uid);
 			camel_data_cache_remove (mapi_folder->cache, "cache", uid, NULL);
 			camel_folder_change_info_remove_uid (changes, uid);
 			CAMEL_MAPI_FOLDER_REC_UNLOCK (m->folder, cache_lock);
+		} else {
+			CamelMapiMessageInfo *mapi_info = (CamelMapiMessageInfo *) info;
+
+			msg_flags = msg_flags & (~CAMEL_MESSAGE_FOLDER_FLAGGED);
+			if (mapi_info->server_flags != msg_flags) {
+				mapi_info->server_flags = msg_flags;
+				camel_message_info_set_flags (info, msg_flags, CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_ATTACHMENTS);
+				camel_folder_change_info_change_uid (changes, uid);
+				flags_changed = TRUE;
+			}
 		}
 
+		camel_message_info_free (info);
+
 		/* Progress update */
 		camel_operation_progress (NULL, (index * 100)/count); /* ;-) */
 
 		/* Check if we have to stop */
 		if (camel_operation_cancel_check(NULL)) {
+			g_hash_table_destroy (server_messages);
 			if (camel_folder_change_info_changed (changes))
 				camel_folder_changed (m->folder, changes);
 			camel_folder_change_info_free (changes);
@@ -674,15 +672,16 @@ mapi_sync_deleted (CamelSession *session, CamelSessionThreadMsg *msg)
 
 	camel_operation_end (NULL);
 
-	if (camel_folder_change_info_changed (changes))
+	if (camel_folder_change_info_changed (changes)) {
+		if (flags_changed)
+			camel_mapi_summary_update_store_info_counts (CAMEL_MAPI_SUMMARY (CAMEL_FOLDER (mapi_folder)->summary));
 		camel_folder_changed (m->folder, changes);
+	}
 	camel_folder_change_info_free (changes);
 
-	m->need_refresh = camel_folder_summary_count (m->folder->summary) != g_slist_length (server_uid_list);
+	m->need_refresh = camel_folder_summary_count (m->folder->summary) != g_hash_table_size (server_messages);
 
-	/* Discard server uid list */
-	g_slist_foreach (server_uid_list, (GFunc) g_free, NULL);
-	g_slist_free (server_uid_list);
+	g_hash_table_destroy (server_messages);
 }
 
 static void
@@ -745,7 +744,7 @@ mapi_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
 
 	if (((CamelOfflineStore *) mapi_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL ||
 			((CamelService *)mapi_store)->status == CAMEL_SERVICE_DISCONNECTED) {
-		mapi_sync_summary (folder, ex);
+		update_store_summary (folder, ex);
 		return !camel_exception_is_set (ex);
 	}
 
@@ -891,7 +890,7 @@ mapi_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
 	}
 
 	camel_service_lock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
-	mapi_sync_summary (folder, ex);
+	update_store_summary (folder, ex);
 	camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	return !camel_exception_is_set (ex);
@@ -1068,7 +1067,7 @@ mapi_refresh_folder(CamelFolder *folder, CamelException *ex)
 		mapi_summary->sync_time_stamp = g_time_val_to_iso8601 (&fetch_data->last_modification_time);
 
 		camel_folder_summary_touch (folder->summary);
-		mapi_sync_summary (folder, ex);
+		update_store_summary (folder, ex);
 
 		camel_service_unlock (CAMEL_SERVICE (mapi_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
 		is_locked = FALSE;
diff --git a/src/camel/camel-mapi-store.c b/src/camel/camel-mapi-store.c
index 04ad241..7dbbc10 100644
--- a/src/camel/camel-mapi-store.c
+++ b/src/camel/camel-mapi-store.c
@@ -1671,6 +1671,9 @@ mapi_subscribe_folder(CamelStore *store, const gchar *folder_name, CamelExceptio
 			camel_url_free (url);
 		}
 
+		fi->unread = si->unread;
+		fi->total = si->total;
+		fi->flags = si->flags;
 		camel_store_summary_info_free((CamelStoreSummary *)mapi_store->summary, si);
 	}
 
diff --git a/src/camel/camel-mapi-summary.c b/src/camel/camel-mapi-summary.c
index 9823a5d..73011f2 100644
--- a/src/camel/camel-mapi-summary.c
+++ b/src/camel/camel-mapi-summary.c
@@ -33,6 +33,7 @@
 
 #include "camel-mapi-folder.h"
 #include "camel-mapi-summary.h"
+#include "camel-mapi-store.h"
 
 #define CAMEL_MAPI_SUMMARY_VERSION (1)
 
@@ -148,6 +149,41 @@ camel_mapi_summary_new (CamelFolder *folder, const gchar *filename)
 	return summary;
 }
 
+void
+camel_mapi_summary_update_store_info_counts (CamelMapiSummary *mapi_summary)
+{
+	CamelFolderSummary *summary;
+
+	g_return_if_fail (mapi_summary != NULL);
+
+	summary = CAMEL_FOLDER_SUMMARY (mapi_summary);
+	g_return_if_fail (summary != NULL);
+
+	if (summary->folder) {
+		CamelMapiStore *mapi_store;
+
+		mapi_store = CAMEL_MAPI_STORE (camel_folder_get_parent_store (summary->folder));
+		if (mapi_store && mapi_store->summary) {
+			CamelStoreInfo *si;
+			CamelStoreSummary *store_summary = CAMEL_STORE_SUMMARY (mapi_store->summary);
+
+			g_return_if_fail (store_summary != NULL);
+
+			si = camel_store_summary_path (store_summary, camel_folder_get_full_name (summary->folder));
+			if (si) {
+				if (si->unread != summary->unread_count || si->total != summary->saved_count) {
+					si->unread = summary->unread_count;
+					si->total = summary->saved_count;
+
+					camel_store_summary_touch (store_summary);
+				}
+
+				camel_store_summary_info_free (store_summary, si);
+			}
+		}
+	}
+}
+
 static gint
 mapi_summary_header_from_db (CamelFolderSummary *summary, CamelFIRecord *fir)
 {
@@ -173,6 +209,7 @@ mapi_summary_header_from_db (CamelFolderSummary *summary, CamelFIRecord *fir)
 
 	return 0;
 }
+
 static CamelFIRecord *
 mapi_summary_header_to_db (CamelFolderSummary *summary, CamelException *ex)
 {
@@ -190,6 +227,8 @@ mapi_summary_header_to_db (CamelFolderSummary *summary, CamelException *ex)
 
 	fir->bdata = g_strdup_printf ("%d %s", CAMEL_MAPI_SUMMARY_VERSION, mapi_summary->sync_time_stamp);
 
+	camel_mapi_summary_update_store_info_counts (mapi_summary);
+
 	return fir;
 }
 
diff --git a/src/camel/camel-mapi-summary.h b/src/camel/camel-mapi-summary.h
index 2311a19..a657faa 100644
--- a/src/camel/camel-mapi-summary.h
+++ b/src/camel/camel-mapi-summary.h
@@ -85,6 +85,7 @@ GType camel_mapi_summary_get_type (void);
 CamelFolderSummary *camel_mapi_summary_new (struct _CamelFolder *folder, const gchar *filename);
 
 void mapi_summary_clear (CamelFolderSummary *summary, gboolean uncache);
+void camel_mapi_summary_update_store_info_counts (CamelMapiSummary *mapi_summary);
 
 G_END_DECLS
 
diff --git a/src/libexchangemapi/exchange-mapi-connection.c b/src/libexchangemapi/exchange-mapi-connection.c
index a63fb52..5de210f 100644
--- a/src/libexchangemapi/exchange-mapi-connection.c
+++ b/src/libexchangemapi/exchange-mapi-connection.c
@@ -1439,11 +1439,12 @@ exchange_mapi_connection_fetch_items   (ExchangeMapiConnection *conn, mapi_id_t
 		goto cleanup;
 	}
 
-	SPropTagArray = set_SPropTagArray(mem_ctx, 0x4,
+	SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
 					  PR_FID,
 					  PR_MID,
 					  PR_LAST_MODIFICATION_TIME,
-					  PR_HASATTACH);
+					  PR_HASATTACH,
+					  PR_MESSAGE_FLAGS);
 
 	/* Set primary columns to be fetched */
 	retval = SetColumns(&obj_table, SPropTagArray);
@@ -1500,6 +1501,7 @@ exchange_mapi_connection_fetch_items   (ExchangeMapiConnection *conn, mapi_id_t
 			const mapi_id_t *pfid;
 			const mapi_id_t	*pmid;
 			const bool *has_attach = NULL;
+			const uint32_t *msg_flags;
 			GSList *attach_list = NULL;
 			GSList *recip_list = NULL;
 			GSList *stream_list = NULL;
@@ -1511,6 +1513,7 @@ exchange_mapi_connection_fetch_items   (ExchangeMapiConnection *conn, mapi_id_t
 			pmid = (const uint64_t *) get_SPropValue_SRow_data(&SRowSet.aRow[i], PR_MID);
 
 			has_attach = (const bool *) get_SPropValue_SRow_data(&SRowSet.aRow[i], PR_HASATTACH);
+			msg_flags = get_SPropValue_SRow_data (&SRowSet.aRow[i], PR_MESSAGE_FLAGS);
 
 			if (options & MAPI_OPTIONS_DONT_OPEN_MESSAGE)
 				goto relax;
@@ -1588,6 +1591,7 @@ exchange_mapi_connection_fetch_items   (ExchangeMapiConnection *conn, mapi_id_t
 				item_data->conn = conn;
 				item_data->fid = *pfid;
 				item_data->mid = *pmid;
+				item_data->msg_flags = msg_flags ? *msg_flags : 0;
 				item_data->properties = &properties_array;
 				item_data->streams = stream_list;
 				item_data->recipients = recip_list;
diff --git a/src/libexchangemapi/exchange-mapi-connection.h b/src/libexchangemapi/exchange-mapi-connection.h
index 8a4a595..ff83637 100644
--- a/src/libexchangemapi/exchange-mapi-connection.h
+++ b/src/libexchangemapi/exchange-mapi-connection.h
@@ -115,6 +115,7 @@ typedef struct {
 	struct mapi_SPropValue_array *properties;
 	mapi_id_t fid;
 	mapi_id_t mid;
+	uint32_t msg_flags; /* used only with fetch_items */
 	GSList *attachments;
 	GSList *recipients;
 	GSList *gallist;



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