[evolution/wip/webkit2] Bug 752644 - Unread mail indicator next to collapsed account names
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/wip/webkit2] Bug 752644 - Unread mail indicator next to collapsed account names
- Date: Fri, 26 Feb 2016 11:19:42 +0000 (UTC)
commit c3893218cd04a10599f8f09a0a9b8102487c04b1
Author: Milan Crha <mcrha redhat com>
Date: Tue Jul 21 16:24:37 2015 +0200
Bug 752644 - Unread mail indicator next to collapsed account names
mail/em-folder-tree-model.c | 138 +++++++++++++++++++++++++++++++++++++++++--
mail/em-folder-tree-model.h | 3 +
mail/em-folder-tree.c | 39 ++++++++++++-
3 files changed, 173 insertions(+), 7 deletions(-)
---
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index ebe61b8..6bce0e9 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -65,6 +65,13 @@ struct _EMFolderTreeModelPrivate {
GMutex store_index_lock;
};
+typedef struct _FolderUnreadInfo {
+ guint unread;
+ guint unread_last_sel;
+ gboolean is_drafts;
+ guint32 fi_flags;
+} FolderUnreadInfo;
+
struct _StoreInfo {
volatile gint ref_count;
@@ -74,6 +81,10 @@ struct _StoreInfo {
/* CamelFolderInfo::full_name -> GtkTreeRowReference */
GHashTable *full_hash;
+ /* CamelFolderInfo::full_name ~> FolderUnreadInfo * - last known unread count
+ for folders which are not loaded in the tree yet */
+ GHashTable *full_hash_unread;
+
/* CamelStore signal handler IDs */
gulong folder_created_handler_id;
gulong folder_deleted_handler_id;
@@ -171,6 +182,7 @@ store_info_unref (StoreInfo *si)
g_object_unref (si->store);
gtk_tree_row_reference_free (si->row);
g_hash_table_destroy (si->full_hash);
+ g_hash_table_destroy (si->full_hash_unread);
g_slice_free (StoreInfo, si);
}
@@ -194,6 +206,8 @@ store_info_new (EMFolderTreeModel *model,
(GDestroyNotify) g_free,
(GDestroyNotify) gtk_tree_row_reference_free);
+ si->full_hash_unread = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
handler_id = g_signal_connect_data (
store, "folder-created",
G_CALLBACK (folder_tree_model_folder_created_cb),
@@ -490,8 +504,10 @@ folder_tree_model_remove_folders (EMFolderTreeModel *folder_tree_model,
COL_STRING_FULL_NAME, &full_name,
COL_BOOL_IS_STORE, &is_store, -1);
- if (full_name != NULL)
+ if (full_name != NULL) {
g_hash_table_remove (si->full_hash, full_name);
+ g_hash_table_remove (si->full_hash_unread, full_name);
+ }
gtk_tree_store_remove (GTK_TREE_STORE (model), toplevel);
@@ -773,7 +789,8 @@ static void
folder_tree_model_set_unread_count (EMFolderTreeModel *model,
CamelStore *store,
const gchar *full,
- gint unread)
+ gint unread,
+ MailFolderCache *folder_cache)
{
GtkTreeRowReference *reference;
GtkTreeModel *tree_model;
@@ -794,11 +811,47 @@ folder_tree_model_set_unread_count (EMFolderTreeModel *model,
if (si == NULL)
return;
+ tree_model = GTK_TREE_MODEL (model);
+
reference = g_hash_table_lookup (si->full_hash, full);
- if (!gtk_tree_row_reference_valid (reference))
- goto exit;
+ if (!gtk_tree_row_reference_valid (reference)) {
+ FolderUnreadInfo *fu_info;
- tree_model = GTK_TREE_MODEL (model);
+ fu_info = g_new0 (FolderUnreadInfo, 1);
+ fu_info->unread = unread;
+ fu_info->unread_last_sel = unread;
+ fu_info->is_drafts = FALSE;
+
+ if (g_hash_table_contains (si->full_hash_unread, full)) {
+ FolderUnreadInfo *saved_fu_info;
+
+ saved_fu_info = g_hash_table_lookup (si->full_hash_unread, full);
+
+ 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;
+ } else {
+ CamelFolder *folder;
+ CamelFolderInfoFlags flags;
+
+ fu_info->unread_last_sel = unread;
+
+ folder = mail_folder_cache_ref_folder (folder_cache, store, full);
+ if (folder) {
+ fu_info->is_drafts = em_utils_folder_is_drafts (e_mail_session_get_registry
(model->priv->session), folder);
+ g_object_unref (folder);
+ }
+
+ if (!mail_folder_cache_get_folder_info_flags (folder_cache, store, full, &flags))
+ flags = 0;
+
+ fu_info->fi_flags = flags;
+ }
+
+ g_hash_table_insert (si->full_hash_unread, g_strdup (full), fu_info);
+
+ goto exit;
+ }
path = gtk_tree_row_reference_get_path (reference);
gtk_tree_model_get_iter (tree_model, &iter, path);
@@ -1127,6 +1180,8 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
g_hash_table_insert (
si->full_hash, g_strdup (fi->full_name), path_row);
+ g_hash_table_remove (si->full_hash_unread, fi->full_name);
+
store_info_unref (si);
si = NULL;
@@ -1879,3 +1934,76 @@ 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/mail/em-folder-tree-model.h b/mail/em-folder-tree-model.h
index 325e3a5..e04f5b5 100644
--- a/mail/em-folder-tree-model.h
+++ b/mail/em-folder-tree-model.h
@@ -146,6 +146,9 @@ 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/mail/em-folder-tree.c b/mail/em-folder-tree.c
index 37d5792..2c8592a 100644
--- a/mail/em-folder-tree.c
+++ b/mail/em-folder-tree.c
@@ -728,6 +728,32 @@ exit:
g_clear_object (&store);
}
+static void
+folder_tree_render_store_icon (GtkTreeViewColumn *column,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer text_renderer)
+{
+ GtkTreeIter parent;
+ gboolean expanded = TRUE, children_has_unread_mismatch = FALSE;
+
+ /* The first prerequisite: it's a root node and has children. */
+ if (gtk_tree_model_iter_parent (model, &parent, iter) ||
+ !gtk_tree_model_iter_has_child (model, iter)) {
+ g_object_set (renderer, "visible", FALSE, NULL);
+ return;
+ }
+
+ 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);
+
+ g_object_set (renderer, "visible", !expanded && children_has_unread_mismatch, NULL);
+}
+
static gboolean
subdirs_contain_unread (GtkTreeModel *model,
GtkTreeIter *root)
@@ -1272,13 +1298,22 @@ folder_tree_constructed (GObject *object)
column, renderer, (GtkTreeCellDataFunc)
folder_tree_render_icon, NULL, NULL);
- renderer = gtk_cell_renderer_text_new ();
+ renderer = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (G_OBJECT (renderer), "icon-name", "mail-unread", NULL);
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+
+ priv->text_renderer = g_object_ref (gtk_cell_renderer_text_new ());
+
+ gtk_tree_view_column_set_cell_data_func (
+ column, renderer, folder_tree_render_store_icon,
+ g_object_ref (priv->text_renderer), g_object_unref);
+
+ renderer = priv->text_renderer;
g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
gtk_tree_view_column_pack_start (column, renderer, TRUE);
gtk_tree_view_column_set_cell_data_func (
column, renderer, (GtkTreeCellDataFunc)
folder_tree_render_display_name, NULL, NULL);
- priv->text_renderer = g_object_ref (renderer);
g_signal_connect_swapped (
renderer, "edited",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]