Add a property and accessor for getting the avatar to display for a PurplePerson

Fri, 10 Feb 2023 03:03:39 -0600

author
Gary Kramlich <grim@reaperworld.com>
date
Fri, 10 Feb 2023 03:03:39 -0600
changeset 42087
7aa77854392d
parent 42086
742efe62e610
child 42088
2f5bbcc91854

Add a property and accessor for getting the avatar to display for a PurplePerson

Testing Done:
Ran the unit tests and verified everything looks looks right in the contact list.

Bugs closed: PIDGIN-17735

Reviewed at https://reviews.imfreedom.org/r/2232/

libpurple/purpleperson.c file | annotate | diff | comparison | revisions
libpurple/purpleperson.h file | annotate | diff | comparison | revisions
libpurple/tests/test_person.c file | annotate | diff | comparison | revisions
pidgin/pidgincontactlist.c file | annotate | diff | comparison | revisions
--- a/libpurple/purpleperson.c	Fri Feb 10 03:00:58 2023 -0600
+++ b/libpurple/purpleperson.c	Fri Feb 10 03:03:39 2023 -0600
@@ -37,6 +37,7 @@
 	PROP_ID,
 	PROP_ALIAS,
 	PROP_AVATAR,
+	PROP_AVATAR_FOR_DISPLAY,
 	PROP_TAGS,
 	PROP_NAME_FOR_DISPLAY,
 	PROP_PRIORITY_CONTACT_INFO,
@@ -109,6 +110,14 @@
 		g_object_freeze_notify(obj);
 		g_object_notify_by_pspec(obj, properties[PROP_NAME_FOR_DISPLAY]);
 		g_object_notify_by_pspec(obj, properties[PROP_PRIORITY_CONTACT_INFO]);
+
+		/* If the person doesn't have an avatar set, notify that the
+		 * avatar-for-display has changed.
+		 */
+		if(!GDK_IS_PIXBUF(person->avatar)) {
+			g_object_notify_by_pspec(obj, properties[PROP_AVATAR_FOR_DISPLAY]);
+		}
+
 		g_object_thaw_notify(obj);
 	}
 }
@@ -182,6 +191,9 @@
 		case PROP_AVATAR:
 			g_value_set_object(value, purple_person_get_avatar(person));
 			break;
+		case PROP_AVATAR_FOR_DISPLAY:
+			g_value_set_object(value, purple_person_get_avatar_for_display(person));
+			break;
 		case PROP_TAGS:
 			g_value_set_object(value, purple_person_get_tags(person));
 			break;
