[evolution] Bug 773038 - Correct unread message indicator for collapsed stores



commit 4ac1c705459da624379785a90916df7d41ea6e0d
Author: Milan Crha <mcrha redhat com>
Date:   Wed Jan 18 19:28:45 2017 +0100

    Bug 773038 - Correct unread message indicator for collapsed stores

 src/libemail-engine/e-mail-utils.c |  103 ++++++++++++++++++++++++++++--------
 src/libemail-engine/e-mail-utils.h |    3 +
 src/mail/em-folder-tree-model.c    |   98 ++++++++--------------------------
 src/mail/em-folder-tree-model.h    |    3 -
 src/mail/em-folder-tree.c          |   44 ++++++++++++++-
 5 files changed, 149 insertions(+), 102 deletions(-)
---
diff --git a/src/libemail-engine/e-mail-utils.c b/src/libemail-engine/e-mail-utils.c
index 888f420..9be8b04 100644
--- a/src/libemail-engine/e-mail-utils.c
+++ b/src/libemail-engine/e-mail-utils.c
@@ -48,6 +48,41 @@
 
 #define d(x)
 
+static gboolean
+e_mail_utils_folder_uri_is_drafts (ESourceRegistry *registry,
+                                  CamelSession *session,
+                                  const gchar *folder_uri)
+{
+       GList *sources, *link;
+       gboolean is_drafts = FALSE;
+
+       g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
+       g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE);
+       g_return_val_if_fail (folder_uri != NULL, FALSE);
+
+       sources = e_source_registry_list_sources (registry, E_SOURCE_EXTENSION_MAIL_COMPOSITION);
+
+       for (link = sources; link; link = g_list_next (link)) {
+               ESource *source = E_SOURCE (link->data);
+               ESourceMailComposition *extension;
+               const gchar *drafts_folder_uri;
+
+               extension = e_source_get_extension (source, E_SOURCE_EXTENSION_MAIL_COMPOSITION);
+
+               drafts_folder_uri = e_source_mail_composition_get_drafts_folder (extension);
+
+               if (drafts_folder_uri != NULL)
+                       is_drafts = e_mail_folder_uri_equal (session, folder_uri, drafts_folder_uri);
+
+               if (is_drafts)
+                       break;
+       }
+
+       g_list_free_full (sources, g_object_unref);
+
+       return is_drafts;
+}
+
 /**
  * em_utils_folder_is_drafts:
  * @registry: an #ESourceRegistry
@@ -64,10 +99,8 @@ em_utils_folder_is_drafts (ESourceRegistry *registry,
        CamelFolder *local_drafts_folder;
        CamelSession *session;
        CamelStore *store;
-       GList *list, *iter;
        gchar *folder_uri;
        gboolean is_drafts = FALSE;
-       const gchar *extension_name;
 
        g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
 
@@ -85,33 +118,59 @@ em_utils_folder_is_drafts (ESourceRegistry *registry,
 
        folder_uri = e_mail_folder_uri_from_folder (folder);
 
-       extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
-       list = e_source_registry_list_sources (registry, extension_name);
+       is_drafts = e_mail_utils_folder_uri_is_drafts (registry, session, folder_uri);
 
-       for (iter = list; iter != NULL; iter = g_list_next (iter)) {
-               ESource *source = E_SOURCE (iter->data);
-               ESourceExtension *extension;
-               const gchar *drafts_folder_uri;
+       g_free (folder_uri);
 
-               extension = e_source_get_extension (source, extension_name);
+exit:
+       g_object_unref (session);
 
-               drafts_folder_uri =
-                       e_source_mail_composition_get_drafts_folder (
-                       E_SOURCE_MAIL_COMPOSITION (extension));
+       return is_drafts;
+}
 
-               if (drafts_folder_uri != NULL)
-                       is_drafts = e_mail_folder_uri_equal (
-                               session, folder_uri, drafts_folder_uri);
+/**
+ * em_utils_folder_name_is_drafts:
+ * @registry: an #ESourceRegistry
+ * @store: a #CamelStore
+ * @folder_name: a folder name
+ *
+ * Decides if @folder_name of the @store is a Drafts folder.
+ *
+ * Returns %TRUE if this is a Drafts folder or %FALSE otherwise.
+ *
+ * Since: 3.24
+ **/
+gboolean
+em_utils_folder_name_is_drafts (ESourceRegistry *registry,
+                               CamelStore *store,
+                               const gchar *folder_name)
+{
+       CamelSession *session;
+       CamelFolder *local_drafts_folder;
+       gchar *folder_uri, *local_drafts_uri;
+       gboolean is_drafts;
 
-               if (is_drafts)
-                       break;
-       }
+       g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (folder_name != NULL, FALSE);
 
