# HG changeset patch
# Node ID 65a48275f7f8b62456999f98111c5ec2ad3f8498
# Parent  ad73c9be8cb1b01410140d327d2ddd5d6288db8f
diff --git a/libpurple/purpleconversationmember.c b/libpurple/purpleconversationmember.c
--- a/libpurple/purpleconversationmember.c
+++ b/libpurple/purpleconversationmember.c
@@ -28,6 +28,7 @@
 struct _PurpleConversationMember {
 	GObject parent;
 
+	char *alias;
 	PurpleBadges *badges;
 	PurpleContactInfo *contact_info;
 	PurpleTags *tags;
@@ -39,6 +40,7 @@
 
 enum {
 	PROP_0,
+	PROP_ALIAS,
 	PROP_BADGES,
 	PROP_CONTACT_INFO,
 	PROP_TAGS,
@@ -120,6 +122,10 @@
 	PurpleConversationMember *member = PURPLE_CONVERSATION_MEMBER(obj);
 
 	switch(param_id) {
+	case PROP_ALIAS:
+		g_value_set_string(value,
+		                   purple_conversation_member_get_alias(member));
+		break;
 	case PROP_BADGES:
 		g_value_set_object(value,
 		                   purple_conversation_member_get_badges(member));
@@ -157,6 +163,10 @@
 	PurpleConversationMember *member = PURPLE_CONVERSATION_MEMBER(obj);
 
 	switch(param_id) {
+	case PROP_ALIAS:
+		purple_conversation_member_set_alias(member,
+		                                     g_value_get_string(value));
+		break;
 	case PROP_CONTACT_INFO:
 		purple_conversation_member_set_contact_info(member,
 		                                            g_value_get_object(value));
@@ -191,6 +201,7 @@
 purple_conversation_member_finalize(GObject *obj) {
 	PurpleConversationMember *member = PURPLE_CONVERSATION_MEMBER(obj);
 
+	g_clear_pointer(&member->alias, g_free);
 	g_clear_object(&member->badges);
 	g_clear_object(&member->tags);
 	g_clear_pointer(&member->nickname, g_free);
@@ -214,6 +225,21 @@
 	obj_class->set_property = purple_conversation_member_set_property;
 
 	/**
+	 * PurpleConversationMember:alias:
+	 *
+	 * The alias of a member.
+	 *
+	 * The alias is set by a libpurple user and could potentially be stored
+	 * server side.
+	 *
+	 * Since: 3.0
+	 */
+	properties[PROP_ALIAS] = g_param_spec_string(
+		"alias", NULL, NULL,
+		NULL,
+		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+	/**
 	 * PurpleConversationMember:badges:
 	 *
 	 * The badges for the member.
@@ -307,6 +333,29 @@
 		NULL);
 }
 
+const char *
+purple_conversation_member_get_alias(PurpleConversationMember *member) {
+	g_return_val_if_fail(PURPLE_IS_CONVERSATION_MEMBER(member), NULL);
+
+	return member->alias;
+}
+
+void
+purple_conversation_member_set_alias(PurpleConversationMember *member,
+                                     const char *alias)
+{
+	g_return_if_fail(PURPLE_IS_CONVERSATION_MEMBER(member));
+
+	if(g_set_str(&member->alias, alias)) {
+		GObject *obj = G_OBJECT(member);
+
+		g_object_freeze_notify(obj);
+		g_object_notify_by_pspec(obj, properties[PROP_ALIAS]);
+		g_object_notify_by_pspec(obj, properties[PROP_NAME_FOR_DISPLAY]);
+		g_object_thaw_notify(obj);
+	}
+}
+
 PurpleBadges *
 purple_conversation_member_get_badges(PurpleConversationMember *member) {
 	g_return_val_if_fail(PURPLE_IS_CONVERSATION_MEMBER(member), NULL);
@@ -395,6 +444,10 @@
 {
 	g_return_val_if_fail(PURPLE_IS_CONVERSATION_MEMBER(member), NULL);
 
+	if(!purple_strempty(member->alias)) {
+		return member->alias;
+	}
+
 	if(!purple_strempty(member->nickname)) {
 		return member->nickname;
 	}
diff --git a/libpurple/purpleconversationmember.h b/libpurple/purpleconversationmember.h
--- a/libpurple/purpleconversationmember.h
+++ b/libpurple/purpleconversationmember.h
@@ -75,6 +75,29 @@
 PurpleConversationMember *purple_conversation_member_new(PurpleContactInfo *info);
 
 /**
+ * purple_conversation_member_get_alias:
+ *
+ * Gets the alias of a member.
+ *
+ * Returns: (nullable): The alias.
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+const char *purple_conversation_member_get_alias(PurpleConversationMember *member);
+
+/**
+ * purple_conversation_member_set_alias:
+ * @alias: (nullable): the new alias
+ *
+ * Sets the alias of a member.
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+void purple_conversation_member_set_alias(PurpleConversationMember *member, const char *alias);
+
+/**
  * purple_conversation_member_get_badges:
  * @member: The instance.
  *
diff --git a/libpurple/tests/test_conversation_member.c b/libpurple/tests/test_conversation_member.c
--- a/libpurple/tests/test_conversation_member.c
+++ b/libpurple/tests/test_conversation_member.c
@@ -61,6 +61,7 @@
 	PurpleConversationMember *member = NULL;
 	PurpleTags *tags = NULL;
 	PurpleTypingState typing_state = PURPLE_TYPING_STATE_NONE;
+	char *alias = NULL;
 	char *name_for_display = NULL;
 	char *nickname = NULL;
 
@@ -72,13 +73,16 @@
 	 */
 	member = g_object_new(
 		PURPLE_TYPE_CONVERSATION_MEMBER,
+		"alias", "pidgy1",
 		"contact-info", info,
 		"nickname", "pidgy",
 		"typing-state", PURPLE_TYPING_STATE_TYPING,
 		NULL);
 
 	/* Now use g_object_get to read all of the properties. */
-	g_object_get(member,
+	g_object_get(
+		member,
+		"alias", &alias,
 		"badges", &badges,
 		"contact-info", &info1,
 		"name-for-display", &name_for_display,
@@ -87,13 +91,16 @@
 		"typing-state", &typing_state,
 		NULL);
 
+	g_assert_cmpstr(alias, ==, "pidgy1");
+	g_clear_pointer(&alias, g_free);
+
 	g_assert_true(PURPLE_IS_BADGES(badges));
 	g_clear_object(&badges);
 
 	g_assert_true(info1 == info);
 	g_clear_object(&info1);
 
-	g_assert_cmpstr(name_for_display, ==, "pidgy");
+	g_assert_cmpstr(name_for_display, ==, "pidgy1");
 	g_clear_pointer(&name_for_display, g_free);
 
 	g_assert_cmpstr(nickname, ==, "pidgy");
@@ -129,6 +136,7 @@
 	g_assert_cmpstr(name_for_display, ==, "abc123");
 
 	/* Set the username on the contact info and make sure it propagates up. */
+	counter = 0;
 	purple_contact_info_set_username(info, "tron");
 	name_for_display = purple_conversation_member_get_name_for_display(member);
 	g_assert_cmpstr(name_for_display, ==, "tron");
@@ -137,18 +145,36 @@
 	/* Set the nickname on the conversation member and make sure that takes
 	 * precedence.
 	 */
+	counter = 0;
 	purple_conversation_member_set_nickname(member, "rinzler");
 	name_for_display = purple_conversation_member_get_name_for_display(member);
 	g_assert_cmpstr(name_for_display, ==, "rinzler");
-	g_assert_cmpuint(counter, ==, 2);
+	g_assert_cmpuint(counter, ==, 1);
+
+	/* Set the alias on the conversation member and make sure that takes
+	 * precedence.
+	 */
+	counter = 0;
+	purple_conversation_member_set_alias(member, "Alan");
+	name_for_display = purple_conversation_member_get_name_for_display(member);
+	g_assert_cmpstr(name_for_display, ==, "Alan");
+	g_assert_cmpuint(counter, ==, 1);
+
+	/* Remove the alias and verify we fall back to the nickname. */
+	counter = 0;
+	purple_conversation_member_set_alias(member, NULL);
+	name_for_display = purple_conversation_member_get_name_for_display(member);
+	g_assert_cmpstr(name_for_display, ==, "rinzler");
+	g_assert_cmpuint(counter, ==, 1);
 
 	/* Remove the nickname and verify it falls back to the value from the
 	 * contact info.
 	 */
+	counter = 0;
 	purple_conversation_member_set_nickname(member, NULL);
 	name_for_display = purple_conversation_member_get_name_for_display(member);
 	g_assert_cmpstr(name_for_display, ==, "tron");
-	g_assert_cmpuint(counter, ==, 3);
+	g_assert_cmpuint(counter, ==, 1);
 
 	g_assert_finalize_object(member);
 	g_assert_finalize_object(info);