@@ -315,6 +327,22 @@
 		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	/**
+	 * PurplePerson:avatar-for-display
+	 *
+	 * The avatar to show for the person. If [property@Purple.Person:avatar] is
+	 * set, it will be returned. Otherwise the value of
+	 * [property@Purple.ContactInfo:avatar] for
+	 * [property@Purple.Person:priority-contact-info] will be returned.
+	 *
+	 * Since: 3.0.0
+	 */
+	properties[PROP_AVATAR_FOR_DISPLAY] = g_param_spec_object(
+		"avatar-for-display", "avatar-for-display",
+		"The avatar to display for this person",
+		GDK_TYPE_PIXBUF,
+		G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	/**
 	 * PurplePerson:tags:
 	 *
 	 * The [class@Purple.Tags] for this person.
@@ -405,6 +433,24 @@
 }
 
 GdkPixbuf *
+purple_person_get_avatar_for_display(PurplePerson *person) {
+	PurpleContactInfo *priority = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_PERSON(person), NULL);
+
+	if(GDK_IS_PIXBUF(person->avatar)) {
+		return person->avatar;
+	}
+
+	priority = purple_person_get_priority_contact_info(person);
+	if(PURPLE_IS_CONTACT_INFO(priority)) {
+		return purple_contact_info_get_avatar(priority);
+	}
+
+	return NULL;
+}
+
+GdkPixbuf *
 purple_person_get_avatar(PurplePerson *person) {
 	g_return_val_if_fail(PURPLE_IS_PERSON(person), NULL);
 
@@ -416,7 +462,12 @@
 	g_return_if_fail(PURPLE_IS_PERSON(person));
 
 	if(g_set_object(&person->avatar, avatar)) {
-		g_object_notify_by_pspec(G_OBJECT(person), properties[PROP_AVATAR]);
+		GObject *obj = G_OBJECT(person);
+
+		g_object_freeze_notify(obj);
+		g_object_notify_by_pspec(obj, properties[PROP_AVATAR]);
+		g_object_notify_by_pspec(obj, properties[PROP_AVATAR_FOR_DISPLAY]);
+		g_object_thaw_notify(obj);
 	}
 }
 
--- a/libpurple/purpleperson.h	Fri Feb 10 03:00:58 2023 -0600
+++ b/libpurple/purpleperson.h	Fri Feb 10 03:03:39 2023 -0600
@@ -101,6 +101,21 @@
 void purple_person_set_alias(PurplePerson *person, const gchar *alias);
 
 /**
+ * purple_person_get_avatar_for_display:
+ * @person: The instance.
+ *
+ * Gets the avatar that should be displayed for @person. If @person has an
+ * avatar set, it will be returned, otherwise this will fallback to the value
+ * of [property@Purple.ContactInfo:avatar] for
+ * [property@Purple.Person:priority-contact-info].
+ *
+ * Returns: (transfer none) (nullable): The avatar to display.
+ *
+ * Since: 3.0.0
+ */
+GdkPixbuf *purple_person_get_avatar_for_display(PurplePerson *person);
+
+/**
  * purple_person_get_avatar:
  * @person: The instance.
  *
--- a/libpurple/tests/test_person.c	Fri Feb 10 03:00:58 2023 -0600
+++ b/libpurple/tests/test_person.c	Fri Feb 10 03:03:39 2023 -0600
@@ -67,6 +67,7 @@
 	PurpleTags *tags = NULL;
 	GdkPixbuf *avatar = NULL;
 	GdkPixbuf *avatar1 = NULL;
+	GdkPixbuf *avatar_for_display = NULL;
 	char *id = NULL;
 	char *alias = NULL;
 	char *name_for_display = NULL;
@@ -89,6 +90,7 @@
 		"id", &id,
 		"alias", &alias,
 		"avatar", &avatar1,
+		"avatar-for-display", &avatar_for_display,
 		"name-for-display", &name_for_display,
 		"tags", &tags,
 		NULL);
@@ -97,6 +99,7 @@
 	g_assert_nonnull(id);
 	g_assert_cmpstr(alias, ==, "alias");
 	g_assert_true(avatar1 == avatar);
+	g_assert_true(avatar1 == avatar_for_display);
 	g_assert_cmpstr(name_for_display, ==, "alias");
 	g_assert_nonnull(tags);
 
@@ -104,6 +107,7 @@
 	g_clear_pointer(&id, g_free);
 	g_clear_pointer(&alias, g_free);
 	g_clear_object(&avatar1);
+	g_clear_object(&avatar_for_display);
 	g_clear_pointer(&name_for_display, g_free);
 	g_clear_object(&tags);
 
@@ -112,6 +116,48 @@
 }
 
 static void
+test_purple_person_avatar_for_display_person(void) {
+	PurpleContactInfo *info = NULL;
+	PurplePerson *person = NULL;
+	GdkPixbuf *avatar = NULL;
+
+	person = purple_person_new();
+	avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
+	purple_person_set_avatar(person, avatar);
+
+	info = purple_contact_info_new("id");
+	purple_person_add_contact_info(person, info);
+
+	/* Make sure the person's alias is overriding the contact info. */
+	g_assert_true(purple_person_get_avatar_for_display(person) == avatar);
+
+	g_clear_object(&info);
+	g_clear_object(&person);
+	g_clear_object(&avatar);
+}
+
+static void
+test_purple_person_avatar_for_display_contact(void) {
+	PurpleContactInfo *info = NULL;
+	PurplePerson *person = NULL;
+	GdkPixbuf *avatar = NULL;
+
+	person = purple_person_new();
+
+	info = purple_contact_info_new("id");
+	avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
+	purple_contact_info_set_avatar(info, avatar);
+	purple_person_add_contact_info(person, info);
+
+	/* Make sure the person's alias is overriding the contact info. */
+	g_assert_true(purple_person_get_avatar_for_display(person) == avatar);
+
+	g_clear_object(&info);
+	g_clear_object(&person);
+	g_clear_object(&avatar);
+}
+
+static void
 test_purple_person_name_for_display_person(void) {
 	PurpleContactInfo *info = NULL;
 	PurplePerson *person = NULL;
@@ -410,6 +456,11 @@
 	g_test_add_func("/person/properties",
 	                test_purple_person_properties);
 
+	g_test_add_func("/person/avatar-for-display/person",
+	                test_purple_person_avatar_for_display_person);
+	g_test_add_func("/person/avatar-for-display/contact",
+	                test_purple_person_avatar_for_display_contact);
+
 	g_test_add_func("/person/name-for-display/person",
 	                test_purple_person_name_for_display_person);
 	g_test_add_func("/person/name-for-display/contact",
--- a/pidgin/pidgincontactlist.c	Fri Feb 10 03:00:58 2023 -0600
+++ b/pidgin/pidgincontactlist.c	Fri Feb 10 03:03:39 2023 -0600
@@ -46,6 +46,12 @@
 	PurpleContact *contact = NULL;
 	PurpleBuddyIcon *icon = NULL;
 	GdkTexture *texture = NULL;
+	GdkPixbuf *pixbuf = NULL;
+
+	pixbuf = purple_person_get_avatar_for_display(person);
+	if(GDK_IS_PIXBUF(pixbuf)) {
+		return gdk_texture_new_for_pixbuf(pixbuf);
+	}
 
 	info = purple_person_get_priority_contact_info(person);
 

mercurial