[evolution] EMFolderTreeModel: Give StoreInfo a reference count.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] EMFolderTreeModel: Give StoreInfo a reference count.
- Date: Tue, 19 Nov 2013 19:50:03 +0000 (UTC)
commit 988ddab407b1f6a7eb71586a7c247b60b8c1010b
Author: Matthew Barnes <mbarnes redhat com>
Date: Tue Nov 19 11:34:11 2013 -0500
EMFolderTreeModel: Give StoreInfo a reference count.
mail/em-folder-tree-model.c | 368 +++++++++++++++++++++++++------------------
1 files changed, 214 insertions(+), 154 deletions(-)
---
diff --git a/mail/em-folder-tree-model.c b/mail/em-folder-tree-model.c
index 13b5706..d3bb041 100644
--- a/mail/em-folder-tree-model.c
+++ b/mail/em-folder-tree-model.c
@@ -62,6 +62,8 @@ struct _EMFolderTreeModelPrivate {
};
struct _StoreInfo {
+ volatile gint ref_count;
+
CamelStore *store;
GtkTreeRowReference *row;
@@ -89,47 +91,144 @@ enum {
LAST_SIGNAL
};
+/* Forward Declarations */
+static void folder_tree_model_folder_created_cb
+ (CamelStore *store,
+ CamelFolderInfo *fi,
+ EMFolderTreeModel *model);
+static void folder_tree_model_folder_deleted_cb
+ (CamelStore *store,
+ CamelFolderInfo *fi,
+ EMFolderTreeModel *model);
+static void folder_tree_model_folder_renamed_cb
+ (CamelStore *store,
+ const gchar *old_name,
+ CamelFolderInfo *info,
+ EMFolderTreeModel *model);
+static void folder_tree_model_folder_info_stale_cb
+ (CamelStore *store,
+ EMFolderTreeModel *model);
+static void folder_tree_model_folder_subscribed_cb
+ (CamelStore *store,
+ CamelFolderInfo *fi,
+ EMFolderTreeModel *model);
+static void folder_tree_model_folder_unsubscribed_cb
+ (CamelStore *store,
+ CamelFolderInfo *fi,
+ EMFolderTreeModel *model);
+
static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE (EMFolderTreeModel, em_folder_tree_model, GTK_TYPE_TREE_STORE)
+static StoreInfo *
+store_info_new (EMFolderTreeModel *model,
+ CamelStore *store)
+{
+ StoreInfo *si;
+ gulong handler_id;
+
+ si = g_slice_new0 (StoreInfo);
+ si->ref_count = 1;
+ si->store = g_object_ref (store);
+
+ si->full_hash = g_hash_table_new_full (
+ (GHashFunc) g_str_hash,
+ (GEqualFunc) g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) gtk_tree_row_reference_free);
+
+ handler_id = g_signal_connect (
+ store, "folder-created",
+ G_CALLBACK (folder_tree_model_folder_created_cb), model);
+ si->folder_created_handler_id = handler_id;
+
+ handler_id = g_signal_connect (
+ store, "folder-deleted",
+ G_CALLBACK (folder_tree_model_folder_deleted_cb), model);
+ si->folder_deleted_handler_id = handler_id;
+
+ handler_id = g_signal_connect (
+ store, "folder-renamed",
+ G_CALLBACK (folder_tree_model_folder_renamed_cb), model);
+ si->folder_renamed_handler_id = handler_id;
+
+ handler_id = g_signal_connect (
+ store, "folder-info-stale",
+ G_CALLBACK (folder_tree_model_folder_info_stale_cb), model);
+ si->folder_info_stale_handler_id = handler_id;
+
+ if (CAMEL_IS_SUBSCRIBABLE (store)) {
+ handler_id = g_signal_connect (
+ store, "folder-subscribed",
+ G_CALLBACK (folder_tree_model_folder_subscribed_cb),
+ model);
+ si->folder_subscribed_handler_id = handler_id;
+
+ handler_id = g_signal_connect (
+ store, "folder-unsubscribed",
+ G_CALLBACK (folder_tree_model_folder_unsubscribed_cb),
+ model);
+ si->folder_unsubscribed_handler_id = handler_id;
+ }
+
+ return si;
+}
+
+static StoreInfo *
+store_info_ref (StoreInfo *si)
+{
+ g_return_val_if_fail (si != NULL, NULL);
+ g_return_val_if_fail (si->ref_count > 0, NULL);
+
+ g_atomic_int_inc (&si->ref_count);
+
+ return si;
+}
+
static void
-store_info_free (StoreInfo *si)
+store_info_unref (StoreInfo *si)
{
- if (si->folder_created_handler_id > 0)
- g_signal_handler_disconnect (
- si->store,
- si->folder_created_handler_id);
-
- if (si->folder_deleted_handler_id > 0)
- g_signal_handler_disconnect (
- si->store,
- si->folder_deleted_handler_id);
-
- if (si->folder_renamed_handler_id > 0)
- g_signal_handler_disconnect (
- si->store,
- si->folder_renamed_handler_id);
-
- if (si->folder_info_stale_handler_id > 0)
- g_signal_handler_disconnect (
- si->store,
- si->folder_info_stale_handler_id);
-
- if (si->folder_subscribed_handler_id > 0)
- g_signal_handler_disconnect (
- si->store,
- si->folder_subscribed_handler_id);
-
- if (si->folder_unsubscribed_handler_id > 0)
- g_signal_handler_disconnect (
- si->store,
- si->folder_unsubscribed_handler_id);
-
- g_object_unref (si->store);
- gtk_tree_row_reference_free (si->row);
- g_hash_table_destroy (si->full_hash);
- g_free (si);
+ g_return_if_fail (si != NULL);
+ g_return_if_fail (si->ref_count > 0);
+
+ if (g_atomic_int_dec_and_test (&si->ref_count)) {
+ if (si->folder_created_handler_id > 0)
+ g_signal_handler_disconnect (
+ si->store,
+ si->folder_created_handler_id);
+
+ if (si->folder_deleted_handler_id > 0)
+ g_signal_handler_disconnect (
+ si->store,
+ si->folder_deleted_handler_id);
+
+ if (si->folder_renamed_handler_id > 0)
+ g_signal_handler_disconnect (
+ si->store,
+ si->folder_renamed_handler_id);
+
+ if (si->folder_info_stale_handler_id > 0)
+ g_signal_handler_disconnect (
+ si->store,
+ si->folder_info_stale_handler_id);
+
+ if (si->folder_subscribed_handler_id > 0)
+ g_signal_handler_disconnect (
+ si->store,
+ si->folder_subscribed_handler_id);
+
+ if (si->folder_unsubscribed_handler_id > 0)
+ g_signal_handler_disconnect (
+ si->store,
+ si->folder_unsubscribed_handler_id);
+
+ g_object_unref (si->store);
+ gtk_tree_row_reference_free (si->row);
+ g_hash_table_destroy (si->full_hash);
+
+ g_slice_free (StoreInfo, si);
+ }
}
static StoreInfo *
@@ -555,9 +654,10 @@ em_folder_tree_model_init (EMFolderTreeModel *model)
GHashTable *store_index;
store_index = g_hash_table_new_full (
- g_direct_hash, g_direct_equal,
+ (GHashFunc) g_direct_hash,
+ (GEqualFunc) g_direct_equal,
(GDestroyNotify) NULL,
- (GDestroyNotify) store_info_free);
+ (GDestroyNotify) store_info_unref);
model->priv = EM_FOLDER_TREE_MODEL_GET_PRIVATE (model);
model->priv->store_index = store_index;
@@ -987,82 +1087,6 @@ em_folder_tree_model_set_folder_info (EMFolderTreeModel *model,
}
static void
-folder_tree_model_folder_subscribed_cb (CamelStore *store,
- CamelFolderInfo *fi,
- EMFolderTreeModel *model)
-{
- GtkTreeRowReference *reference;
- GtkTreeIter parent, iter;
- GtkTreePath *path;
- StoreInfo *si;
- gboolean load;
- gchar *dirname, *p;
-
- si = folder_tree_model_lookup_store_info (model, store);
- if (si == NULL)
- return;
-
- /* Make sure we don't already know about it? */
- if (g_hash_table_lookup (si->full_hash, fi->full_name))
- return;
-
- /* Get our parent folder's path. */
- dirname = g_alloca (strlen (fi->full_name) + 1);
- strcpy (dirname, fi->full_name);
- p = strrchr (dirname, '/');
- if (p == NULL) {
- /* User subscribed to a toplevel folder. */
- reference = si->row;
- } else {
- *p = 0;
- reference = g_hash_table_lookup (si->full_hash, dirname);
- }
-
- if (!gtk_tree_row_reference_valid (reference))
- return;
-
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &parent, path);
- gtk_tree_path_free (path);
-
- /* Make sure parent's subfolders have already been loaded. */
- gtk_tree_model_get (
- GTK_TREE_MODEL (model), &parent,
- COL_BOOL_LOAD_SUBDIRS, &load, -1);
- if (load)
- return;
-
- gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent);
-
- em_folder_tree_model_set_folder_info (model, &iter, store, fi, TRUE);
-}
-
-static void
-folder_tree_model_folder_unsubscribed_cb (CamelStore *store,
- CamelFolderInfo *fi,
- EMFolderTreeModel *model)
-{
- GtkTreeRowReference *reference;
- GtkTreePath *path;
- GtkTreeIter iter;
- StoreInfo *si;
-
- si = folder_tree_model_lookup_store_info (model, store);
- if (si == NULL)
- return;
-
- reference = g_hash_table_lookup (si->full_hash, fi->full_name);
- if (!gtk_tree_row_reference_valid (reference))
- return;
-
- path = gtk_tree_row_reference_get_path (reference);
- gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
- gtk_tree_path_free (path);
-
- folder_tree_model_remove_folders (model, si, &iter);
-}
-
-static void
folder_tree_model_folder_created_cb (CamelStore *store,
CamelFolderInfo *fi,
EMFolderTreeModel *model)
@@ -1158,6 +1182,82 @@ folder_tree_model_folder_info_stale_cb (CamelStore *store,
em_folder_tree_model_add_store (model, store);
}
+static void
+folder_tree_model_folder_subscribed_cb (CamelStore *store,
+ CamelFolderInfo *fi,
+ EMFolderTreeModel *model)
+{
+ GtkTreeRowReference *reference;
+ GtkTreeIter parent, iter;
+ GtkTreePath *path;
+ StoreInfo *si;
+ gboolean load;
+ gchar *dirname, *p;
+
+ si = folder_tree_model_lookup_store_info (model, store);
+ if (si == NULL)
+ return;
+
+ /* Make sure we don't already know about it? */
+ if (g_hash_table_lookup (si->full_hash, fi->full_name))
+ return;
+
+ /* Get our parent folder's path. */
+ dirname = g_alloca (strlen (fi->full_name) + 1);
+ strcpy (dirname, fi->full_name);
+ p = strrchr (dirname, '/');
+ if (p == NULL) {
+ /* User subscribed to a toplevel folder. */
+ reference = si->row;
+ } else {
+ *p = 0;
+ reference = g_hash_table_lookup (si->full_hash, dirname);
+ }
+
+ if (!gtk_tree_row_reference_valid (reference))
+ return;
+
+ path = gtk_tree_row_reference_get_path (reference);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &parent, path);
+ gtk_tree_path_free (path);
+
+ /* Make sure parent's subfolders have already been loaded. */
+ gtk_tree_model_get (
+ GTK_TREE_MODEL (model), &parent,
+ COL_BOOL_LOAD_SUBDIRS, &load, -1);
+ if (load)
+ return;
+
+ gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent);
+
+ em_folder_tree_model_set_folder_info (model, &iter, store, fi, TRUE);
+}
+
+static void
+folder_tree_model_folder_unsubscribed_cb (CamelStore *store,
+ CamelFolderInfo *fi,
+ EMFolderTreeModel *model)
+{
+ GtkTreeRowReference *reference;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ StoreInfo *si;
+
+ si = folder_tree_model_lookup_store_info (model, store);
+ if (si == NULL)
+ return;
+
+ reference = g_hash_table_lookup (si->full_hash, fi->full_name);
+ if (!gtk_tree_row_reference_valid (reference))
+ return;
+
+ path = gtk_tree_row_reference_get_path (reference);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path);
+ gtk_tree_path_free (path);
+
+ folder_tree_model_remove_folders (model, si, &iter);
+}
+
void
em_folder_tree_model_add_store (EMFolderTreeModel *model,
CamelStore *store)
@@ -1171,7 +1271,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model,
CamelURL *service_url;
StoreInfo *si;
const gchar *display_name;
- gulong handler_id;
gchar *uri;
g_return_if_fail (EM_IS_FOLDER_TREE_MODEL (model));
@@ -1219,13 +1318,8 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model,
path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
reference = gtk_tree_row_reference_new (GTK_TREE_MODEL (model), path);
- si = g_new0 (StoreInfo, 1);
- si->store = g_object_ref (store);
+ si = store_info_new (model, store);
si->row = reference; /* takes ownership */
- si->full_hash = g_hash_table_new_full (
- g_str_hash, g_str_equal,
- (GDestroyNotify) g_free,
- (GDestroyNotify) gtk_tree_row_reference_free);
g_hash_table_insert (model->priv->store_index, store, si);
/* Each store has folders, but we don't load them until
@@ -1245,40 +1339,6 @@ em_folder_tree_model_add_store (EMFolderTreeModel *model,
COL_BOOL_IS_DRAFT, FALSE,
-1);
- handler_id = g_signal_connect (
- store, "folder-created",
- G_CALLBACK (folder_tree_model_folder_created_cb), model);
- si->folder_created_handler_id = handler_id;
-
- handler_id = g_signal_connect (
- store, "folder-deleted",
- G_CALLBACK (folder_tree_model_folder_deleted_cb), model);
- si->folder_deleted_handler_id = handler_id;
-
- handler_id = g_signal_connect (
- store, "folder-renamed",
- G_CALLBACK (folder_tree_model_folder_renamed_cb), model);
- si->folder_renamed_handler_id = handler_id;
-
- handler_id = g_signal_connect (
- store, "folder-info-stale",
- G_CALLBACK (folder_tree_model_folder_info_stale_cb), model);
- si->folder_info_stale_handler_id = handler_id;
-
- if (CAMEL_IS_SUBSCRIBABLE (store)) {
- handler_id = g_signal_connect (
- store, "folder-subscribed",
- G_CALLBACK (folder_tree_model_folder_subscribed_cb),
- model);
- si->folder_subscribed_handler_id = handler_id;
-
- handler_id = g_signal_connect (
- store, "folder-unsubscribed",
- G_CALLBACK (folder_tree_model_folder_unsubscribed_cb),
- model);
- si->folder_unsubscribed_handler_id = handler_id;
- }
-
g_signal_emit (model, signals[LOADED_ROW], 0, path, &root);
gtk_tree_path_free (path);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]