[evolution] EAddressbookModel: Listen to the cache for client readonly changes.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] EAddressbookModel: Listen to the cache for client readonly changes.
- Date: Mon, 25 Feb 2013 14:27:18 +0000 (UTC)
commit 5fdcdbc7854c2e3f075619e8b34734c922167b59
Author: Matthew Barnes <mbarnes redhat com>
Date: Mon Feb 25 08:53:34 2013 -0500
EAddressbookModel: Listen to the cache for client readonly changes.
Change notifications for EClient's "readonly" property can come on any
thread. Our "notify::readonly" signal handler immediately updates the
model's editable status, which triggers GTK+ calls, which can crash the
application if we're not in the correct thread.
Connect instead to EClientCache's "client-notify" signal, which is
always emitted from EClientCache's dedicated main loop context, and
happens to be the same main loop context that GTK+ uses. It's also
less bookkeeping when the model's EBookClient gets replaced.
addressbook/gui/widgets/e-addressbook-model.c | 76 ++++++++++++++-----------
1 files changed, 43 insertions(+), 33 deletions(-)
---
diff --git a/addressbook/gui/widgets/e-addressbook-model.c b/addressbook/gui/widgets/e-addressbook-model.c
index cddbabf..00c2357 100644
--- a/addressbook/gui/widgets/e-addressbook-model.c
+++ b/addressbook/gui/widgets/e-addressbook-model.c
@@ -37,6 +37,8 @@
struct _EAddressbookModelPrivate {
EClientCache *client_cache;
+ gulong client_notify_readonly_handler_id;
+
EBookClient *book_client;
gchar *query_str;
EBookClientView *client_view;
@@ -50,7 +52,6 @@ struct _EAddressbookModelPrivate {
gulong remove_contact_id;
gulong modify_contact_id;
gulong status_message_id;
- gulong writable_status_id;
gulong view_complete_id;
guint remove_status_id;
@@ -335,14 +336,18 @@ view_complete_cb (EBookClientView *client_view,
}
static void
-readonly_cb (EBookClient *book_client,
- GParamSpec *pspec,
- EAddressbookModel *model)
+addressbook_model_client_notify_readonly_cb (EClientCache *client_cache,
+ EClient *client,
+ GParamSpec *pspec,
+ EAddressbookModel *model)
{
- gboolean editable;
+ if (!E_IS_BOOK_CLIENT (client))
+ return;
- editable = !e_client_is_readonly (E_CLIENT (book_client));
- e_addressbook_model_set_editable (model, editable);
+ if (E_BOOK_CLIENT (client) == model->priv->book_client) {
+ gboolean editable = !e_client_is_readonly (client);
+ e_addressbook_model_set_editable (model, editable);
+ }
}
static void
@@ -542,19 +547,16 @@ addressbook_model_dispose (GObject *object)
remove_book_view (model);
free_data (model);
- g_clear_object (&model->priv->client_cache);
-
- if (model->priv->book_client) {
- if (model->priv->writable_status_id)
- g_signal_handler_disconnect (
- model->priv->book_client,
- model->priv->writable_status_id);
- model->priv->writable_status_id = 0;
-
- g_object_unref (model->priv->book_client);
- model->priv->book_client = NULL;
+ if (model->priv->client_notify_readonly_handler_id > 0) {
+ g_signal_handler_disconnect (
+ model->priv->client_cache,
+ model->priv->client_notify_readonly_handler_id);
+ model->priv->client_notify_readonly_handler_id = 0;
}
+ g_clear_object (&model->priv->client_cache);
+ g_clear_object (&model->priv->book_client);
+
if (model->priv->query_str) {
g_free (model->priv->query_str);
model->priv->query_str = NULL;
@@ -578,6 +580,27 @@ addressbook_model_finalize (GObject *object)
}
static void
+addressbook_model_constructed (GObject *object)
+{
+ EAddressbookModel *model;
+ EClientCache *client_cache;
+ gulong handler_id;
+
+ model = E_ADDRESSBOOK_MODEL (object);
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_addressbook_model_parent_class)->constructed (object);
+
+ client_cache = e_addressbook_model_get_client_cache (model);
+
+ handler_id = g_signal_connect (
+ client_cache, "client-notify::readonly",
+ G_CALLBACK (addressbook_model_client_notify_readonly_cb),
+ model);
+ model->priv->client_notify_readonly_handler_id = handler_id;
+}
+
+static void
e_addressbook_model_class_init (EAddressbookModelClass *class)
{
GObjectClass *object_class;
@@ -589,6 +612,7 @@ e_addressbook_model_class_init (EAddressbookModelClass *class)
object_class->get_property = addressbook_model_get_property;
object_class->dispose = addressbook_model_dispose;
object_class->finalize = addressbook_model_finalize;
+ object_class->constructed = addressbook_model_constructed;
g_object_class_install_property (
object_class,
@@ -875,26 +899,12 @@ e_addressbook_model_set_client (EAddressbookModel *model,
if (model->priv->book_client == book_client)
return;
- if (model->priv->book_client != NULL) {
- if (model->priv->book_client == book_client)
- return;
-
- if (model->priv->writable_status_id != 0)
- g_signal_handler_disconnect (
- model->priv->book_client,
- model->priv->writable_status_id);
- model->priv->writable_status_id = 0;
-
+ if (model->priv->book_client != NULL)
g_object_unref (model->priv->book_client);
- }
model->priv->book_client = g_object_ref (book_client);
model->priv->first_get_view = TRUE;
- model->priv->writable_status_id = g_signal_connect (
- book_client, "notify::readonly",
- G_CALLBACK (readonly_cb), model);
-
editable = !e_client_is_readonly (E_CLIENT (book_client));
e_addressbook_model_set_editable (model, editable);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]