aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/mark-all-read/mark-all-read.c213
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 3923f86c2b..24bc48521a 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