changeset 16817:56823a55581a

Rework purple_buddy_icons_find() to return a reference for the caller, which is clearer and more consistent with other functions. Also, update purple_buddy_icons_set_for_user() to behave properly when called to clear an icon that isn't already in memory.
author Richard Laager <rlaager@wiktel.com>
date Thu, 03 May 2007 21:57:49 +0000
parents 41f85148a60f
children 179e63936967
files libpurple/buddyicon.c libpurple/buddyicon.h libpurple/conversation.c libpurple/protocols/qq/buddy_info.c pidgin/gtkblist.c
diffstat 5 files changed, 57 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/buddyicon.c	Thu May 03 15:37:25 2007 +0000
+++ b/libpurple/buddyicon.c	Thu May 03 21:57:49 2007 +0000
@@ -314,9 +314,6 @@
 	if (icon == NULL)
 		icon = purple_buddy_icon_create(account, username);
 
-	/* Take a reference for the caller of this function. */
-	icon->ref_count = 1;
-
 	/* purple_buddy_icon_set_data() sets img, but it
 	 * references img first, so we need to initialize it */
 	icon->img = NULL;
@@ -514,19 +511,53 @@
                                 void *icon_data, size_t icon_len,
                                 const char *checksum)
 {
-	PurpleBuddyIcon *icon;
+	GHashTable *icon_cache;
+	PurpleBuddyIcon *icon = NULL;
 
 	g_return_if_fail(account  != NULL);
 	g_return_if_fail(username != NULL);
 
-	icon = purple_buddy_icons_find(account, username);
+	icon_cache = g_hash_table_lookup(account_cache, account);
+
+	if (icon_cache != NULL)
+		icon = g_hash_table_lookup(icon_cache, username);
 
 	if (icon != NULL)
 		purple_buddy_icon_set_data(icon, icon_data, icon_len, checksum);
 	else
 	{
-		PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len, checksum);
-		purple_buddy_icon_unref(icon);
+		if (icon_data != NULL && icon_len > 0)
+		{
+			PurpleBuddyIcon *icon = purple_buddy_icon_new(account, username, icon_data, icon_len, checksum);
+
+			/* purple_buddy_icon_new() calls
+			 * purple_buddy_icon_set_data(), which calls
+			 * purple_buddy_icon_update(), which has the buddy list
+			 * and conversations take references as appropriate.
+			 * This function doesn't return icon, so we can't
+			 * leave a reference dangling. */
+			purple_buddy_icon_unref(icon);
+		}
+		else
+		{
+			/* If the buddy list or a conversation was holding a
+			 * reference, we'd have found the icon in the cache.
+			 * Since we know we're deleting the icon, we only
+			 * need a subset of purple_buddy_icon_update(). */
+
+			GSList *buddies = purple_find_buddies(account, username);
+			while (buddies != NULL)
+			{
+				PurpleBuddy *buddy = (PurpleBuddy *)buddies->data;
+
+				unref_filename(purple_blist_node_get_string((PurpleBlistNode *)buddy, "buddy_icon"));
+				purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon");
+				purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum");
+
+				buddies = g_slist_delete_link(buddies, buddies);
+			}
+
+		}
 	}
 }
 
@@ -629,7 +660,7 @@
 		purple_buddy_icons_set_caching(caching);
 	}
 
-	return icon;
+	return purple_buddy_icon_ref(icon);
 }
 
 gboolean
--- a/libpurple/buddyicon.h	Thu May 03 15:37:25 2007 +0000
+++ b/libpurple/buddyicon.h	Thu May 03 21:57:49 2007 +0000
@@ -54,7 +54,7 @@
  * @param icon_len  The buddy icon length.
  * @param checksum  A protocol checksum from the prpl or @c NULL.
  *
- * @return The buddy icon structure.
+ * @return The buddy icon structure, with a reference for the caller.
  */
 PurpleBuddyIcon *purple_buddy_icon_new(PurpleAccount *account, const char *username,
                                        void *icon_data, size_t icon_len,
@@ -209,7 +209,8 @@
  * @param account  The account the user is on.
  * @param username The username of the user.
  *
- * @return The icon data if found, or @c NULL if not found.
+ * @return The icon (with a reference for the caller) if found, or @c NULL if
+ *         not found.
  */
 PurpleBuddyIcon *
 purple_buddy_icons_find(PurpleAccount *account, const char *username);
--- a/libpurple/conversation.c	Thu May 03 15:37:25 2007 +0000
+++ b/libpurple/conversation.c	Thu May 03 21:57:49 2007 +0000
@@ -279,7 +279,11 @@
 
 		ims = g_list_append(ims, conv);
 		if ((icon = purple_buddy_icons_find(account, name)))
+		{
 			purple_conv_im_set_icon(conv->u.im, icon);
+			/* purple_conv_im_set_icon refs the icon. */
+			purple_buddy_icon_unref(icon);
+		}
 
 		if (purple_prefs_get_bool("/purple/logging/log_ims"))
 		{
--- a/libpurple/protocols/qq/buddy_info.c	Thu May 03 15:37:25 2007 +0000
+++ b/libpurple/protocols/qq/buddy_info.c	Thu May 03 21:57:49 2007 +0000
@@ -601,11 +601,14 @@
 
 static void _qq_update_buddy_icon(PurpleAccount *account, const gchar *name, gint face)
 {
-	PurpleBuddyIcon *icon = purple_buddy_icons_find(account, name);
+	PurpleBuddy *buddy;
 	gchar *icon_num_str = face_to_icon_str(face);
-	const gchar *old_icon_num = purple_buddy_icon_get_checksum(icon);
+	const gchar *old_icon_num = NULL;
 
-	if (icon == NULL || old_icon_num == NULL ||
+	if ((buddy = purple_find_buddy(account, name)))
+		old_icon_num = purple_buddy_icons_get_checksum_for_user(buddy);
+
+	if (old_icon_num == NULL ||
 	    strcmp(icon_num_str, old_icon_num))
 	{
 		gchar *icon_path;
--- a/pidgin/gtkblist.c	Thu May 03 15:37:25 2007 +0000
+++ b/pidgin/gtkblist.c	Thu May 03 21:57:49 2007 +0000
@@ -2160,7 +2160,7 @@
 {
 	GdkPixbuf *buf, *ret = NULL;
 	GdkPixbufLoader *loader;
-	PurpleBuddyIcon *icon;
+	PurpleBuddyIcon *icon = NULL;
 	const guchar *data = NULL;
 	gsize len;
 	PurpleBuddy *buddy = NULL;
@@ -2197,9 +2197,9 @@
 	}
 
 	if (data == NULL) {
-		if (!(icon = purple_buddy_get_icon(buddy)))
-			if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name))) /* Not sure I like this...*/
-				return NULL;
+		/* Not sure I like this...*/
+		if (!(icon = purple_buddy_icons_find(buddy->account, buddy->name)))
+			return NULL;
 		data = purple_buddy_icon_get_data(icon, &len);
 
 		if(data == NULL)
@@ -2211,6 +2211,7 @@
 	gdk_pixbuf_loader_close(loader, NULL);
 
 	purple_imgstore_unref(custom_img);
+	purple_buddy_icon_unref(icon);
 
 	buf = gdk_pixbuf_loader_get_pixbuf(loader);
 	if (buf)