[evolution] Bug 609982 - Avoid unnecessary prompts when marking folders as read



commit 781c3b10aae6a0d7630bca665787b5ff31e4b567
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue Feb 16 16:55:51 2010 -0500

    Bug 609982 - Avoid unnecessary prompts when marking folders as read

 plugins/mark-all-read/mark-all-read.c |  213 ++++++++++++++++++--------------
 1 files changed, 120 insertions(+), 93 deletions(-)
---
diff --git a/plugins/mark-all-read/mark-all-read.c b/plugins/mark-all-read/mark-all-read.c
index 3923f86..24bc485 100644
--- a/plugins/mark-all-read/mark-all-read.c
+++ b/plugins/mark-all-read/mark-all-read.c
@@ -196,6 +196,104 @@ prompt_user (void)
 	return response;
 }
 
+static gboolean
+scan_folder_tree_for_unread_helper (GtkTreeModel *model,
+                                    GtkTreeIter *iter,
+                                    GtkTreePath *path,
+                                    gint initial_depth,
+                                    gint *relative_depth)
+{
+	/* This is based on gtk_tree_model_foreach().  Unfortunately
+	 * that function insists on traversing the entire tree model. */
+
+	do {
+		GtkTreeIter child;
+		gboolean folder_has_unread;
+		gboolean is_draft = FALSE;
+		gboolean is_store = FALSE;
+		guint unread = 0;
+
+		gtk_tree_model_get (
+			model, iter,
+			COL_UINT_UNREAD, &unread,
+			COL_BOOL_IS_STORE, &is_store,
+			COL_BOOL_IS_DRAFT, &is_draft, -1);
+
+		folder_has_unread =
+			!is_store && !is_draft &&
+			unread > 0 && unread != ~((guint) 0);
+
+		if (folder_has_unread) {
+			gint current_depth;
+
+			current_depth = gtk_tree_path_get_depth (path);
+			*relative_depth = current_depth - initial_depth + 1;
+
+			/* If we find unread messages in a child of the
+			 * selected folder, short-circuit the recursion. */
+			if (*relative_depth > 1)
+				return TRUE;
+		}
+
+		if (gtk_tree_model_iter_children (model, &child, iter)) {
+			gtk_tree_path_down (path);
+
+			if (scan_folder_tree_for_unread_helper (
+				model, &child, path,
+				initial_depth, relative_depth))
+				return TRUE;
+
+			gtk_tree_path_up (path);
+		}
+
+		gtk_tree_path_next (path);
+
+	} while (gtk_tree_model_iter_next (model, iter));
+
+	return FALSE;
+}
+
+static gint
+scan_folder_tree_for_unread (const gchar *folder_uri)
+{
+	GtkTreeRowReference *reference;
+	EMFolderTreeModel *model;
+	gint relative_depth = 0;
+
+	/* Traverses the selected folder and its children and returns
+	 * the relative depth of the furthest child folder containing
+	 * unread mail.  Except, we abort the traversal as soon as we
+	 * find a child folder with unread messages.  So the possible
+	 * return values are:
+	 *
+	 *    Depth = 0:  No unread mail found.
+	 *    Depth = 1:  Unread mail only in selected folder.
+	 *    Depth = 2:  Unread mail in one of the child folders.
+	 */
+
+	if (folder_uri == NULL)
+		return 0;
+
+	model = em_folder_tree_model_get_default ();
+	reference = em_folder_tree_model_lookup_uri (model, folder_uri);
+
+	if (gtk_tree_row_reference_valid (reference)) {
+		GtkTreePath *path;
+		GtkTreeIter iter;
+
+		path = gtk_tree_row_reference_get_path (reference);
+		gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
+
+		scan_folder_tree_for_unread_helper (
+			GTK_TREE_MODEL (model), &iter, path,
+			gtk_tree_path_get_depth (path), &relative_depth);
+
+		gtk_tree_path_free (path);
+	}
+
+	return relative_depth;
+}
+
 static void
 mark_all_as_read (CamelFolder *folder)
 {
@@ -238,15 +336,14 @@ mar_all_sub_folders (CamelStore *store,
 }
 
 static void
-mar_got_folder (gchar *uri,
+mar_got_folder (gchar *folder_uri,
                 CamelFolder *folder,
                 gpointer data)
 {
-	CamelFolderInfo *info;
+	CamelFolderInfo *folder_info;
 	CamelStore *store;
 	CamelException ex;
 	gint response;
-	guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE | CAMEL_STORE_FOLDER_INFO_FAST;
 
 	/* FIXME we have to disable the menu item */
 	if (!folder)
@@ -255,12 +352,15 @@ mar_got_folder (gchar *uri,
 	camel_exception_init (&ex);
 
 	store = folder->parent_store;
-	info = camel_store_get_folder_info (store, folder->full_name, flags, &ex);
+	folder_info = camel_store_get_folder_info (
+		store, folder->full_name,
+		CAMEL_STORE_FOLDER_INFO_RECURSIVE |
+		CAMEL_STORE_FOLDER_INFO_FAST, &ex);
 
 	if (camel_exception_is_set (&ex))
-		goto out;
+		goto exit;
 
-	if (info && (info->child || info->next))
+	if (scan_folder_tree_for_unread (folder_uri) > 1)
 		response = prompt_user ();
 	else
 		response = GTK_RESPONSE_NO;
@@ -268,58 +368,10 @@ mar_got_folder (gchar *uri,
 	if (response == GTK_RESPONSE_NO)
 		mark_all_as_read (folder);
 	else if (response == GTK_RESPONSE_YES)
-		mar_all_sub_folders (store, info, &ex);
-out:
-	camel_store_free_folder_info(store, info);
-}
-
-static void
-has_unread_mail (GtkTreeModel *model,
-                 GtkTreeIter *parent,
-                 gboolean is_root,
-                 gboolean *has_unread,
-                 gboolean *applicable)
-{
-	guint unread = 0;
-	GtkTreeIter iter, child;
-
-	g_return_if_fail (model != NULL);
-	g_return_if_fail (parent != NULL);
-	g_return_if_fail (has_unread != NULL);
-	g_return_if_fail (applicable != NULL);
+		mar_all_sub_folders (store, folder_info, &ex);
 
-	if (is_root) {
-		gboolean is_draft = FALSE, is_store = FALSE;
-
-		gtk_tree_model_get (model, parent,
-			COL_UINT_UNREAD, &unread,
-			COL_BOOL_IS_STORE, &is_store,
-			COL_BOOL_IS_DRAFT, &is_draft,
-			-1);
-
-		*has_unread = *has_unread || (unread > 0 && unread != ~((guint)0));
-		*applicable = !is_store && !is_draft;
-
-		if (*has_unread)
-			return;
-
-		if (!gtk_tree_model_iter_children (model, &iter, parent))
-			return;
-	} else {
-		iter = *parent;
-	}
-
-	do {
-		gtk_tree_model_get (model, &iter, COL_UINT_UNREAD, &unread, -1);
-
-		*has_unread = *has_unread || (unread > 0 && unread != ~((guint)0));
-		if (*has_unread)
-			break;
-
-		if (gtk_tree_model_iter_children (model, &child, &iter))
-			has_unread_mail (model, &child, FALSE, has_unread, applicable);
-
-	} while (gtk_tree_model_iter_next (model, &iter) && !*has_unread);
+exit:
+	camel_store_free_folder_info (store, folder_info);
 }
 
 static void
@@ -336,10 +388,11 @@ action_mail_mark_read_recursive_cb (GtkAction *action,
 	g_return_if_fail (folder_uri != NULL);
 
 	mail_get_folder (
-		folder_uri, 0, mar_got_folder, NULL, mail_msg_unordered_push);
+		folder_uri, 0, mar_got_folder,
+		NULL, mail_msg_unordered_push);
 
-	g_free (folder_uri);
 	g_object_unref (folder_tree);
+	g_free (folder_uri);
 }
 
 static GtkActionEntry entries[] = {
@@ -357,56 +410,30 @@ update_actions_cb (EShellView *shell_view,
                    gpointer user_data)
 {
 	GtkActionGroup *action_group;
-	EShellWindow *shell_window;
-	GtkAction *action;
 	EShellSidebar *shell_sidebar;
+	EShellWindow *shell_window;
 	EMFolderTree *folder_tree;
+	GtkAction *action;
 	gchar *folder_uri;
-	gboolean has_unread = FALSE;
-	gboolean applicable = FALSE;
 	gboolean visible;
 
 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
 
-	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
-	g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
-	folder_uri = em_folder_tree_get_selected_uri (folder_tree);
-
-	if (folder_uri != NULL) {
-		EMFolderTreeModel *model;
-
-		model = em_folder_tree_model_get_default ();
-		if (model) {
-			GtkTreeRowReference *reference;
-
-			reference = em_folder_tree_model_lookup_uri (
-				model, folder_uri);
-			if (reference != NULL) {
-				GtkTreePath *path;
-				GtkTreeIter iter;
-
-				path = gtk_tree_row_reference_get_path (reference);
-				gtk_tree_model_get_iter (
-					GTK_TREE_MODEL (model), &iter, path);
-				has_unread_mail (
-					GTK_TREE_MODEL (model), &iter,
-					TRUE, &has_unread, &applicable);
-				gtk_tree_path_free (path);
-			}
-		}
-	}
-
 	shell_window = e_shell_view_get_shell_window (shell_view);
 	action_group = e_shell_window_get_action_group (shell_window, "mail");
 
 	action = gtk_action_group_get_action (action_group, entries[0].name);
 	g_return_if_fail (action != NULL);
 
-	visible = has_unread && applicable;
+	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
+	g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
+	folder_uri = em_folder_tree_get_selected_uri (folder_tree);
+
+	visible = (scan_folder_tree_for_unread (folder_uri) > 0);
 	gtk_action_set_visible (action, visible);
 
-	g_free (folder_uri);
 	g_object_unref (folder_tree);
+	g_free (folder_uri);
 }
 
 gboolean



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