-       g_list_free_full (list, (GDestroyNotify) g_object_unref);
-       g_free (folder_uri);
+       folder_uri = e_mail_folder_uri_build (store, folder_name);
+       g_return_val_if_fail (folder_uri != NULL, FALSE);
 
-exit:
-       g_object_unref (session);
+       session = camel_service_ref_session (CAMEL_SERVICE (store));
+
+       local_drafts_folder =
+               e_mail_session_get_local_folder (
+               E_MAIL_SESSION (session), E_MAIL_LOCAL_FOLDER_DRAFTS);
+
+       local_drafts_uri = e_mail_folder_uri_from_folder (local_drafts_folder);
+
+       is_drafts = g_strcmp0 (local_drafts_uri, folder_uri) == 0 ||
+               e_mail_utils_folder_uri_is_drafts (registry, session, folder_uri);
+
+       g_clear_object (&session);
+       g_free (local_drafts_uri);
+       g_free (folder_uri);
 
        return is_drafts;
 }
diff --git a/src/libemail-engine/e-mail-utils.h b/src/libemail-engine/e-mail-utils.h
index ac90883..48f9de7 100644
--- a/src/libemail-engine/e-mail-utils.h
+++ b/src/libemail-engine/e-mail-utils.h
@@ -33,6 +33,9 @@ typedef void  (*EMailUtilsSortSourcesFunc)    (GList **psources,
 
 gboolean       em_utils_folder_is_drafts       (ESourceRegistry *registry,
                                                 CamelFolder *folder);
+gboolean       em_utils_folder_name_is_drafts  (ESourceRegistry *registry,
+                                                CamelStore *store,
+                                                const gchar *folder_name);
 gboolean       em_utils_folder_is_templates    (ESourceRegistry *registry,
                                                 CamelFolder *folder);
 gboolean       em_utils_folder_is_sent         (ESourceRegistry *registry,
diff --git a/src/mail/em-folder-tree-model.c b/src/mail/em-folder-tree-model.c
index 2d76046..a1d4a60 100644
--- a/src/mail/em-folder-tree-model.c
+++ b/src/mail/em-folder-tree-model.c
@@ -800,6 +800,7 @@ folder_tree_model_set_unread_count (EMFolderTreeModel *model,
        GtkTreeIter iter;
        StoreInfo *si;
        guint old_unread = 0;
+       gboolean unread_increased = FALSE, is_drafts = FALSE;
 
        g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model));
        g_return_if_fail (CAMEL_IS_STORE (store));
@@ -828,6 +829,8 @@ folder_tree_model_set_unread_count (EMFolderTreeModel *model,
 
                        saved_fu_info = g_hash_table_lookup (si->full_hash_unread, full);
 
+                       unread_increased = unread > saved_fu_info->unread;
+
                        fu_info->unread_last_sel = MIN (saved_fu_info->unread_last_sel, unread);
                        fu_info->is_drafts = saved_fu_info->is_drafts;
                        fu_info->fi_flags = saved_fu_info->fi_flags;
@@ -841,6 +844,8 @@ folder_tree_model_set_unread_count (EMFolderTreeModel *model,
                        if (folder) {
                                fu_info->is_drafts = em_utils_folder_is_drafts (e_mail_session_get_registry 
(model->priv->session), folder);
                                g_object_unref (folder);
+                       } else {
+                               fu_info->is_drafts = em_utils_folder_name_is_drafts 
(e_mail_session_get_registry (model->priv->session), store, full);
                        }
 
                        if (!mail_folder_cache_get_folder_info_flags (folder_cache, store, full, &flags))
@@ -849,6 +854,8 @@ folder_tree_model_set_unread_count (EMFolderTreeModel *model,
                        fu_info->fi_flags = flags;
                }
 
+               is_drafts = fu_info->is_drafts;
+
                g_hash_table_insert (si->full_hash_unread, g_strdup (full), fu_info);
 
                goto exit;
@@ -860,7 +867,11 @@ folder_tree_model_set_unread_count (EMFolderTreeModel *model,
 
        gtk_tree_model_get (
                tree_model, &iter,
-               COL_UINT_UNREAD_LAST_SEL, &old_unread, -1);
+               COL_UINT_UNREAD_LAST_SEL, &old_unread,
+               COL_BOOL_IS_DRAFT, &is_drafts,
+               -1);
+
+       unread_increased = unread > old_unread;
 
        gtk_tree_store_set (
                GTK_TREE_STORE (model), &iter,
@@ -878,6 +889,18 @@ folder_tree_model_set_unread_count (EMFolderTreeModel *model,
        }
 
 exit:
+       if (unread_increased && !is_drafts && gtk_tree_row_reference_valid (si->row)) {
+               path = gtk_tree_row_reference_get_path (si->row);
+               gtk_tree_model_get_iter (tree_model, &iter, path);
+               gtk_tree_path_free (path);
+
+               gtk_tree_store_set (
+                       GTK_TREE_STORE (model), &iter,
+                       COL_UINT_UNREAD, 0,
+                       COL_UINT_UNREAD_LAST_SEL, 1,
+                       -1);
+       }
+
        store_info_unref (si);
 }
 
@@ -1923,76 +1946,3 @@ em_folder_tree_model_user_marked_unread (EMFolderTreeModel *model,
                COL_UINT_UNREAD_LAST_SEL, unread,
                COL_UINT_UNREAD, unread, -1);
 }
-
-static gboolean
-folder_tree_model_eval_children_has_unread_mismatch (GtkTreeModel *model,
-                                                    GtkTreeIter *root)
-{
-       guint unread, unread_last_sel;
-       GtkTreeIter iter;
-
-       if (!gtk_tree_model_iter_children (model, &iter, root))
-               return FALSE;
-
-       do {
-               gtk_tree_model_get (model, &iter,
-                       COL_UINT_UNREAD, &unread,
-                       COL_UINT_UNREAD_LAST_SEL, &unread_last_sel,
-                       -1);
-
-               if (unread != ~0 && unread > unread_last_sel)
-                       return TRUE;
-
-               if (gtk_tree_model_iter_has_child (model, &iter))
-                       if (folder_tree_model_eval_children_has_unread_mismatch (model, &iter))
-                               return TRUE;
-       } while (gtk_tree_model_iter_next (model, &iter));
-
-       return FALSE;
-}
-
-gboolean
-em_folder_tree_model_has_unread_mismatch (GtkTreeModel *model,
-                                         GtkTreeIter *store_iter)
-{
-       StoreInfo *si;
-       CamelStore *store = NULL;
-       gboolean is_store = FALSE;
-       gboolean has_unread_mismatch = FALSE;
-
-       g_return_val_if_fail (EM_IS_FOLDER_TREE_MODEL (model), FALSE);
-       g_return_val_if_fail (store_iter != NULL, FALSE);
-
-       gtk_tree_model_get (model, store_iter,
-               COL_BOOL_IS_STORE, &is_store,
-               COL_OBJECT_CAMEL_STORE, &store,
-               -1);
-
-       if (is_store) {
-               si = folder_tree_model_store_index_lookup (EM_FOLDER_TREE_MODEL (model), store);
-               if (si) {
-                       GHashTableIter hash_iter;
-                       gpointer value;
-
-                       g_hash_table_iter_init (&hash_iter, si->full_hash_unread);
-                       while (g_hash_table_iter_next (&hash_iter, NULL, &value)) {
-                               FolderUnreadInfo *fu_info = value;
-
-                               if (fu_info && !fu_info->is_drafts && (fu_info->fi_flags & 
CAMEL_FOLDER_VIRTUAL) == 0 &&
-                                   fu_info->unread > fu_info->unread_last_sel) {
-                                       has_unread_mismatch = TRUE;
-                                       break;
-                               }
-                       }
-
-                       store_info_unref (si);
-               }
-
-               has_unread_mismatch = has_unread_mismatch ||
-                       folder_tree_model_eval_children_has_unread_mismatch (model, store_iter);
-       }
-
-       g_clear_object (&store);
-
-       return has_unread_mismatch;
-}
diff --git a/src/mail/em-folder-tree-model.h b/src/mail/em-folder-tree-model.h
index e04f5b5..325e3a5 100644
--- a/src/mail/em-folder-tree-model.h
+++ b/src/mail/em-folder-tree-model.h
@@ -146,9 +146,6 @@ void                em_folder_tree_model_user_marked_unread
                                        (EMFolderTreeModel *model,
                                         CamelFolder *folder,
                                         guint n_marked);
-gboolean       em_folder_tree_model_has_unread_mismatch
-                                       (GtkTreeModel *model,
-                                        GtkTreeIter *store_iter);
 
 G_END_DECLS
 
diff --git a/src/mail/em-folder-tree.c b/src/mail/em-folder-tree.c
index 5f3d662..8117227 100644
--- a/src/mail/em-folder-tree.c
+++ b/src/mail/em-folder-tree.c
@@ -749,12 +749,43 @@ folder_tree_render_store_icon (GtkTreeViewColumn *column,
        g_object_get (text_renderer, "is-expanded", &expanded, NULL);
 
        /* The second prerequisite: it's not expanded and children has unread mismatch. */
-       if (!expanded)
-               children_has_unread_mismatch = em_folder_tree_model_has_unread_mismatch (model, iter);
+       if (!expanded) {
+               guint unread, unread_last_sel;
+
+               gtk_tree_model_get (model, iter,
+                       COL_UINT_UNREAD, &unread,
+                       COL_UINT_UNREAD_LAST_SEL, &unread_last_sel,
+                       -1);
+
+               children_has_unread_mismatch = unread != unread_last_sel;
+       }
 
        g_object_set (renderer, "visible", !expanded && children_has_unread_mismatch, NULL);
 }
 
+static void
+folder_tree_reset_store_unread_value_cb (GtkTreeView *tree_view,
+                                        GtkTreeIter *iter,
+                                        GtkTreePath *path,
+                                        gpointer user_data)
+{
+       GtkTreeIter parent;
+       GtkTreeModel *model;
+
+       g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
+
+       model = gtk_tree_view_get_model (tree_view);
+       if (!model)
+               return;
+
+       if (!gtk_tree_model_iter_parent (model, &parent, iter)) {
+               gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+                       COL_UINT_UNREAD_LAST_SEL, 0,
+                       COL_UINT_UNREAD, 0,
+                       -1);
+       }
+}
+
 static gboolean
 subdirs_contain_unread (GtkTreeModel *model,
                         GtkTreeIter *root)
@@ -972,10 +1003,11 @@ folder_tree_selection_changed_cb (EMFolderTree *folder_tree,
                COL_UINT_UNREAD_LAST_SEL, &old_unread, -1);
 
        /* Sync unread counts to distinguish new incoming mail. */
-       if (unread != old_unread)
+       if (unread != old_unread) {
                gtk_tree_store_set (
                        GTK_TREE_STORE (model), &iter,
                        COL_UINT_UNREAD_LAST_SEL, unread, -1);
+       }
 
 exit:
        g_signal_emit (
@@ -1351,6 +1383,12 @@ folder_tree_constructed (GObject *object)
 
        folder_tree_copy_state (EM_FOLDER_TREE (object));
        gtk_widget_show (GTK_WIDGET (object));
+
+       g_signal_connect (tree_view, "row-expanded",
+               G_CALLBACK (folder_tree_reset_store_unread_value_cb), NULL);
+
+       g_signal_connect (tree_view, "row-collapsed",
+               G_CALLBACK (folder_tree_reset_store_unread_value_cb), NULL);
 }
 
 static gboolean


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