diff options
author | Philip Withnall <philip.withnall@collabora.co.uk> | 2010-08-19 01:13:02 +0800 |
---|---|---|
committer | Philip Withnall <philip.withnall@collabora.co.uk> | 2010-08-19 01:55:09 +0800 |
commit | 015070caec0ec80ac53127c619bde516081670e6 (patch) | |
tree | fce9210305d5bd92578d85196671bdfb65cf93dc /libempathy-gtk | |
parent | 41c88d2a8b3670901473061dd53eb83e6f7ad34c (diff) | |
download | gsoc2013-empathy-015070caec0ec80ac53127c619bde516081670e6.tar gsoc2013-empathy-015070caec0ec80ac53127c619bde516081670e6.tar.gz gsoc2013-empathy-015070caec0ec80ac53127c619bde516081670e6.tar.bz2 gsoc2013-empathy-015070caec0ec80ac53127c619bde516081670e6.tar.lz gsoc2013-empathy-015070caec0ec80ac53127c619bde516081670e6.tar.xz gsoc2013-empathy-015070caec0ec80ac53127c619bde516081670e6.tar.zst gsoc2013-empathy-015070caec0ec80ac53127c619bde516081670e6.zip |
Allow cancellation of avatar load operations
Automatically cancel all pending avatar load operations when disposing of
an EmpathyIndividualStore. This prevents crashes when linking individuals in
the case that the EmpathyIndividualStore in the linking dialogue gets
notified of the new linked individual just before it's destroyed.
Diffstat (limited to 'libempathy-gtk')
-rw-r--r-- | libempathy-gtk/empathy-individual-store.c | 57 | ||||
-rw-r--r-- | libempathy-gtk/empathy-ui-utils.c | 7 | ||||
-rw-r--r-- | libempathy-gtk/empathy-ui-utils.h | 3 |
3 files changed, 54 insertions, 13 deletions
diff --git a/libempathy-gtk/empathy-individual-store.c b/libempathy-gtk/empathy-individual-store.c index 161787299..26b56954e 100644 --- a/libempathy-gtk/empathy-individual-store.c +++ b/libempathy-gtk/empathy-individual-store.c @@ -71,6 +71,8 @@ typedef struct guint setup_idle_id; gboolean dispose_has_run; GHashTable *status_icons; + /* List of owned GCancellables for each pending avatar load operation */ + GList *avatar_cancellables; } EmpathyIndividualStorePriv; typedef struct @@ -552,13 +554,16 @@ individual_store_contact_active_cb (ShowActiveData *data) return FALSE; } +typedef struct { + EmpathyIndividualStore *store; /* weak */ + GCancellable *cancellable; /* owned */ +} LoadAvatarData; + static void -individual_avatar_pixbuf_received_cb (GObject *object, +individual_avatar_pixbuf_received_cb (FolksIndividual *individual, GAsyncResult *result, - gpointer user_data) + LoadAvatarData *data) { - FolksIndividual *individual = FOLKS_INDIVIDUAL (object); - EmpathyIndividualStore *self = user_data; GError *error = NULL; GdkPixbuf *pixbuf; @@ -572,18 +577,32 @@ individual_avatar_pixbuf_received_cb (GObject *object, error->message); g_clear_error (&error); } - else + else if (data->store != NULL) { GList *iters, *l; - iters = individual_store_find_contact (self, individual); + iters = individual_store_find_contact (data->store, individual); for (l = iters; l; l = l->next) { - gtk_tree_store_set (GTK_TREE_STORE (self), l->data, + gtk_tree_store_set (GTK_TREE_STORE (data->store), l->data, EMPATHY_INDIVIDUAL_STORE_COL_PIXBUF_AVATAR, pixbuf, -1); } } + + /* Free things */ + if (data->store != NULL) + { + EmpathyIndividualStorePriv *priv = GET_PRIV (data->store); + + g_object_remove_weak_pointer (G_OBJECT (data->store), + (gpointer *) &data->store); + priv->avatar_cancellables = g_list_remove (priv->avatar_cancellables, + data->cancellable); + } + + g_object_unref (data->cancellable); + g_slice_free (LoadAvatarData, data); } static void @@ -604,6 +623,7 @@ individual_store_contact_update (EmpathyIndividualStore *self, gboolean do_set_refresh = FALSE; gboolean show_avatar = FALSE; GdkPixbuf *pixbuf_status; + LoadAvatarData *load_avatar_data; priv = GET_PRIV (self); @@ -678,8 +698,19 @@ individual_store_contact_update (EmpathyIndividualStore *self, show_avatar = TRUE; } - empathy_pixbuf_avatar_from_individual_scaled_async (individual, - individual_avatar_pixbuf_received_cb, 32, 32, self); + /* Load the avatar asynchronously */ + load_avatar_data = g_slice_new (LoadAvatarData); + load_avatar_data->store = self; + g_object_add_weak_pointer (G_OBJECT (self), + (gpointer *) &load_avatar_data->store); + load_avatar_data->cancellable = g_cancellable_new (); + + priv->avatar_cancellables = g_list_prepend (priv->avatar_cancellables, + load_avatar_data->cancellable); + empathy_pixbuf_avatar_from_individual_scaled_async (individual, 32, 32, + load_avatar_data->cancellable, + (GAsyncReadyCallback) individual_avatar_pixbuf_received_cb, + load_avatar_data); pixbuf_status = empathy_individual_store_get_individual_status_icon (self, individual); @@ -957,6 +988,14 @@ individual_store_dispose (GObject *object) return; priv->dispose_has_run = TRUE; + /* Cancel any pending avatar load operations */ + for (l = priv->avatar_cancellables; l != NULL; l = l->next) + { + /* The cancellables are freed in individual_avatar_pixbuf_received_cb() */ + g_cancellable_cancel (G_CANCELLABLE (l->data)); + } + g_list_free (priv->avatar_cancellables); + contacts = empathy_individual_manager_get_members (priv->manager); for (l = contacts; l; l = l->next) { diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c index 46a26d8f7..0a2d4f4f4 100644 --- a/libempathy-gtk/empathy-ui-utils.c +++ b/libempathy-gtk/empathy-ui-utils.c @@ -564,7 +564,7 @@ avatar_file_load_contents_cb (GObject *object, { GFile *file = G_FILE (object); PixbufAvatarFromIndividualClosure *closure = user_data; - char *data; + char *data = NULL; gsize data_size; struct SizeData size_data; GError *error = NULL; @@ -617,9 +617,10 @@ out: void empathy_pixbuf_avatar_from_individual_scaled_async ( FolksIndividual *individual, - GAsyncReadyCallback callback, gint width, gint height, + GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) { GFile *avatar_file; @@ -639,7 +640,7 @@ empathy_pixbuf_avatar_from_individual_scaled_async ( if (closure == NULL) goto out; - g_file_load_contents_async (avatar_file, NULL, + g_file_load_contents_async (avatar_file, cancellable, avatar_file_load_contents_cb, closure); g_object_unref (result); diff --git a/libempathy-gtk/empathy-ui-utils.h b/libempathy-gtk/empathy-ui-utils.h index 9c3ec6517..0b76d09a3 100644 --- a/libempathy-gtk/empathy-ui-utils.h +++ b/libempathy-gtk/empathy-ui-utils.h @@ -77,9 +77,10 @@ GdkPixbuf * empathy_pixbuf_from_data_and_mime (gchar *data, gsize data_size, gchar **mime_type); void empathy_pixbuf_avatar_from_individual_scaled_async (FolksIndividual *individual, - GAsyncReadyCallback callback, gint width, gint height, + GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data); GdkPixbuf * empathy_pixbuf_avatar_from_individual_scaled_finish ( FolksIndividual *individual, |