--- a/libpurple/purplecontactinfo.c Thu Jan 05 22:41:48 2023 -0600
+++ b/libpurple/purplecontactinfo.c Fri Jan 06 01:53:58 2023 -0600
@@ -22,12 +22,14 @@
+ char *name_for_display; @@ -52,6 +54,7 @@
static GParamSpec *properties[N_PROPERTIES] = {NULL, };
@@ -60,6 +63,70 @@
/******************************************************************************
+ *****************************************************************************/ +purple_contact_info_update_name_for_display(PurpleContactInfo *info) { + PurpleContactInfoPrivate *priv = NULL; + const char *name_for_display = NULL; + priv = purple_contact_info_get_instance_private(info); + /* If the info has an alias set, use it. */ + if(name_for_display == NULL && !purple_strempty(priv->alias)) { + name_for_display = priv->alias; + /* If info is associated with a PurplePerson that has an alias set, use the + * alias of that PurplePerson. + if(name_for_display == NULL && priv->person != NULL) { + const char *alias = purple_person_get_alias(priv->person); + if(!purple_strempty(alias)) { + name_for_display = alias; + /* If the info has a display name set, use it. */ + if(name_for_display == NULL && !purple_strempty(priv->display_name)) { + name_for_display = priv->display_name; + /* Fallback to the username if that is set. */ + if(name_for_display == NULL && !purple_strempty(priv->username)) { + name_for_display = priv->username; + /* Finally, in a last ditch effort, use the id of the info. */ + if(name_for_display == NULL) { + name_for_display = priv->id; + if(!purple_strequal(name_for_display, priv->name_for_display)) { + /* If we have a new name for display, free the old one, dup the new one + * into the struct, and then emit the notify signal. + g_free(priv->name_for_display); + priv->name_for_display = g_strdup(name_for_display); + g_object_notify_by_pspec(G_OBJECT(info), + properties[PROP_NAME_FOR_DISPLAY]); +/****************************************************************************** + *****************************************************************************/ +purple_contact_info_person_alias_changed_cb(G_GNUC_UNUSED GObject *obj, + G_GNUC_UNUSED GParamSpec *pspec, + purple_contact_info_update_name_for_display(data); +/****************************************************************************** *****************************************************************************/
@@ -100,6 +167,10 @@
g_value_set_enum(value, purple_contact_info_get_permission(info));
+ case PROP_NAME_FOR_DISPLAY: + g_value_set_string(value, + purple_contact_info_get_name_for_display(info)); G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -170,6 +241,7 @@
g_clear_pointer(&priv->username, g_free);
g_clear_pointer(&priv->display_name, g_free);
g_clear_pointer(&priv->alias, g_free);
+ g_clear_pointer(&priv->name_for_display, g_free); G_OBJECT_CLASS(purple_contact_info_parent_class)->finalize(obj);
@@ -187,6 +259,8 @@
purple_contact_info_set_id(info, NULL);
+ purple_contact_info_update_name_for_display(info); @@ -348,6 +422,33 @@
PURPLE_CONTACT_INFO_PERMISSION_UNSET,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ * PurpleContactInfo:name-for-display: + * The name that the user interface should display for this contact info. + * This will first check [property@Purple.ContactInfo:alias] and return + * Next, if the [property@Purple.ContactInfo:person] points to a valid + * [class@Purple.Person], the alias of [class@Purple.Person] will be + * returned if it is set. + * Otherwise, this will be set to the first set property from the following + * * [property@Purple.ContactInfo:display-name] + * * [property@Purple.ContactInfo:username] + * * [property@Purple.ContactInfo:id] + properties[PROP_NAME_FOR_DISPLAY] = g_param_spec_string( + "name-for-display", "name-for-display", + "The name that should be displayed for the contact info", + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
@@ -376,15 +477,26 @@
purple_contact_info_set_id(PurpleContactInfo *info, const gchar *id) {
PurpleContactInfoPrivate *priv = NULL;
+ gboolean changed = FALSE; g_return_if_fail(PURPLE_IS_CONTACT_INFO(info));
priv = purple_contact_info_get_instance_private(info);
+ changed = !purple_strequal(priv->id, id); - g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_ID]);
+ g_object_freeze_notify(G_OBJECT(info)); + g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_ID]); + purple_contact_info_update_name_for_display(info); + g_object_thaw_notify(G_OBJECT(info)); @@ -403,15 +515,26 @@
PurpleContactInfoPrivate *priv = NULL;
+ gboolean changed = FALSE; g_return_if_fail(PURPLE_IS_CONTACT_INFO(info));
priv = purple_contact_info_get_instance_private(info);
+ changed = !purple_strequal(priv->username, username); priv->username = g_strdup(username);
- g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_USERNAME]);
+ g_object_freeze_notify(G_OBJECT(info)); + g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_USERNAME]); + purple_contact_info_update_name_for_display(info); + g_object_thaw_notify(G_OBJECT(info)); @@ -430,15 +553,26 @@
const gchar *display_name)
PurpleContactInfoPrivate *priv = NULL;
+ gboolean changed = FALSE; g_return_if_fail(PURPLE_IS_CONTACT_INFO(info));
priv = purple_contact_info_get_instance_private(info);
+ changed = !purple_strequal(priv->display_name, display_name); g_free(priv->display_name);
priv->display_name = g_strdup(display_name);
- g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_DISPLAY_NAME]);
+ g_object_freeze_notify(G_OBJECT(info)); + g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_DISPLAY_NAME]); + purple_contact_info_update_name_for_display(info); + g_object_thaw_notify(G_OBJECT(info)); @@ -455,15 +589,26 @@
purple_contact_info_set_alias(PurpleContactInfo *info, const gchar *alias) {
PurpleContactInfoPrivate *priv = NULL;
+ gboolean changed = FALSE; g_return_if_fail(PURPLE_IS_CONTACT_INFO(info));
priv = purple_contact_info_get_instance_private(info);
+ changed = !purple_strequal(priv->alias, alias); priv->alias = g_strdup(alias);
- g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_ALIAS]);
+ g_object_freeze_notify(G_OBJECT(info)); + g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_ALIAS]); + purple_contact_info_update_name_for_display(info); + g_object_thaw_notify(G_OBJECT(info)); @@ -548,7 +693,26 @@
priv = purple_contact_info_get_instance_private(info);
if(g_set_object(&priv->person, person)) {
+ /* If we got a new person, we need to connect to the notify::alias + if(PURPLE_IS_PERSON(priv->person)) { + g_signal_connect_object(priv->person, "notify::alias", + G_CALLBACK(purple_contact_info_person_alias_changed_cb), + /* Freeze notifications as the person update could change the + * name-for-display property. + g_object_freeze_notify(G_OBJECT(info)); g_object_notify_by_pspec(G_OBJECT(info), properties[PROP_PERSON]);
+ /* Update the name-for-display property */ + purple_contact_info_update_name_for_display(info); + g_object_thaw_notify(G_OBJECT(info)); @@ -598,34 +762,7 @@
priv = purple_contact_info_get_instance_private(info);
- /* If info is associated with a PurplePerson that has an alias set,
- * return the alias of that PurplePerson.
- if(priv->person != NULL) {
- const char *alias = purple_person_get_alias(priv->person);
- if(alias != NULL && alias[0] != '\0') {
- /* If the purple user set an alias for the info, return that. */
- if(priv->alias != NULL && priv->alias[0] != '\0') {
- /* If the info has a display name set, return that. */
- if(priv->display_name != NULL && priv->display_name[0] != '\0') {
- return priv->display_name;
- /* Fallback to the username if that is set. */
- if(priv->username != NULL && priv->username[0] != '\0') {
- /* Finally, in a last ditch effort, return the id of the info. */
+ return priv->name_for_display; --- a/libpurple/purplecontactinfo.h Thu Jan 05 22:41:48 2023 -0600
+++ b/libpurple/purplecontactinfo.h Fri Jan 06 01:53:58 2023 -0600
@@ -332,17 +332,8 @@
* purple_contact_info_get_name_for_display:
- * Gets the name that should be displayed for @info.
- * If @info is associated with a [class@Purple.Person], the value of
- * [property@Purple.Person:alias] will be returned if it is set.
- * Otherwise, this will return the first set property from the following list:
- * * [property@Purple.ContactInfo:alias]
- * * [property@Purple.ContactInfo:display-name]
- * * [property@Purple.ContactInfo:username]
- * * [property@Purple.ContactInfo:id]
+ * Gets the name that should be displayed for @info. See + * [property@Purple.ContactInfo:name-for-display] for more information. * Returns: (transfer none): The name to display for @info.
--- a/libpurple/tests/test_contact_info.c Thu Jan 05 22:41:48 2023 -0600
+++ b/libpurple/tests/test_contact_info.c Fri Jan 06 01:53:58 2023 -0600
@@ -46,11 +46,12 @@
GdkPixbuf *avatar = NULL;
GdkPixbuf *avatar1 = NULL;
- gchar *username = NULL;
- gchar *display_name = NULL;
+ char *display_name = NULL; + char *name_for_display = NULL; avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
person = purple_person_new();
@@ -83,6 +84,7 @@
"permission", &permission,
+ "name-for-display", &name_for_display, /* Compare all the things. */
@@ -91,6 +93,7 @@
g_assert_cmpstr(display_name, ==, "display-name");
g_assert_cmpstr(alias, ==, "alias");
g_assert_cmpstr(color, ==, "#e9c636");
+ g_assert_cmpstr(name_for_display, ==, "alias"); g_assert_true(avatar1 == avatar);
g_assert_nonnull(presence1);
@@ -103,6 +106,7 @@
g_clear_pointer(&display_name, g_free);
g_clear_pointer(&alias, g_free);
g_clear_pointer(&color, g_free);
+ g_clear_pointer(&name_for_display, g_free); g_clear_object(&avatar1);
g_clear_object(&presence1);
@@ -123,13 +127,18 @@
const char *alias = NULL;
person = purple_person_new();
- purple_person_set_alias(person, "this is the alias");
+ purple_person_set_alias(person, "person alias"); - info = purple_contact_info_new(NULL);
+ info = purple_contact_info_new("id"); + /* we don't set the alias on the contact info, as that takes priority over + purple_contact_info_set_username(info, "username"); + purple_contact_info_set_display_name(info, "display name"); purple_contact_info_set_person(info, person);
alias = purple_contact_info_get_name_for_display(info);
- g_assert_cmpstr(alias, ==, "this is the alias");
+ g_assert_cmpstr(alias, ==, "person alias"); @@ -142,14 +151,17 @@
const char *alias = NULL;
person = purple_person_new();
+ purple_person_set_alias(person, "person alias"); - info = purple_contact_info_new(NULL);
+ info = purple_contact_info_new("id"); purple_contact_info_set_person(info, person);
+ purple_contact_info_set_alias(info, "contact alias"); + purple_contact_info_set_username(info, "username"); + purple_contact_info_set_display_name(info, "display name"); - purple_contact_info_set_alias(info, "this is the alias");
alias = purple_contact_info_get_name_for_display(info);
- g_assert_cmpstr(alias, ==, "this is the alias");
+ g_assert_cmpstr(alias, ==, "contact alias"); @@ -163,13 +175,14 @@
person = purple_person_new();
- info = purple_contact_info_new(NULL);
+ info = purple_contact_info_new("id"); purple_contact_info_set_person(info, person);
- purple_contact_info_set_display_name(info, "this is the display name");
+ purple_contact_info_set_display_name(info, "display name"); + purple_contact_info_set_username(info, "username"); alias = purple_contact_info_get_name_for_display(info);
- g_assert_cmpstr(alias, ==, "this is the display name");
+ g_assert_cmpstr(alias, ==, "display name"); @@ -183,7 +196,7 @@
person = purple_person_new();
- info = purple_contact_info_new(NULL);
+ info = purple_contact_info_new("id"); purple_contact_info_set_username(info, "username");
purple_contact_info_set_person(info, person);
--- a/libpurple/util.h Thu Jan 05 22:41:48 2023 -0600
+++ b/libpurple/util.h Fri Jan 06 01:53:58 2023 -0600
@@ -234,6 +234,21 @@
+ * @str: A string to check if it is empty. + * Determines if @str is empty. That is, if it is %NULL or an empty string. + * Returns: %TRUE if the @str is %NULL or an empty string. +purple_strempty(const char *str) { + return (str == NULL || str[0] == '\0'); * @account: The account the string belongs to, or NULL if you do
* not know the account. If you use NULL, the string