--- a/libpurple/buddy.c Sat Oct 01 01:48:31 2022 -0500
+++ b/libpurple/buddy.c Sat Oct 01 01:50:52 2022 -0500
@@ -24,6 +24,7 @@
#include "purplebuddypresence.h"
+#include "purplecontactmanager.h" #include "purpleconversationmanager.h"
#include "purpleprotocolclient.h"
@@ -292,15 +293,25 @@
purple_buddy_new(PurpleAccount *account, const gchar *name, const gchar *alias)
+ PurpleBuddy *buddy = NULL; + PurpleContactManager *manager = NULL; g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
g_return_val_if_fail(name != NULL, NULL);
+ manager = purple_contact_manager_get_default(); + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + purple_contact_manager_add_buddy(manager, buddy); + G_GNUC_END_IGNORE_DEPRECATIONS --- a/libpurple/purplecontact.c Sat Oct 01 01:48:31 2022 -0500
+++ b/libpurple/purplecontact.c Sat Oct 01 01:50:52 2022 -0500
@@ -150,9 +150,6 @@
purple_contact_set_avatar(contact, g_value_get_object(value));
- purple_contact_set_presence(contact, g_value_get_object(value));
purple_contact_set_person(contact, g_value_get_object(value));
@@ -202,6 +199,7 @@
purple_contact_init(PurpleContact *contact) {
contact->tags = purple_tags_new();
+ contact->presence = g_object_new(PURPLE_TYPE_PRESENCE, NULL); @@ -308,7 +306,7 @@
"The presence of the contact",
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); @@ -443,15 +441,6 @@
return contact->presence;
-purple_contact_set_presence(PurpleContact *contact, PurplePresence *presence) {
- g_return_if_fail(PURPLE_IS_CONTACT(contact));
- if(g_set_object(&contact->presence, presence)) {
- g_object_notify_by_pspec(G_OBJECT(contact), properties[PROP_PRESENCE]);
purple_contact_get_tags(PurpleContact *contact) {
g_return_val_if_fail(PURPLE_IS_CONTACT(contact), NULL);
--- a/libpurple/purplecontact.h Sat Oct 01 01:48:31 2022 -0500
+++ b/libpurple/purplecontact.h Sat Oct 01 01:50:52 2022 -0500
@@ -207,20 +207,6 @@
PurplePresence *purple_contact_get_presence(PurpleContact *contact);
- * purple_contact_set_presence:
- * @contact: The instance.
- * @presence: (nullable): The new [class@Purple.Presence] to set.
- * Sets the presence for @contact to @presence. If @presence is %NULL, the
- * existing presence will be cleared.
- * Typically this should only be called by the protocol plugin.
-void purple_contact_set_presence(PurpleContact *contact, PurplePresence *presence);
* purple_contact_get_tags:
* @contact: The instance.
--- a/libpurple/purplecontactmanager.c Sat Oct 01 01:48:31 2022 -0500
+++ b/libpurple/purplecontactmanager.c Sat Oct 01 01:50:52 2022 -0500
@@ -19,6 +19,8 @@
#include <glib/gi18n-lib.h>
#include "purplecontactmanager.h"
+#include "purplegdkpixbuf.h" #include "purpleprivate.h"
@@ -68,6 +70,62 @@
return purple_strequal(id_a, id_b);
+purple_contact_manager_convert_icon_to_avatar(GBinding *binding, + const GValue *from_value, + PurpleBuddyIcon *icon = g_value_get_pointer(from_value); + GdkPixbuf *avatar = NULL; + gconstpointer data = NULL; + g_value_set_object(to_value, NULL); + data = purple_buddy_icon_get_data(icon, &len); + avatar = purple_gdk_pixbuf_from_data(data, len); + g_value_take_object(to_value, avatar); +purple_contact_manager_convert_avatar_to_icon(GBinding *binding, + const GValue *from_value, + PurpleBuddyIcon *icon = NULL; + GdkPixbuf *avatar = g_value_get_object(from_value); + gboolean result = FALSE; + if(!GDK_IS_PIXBUF(avatar)) { + g_value_set_pointer(to_value, NULL); + result = gdk_pixbuf_save_to_buffer(avatar, &buffer, &len, "png", NULL, + "compression", "9", NULL); + purple_buddy_icon_set_data(icon, (guchar *)buffer, len, NULL); /******************************************************************************
*****************************************************************************/
@@ -367,3 +425,60 @@
+/****************************************************************************** + *****************************************************************************/ +purple_contact_manager_add_buddy(PurpleContactManager *manager, + PurpleAccount *account = NULL; + PurpleContact *contact = NULL; + PurplePresence *buddy_presence = NULL; + PurplePresence *contact_presence = NULL; + const gchar *id = NULL; + g_return_if_fail(PURPLE_IS_CONTACT_MANAGER(manager)); + g_return_if_fail(PURPLE_IS_BUDDY(buddy)); + /* Create the new contact. */ + account = purple_buddy_get_account(buddy); + id = purple_buddy_get_id(buddy); + contact = purple_contact_new(account, id); + /* Bind all of the properties. */ + g_object_bind_property(buddy, "name", contact, "username", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + g_object_bind_property(buddy, "local-alias", contact, "alias", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + g_object_bind_property(buddy, "server-alias", contact, "display-name", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + buddy_presence = purple_buddy_get_presence(buddy); + contact_presence = purple_contact_get_presence(contact); + g_object_bind_property(buddy_presence, "idle", contact_presence, "idle", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + g_object_bind_property(buddy_presence, "idle-time", contact_presence, + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + g_object_bind_property(buddy_presence, "login-time", contact_presence, + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + g_object_bind_property(buddy_presence, "active-status", contact_presence, + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + g_object_bind_property_full(buddy, "icon", contact, "avatar", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + purple_contact_manager_convert_icon_to_avatar, + purple_contact_manager_convert_avatar_to_icon, + /* Finally add it to the manager. */ + purple_contact_manager_add(manager, contact); + /* purple_contact_manager_add adds its own reference, so free our copy. */ + g_clear_object(&contact); --- a/libpurple/purplecontactmanager.h Sat Oct 01 01:48:31 2022 -0500
+++ b/libpurple/purplecontactmanager.h Sat Oct 01 01:50:52 2022 -0500
@@ -141,6 +141,23 @@
PurpleContact *purple_contact_manager_find_with_id(PurpleContactManager *manager, PurpleAccount *account, const gchar *id);
+ * purple_contact_manager_add_buddy: + * @manager: The instance. + * @buddy: A [class@Purple.Buddy] instance. + * Creates a new [class@Purple.Contact] and binds its properties to @buddy and + * then adds the new [class@Purple.Contact] via + * [method@Purple.ContactManager.add]. + * This method is meant to help us transition to the new API and this method + * shouldn't be used elsewhere. +void purple_contact_manager_add_buddy(PurpleContactManager *manager, PurpleBuddy *buddy); #endif /* PURPLE_CONTACT_MANAGER_H */
--- a/libpurple/purpleperson.c Sat Oct 01 01:48:31 2022 -0500
+++ b/libpurple/purpleperson.c Sat Oct 01 01:50:52 2022 -0500
@@ -113,18 +113,6 @@
purple_person_sort_contacts(data);
-purple_person_contact_notify_cb(GObject *obj,
- G_GNUC_UNUSED GParamSpec *pspec,
- PurpleContact *contact = PURPLE_CONTACT(obj);
- g_signal_connect_object(contact, "notify",
- G_CALLBACK(purple_person_presence_notify_cb),
/******************************************************************************
* GListModel Implementation
*****************************************************************************/
@@ -407,17 +395,11 @@
g_ptr_array_add(person->contacts, g_object_ref(contact));
- g_signal_connect_object(contact, "notify::presence",
- G_CALLBACK(purple_person_contact_notify_cb),
+ presence = purple_contact_get_presence(contact); + g_signal_connect_object(presence, "notify", + G_CALLBACK(purple_person_presence_notify_cb), - presence = purple_contact_get_presence(contact);
- if(PURPLE_IS_PRESENCE(presence)) {
- g_signal_connect_object(presence, "notify",
- G_CALLBACK(purple_person_presence_notify_cb),
purple_contact_set_person(contact, person);
purple_person_sort_contacts(person);
@@ -441,17 +423,10 @@
PurplePresence *presence = purple_contact_get_presence(contact);
- /* Disconnect our signal handlers. */
- g_signal_handlers_disconnect_by_func(contact,
- purple_person_contact_notify_cb,
+ g_signal_handlers_disconnect_by_func(presence, + purple_person_presence_notify_cb, - if(PURPLE_IS_PRESENCE(presence)) {
- g_signal_handlers_disconnect_by_func(presence,
- purple_person_presence_notify_cb,
purple_contact_set_person(contact, NULL);
purple_person_sort_contacts(person);
--- a/libpurple/tests/test_contact.c Sat Oct 01 01:48:31 2022 -0500
+++ b/libpurple/tests/test_contact.c Sat Oct 01 01:50:52 2022 -0500
@@ -47,7 +47,6 @@
PurpleContact *contact = NULL;
PurplePerson *person = NULL;
PurplePerson *person1 = NULL;
- PurplePresence *presence = NULL;
PurplePresence *presence1 = NULL;
GdkPixbuf *avatar = NULL;
@@ -59,7 +58,6 @@
account = purple_account_new("test", "test");
avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, 1, 1);
- presence = g_object_new(PURPLE_TYPE_PRESENCE, NULL);
person = purple_person_new();
/* Use g_object_new so we can test setting properties by name. All of them
@@ -74,7 +72,6 @@
"display-name", "display-name",
@@ -98,7 +95,7 @@
g_assert_cmpstr(display_name, ==, "display-name");
g_assert_cmpstr(alias, ==, "alias");
g_assert_true(avatar1 == avatar);
- g_assert_true(presence1 == presence);
+ g_assert_nonnull(presence1); g_assert_true(person1 == person);
@@ -114,7 +111,6 @@
g_clear_object(&person1);
- g_clear_object(&presence);
g_clear_object(&contact);
g_clear_object(&account);
--- a/libpurple/tests/test_contact_manager.c Sat Oct 01 01:48:31 2022 -0500
+++ b/libpurple/tests/test_contact_manager.c Sat Oct 01 01:50:52 2022 -0500
@@ -260,6 +260,90 @@
g_clear_object(&manager);
+test_purple_contact_manager_add_buddy(void) { + PurpleAccount *account = NULL; + PurpleBuddy *buddy = NULL; + PurpleContact *contact = NULL; + PurpleContactManager *manager = NULL; + PurpleStatusType *type = NULL; + GList *statuses = NULL; + const gchar *id = NULL; + const gchar *source = NULL; + const gchar *destination = NULL; + manager = purple_contact_manager_get_default(); + /* Create our account and add the statuses for testing. */ + account = purple_account_new("test", "test"); + type = purple_status_type_new(PURPLE_STATUS_OFFLINE, "offline", + statuses = g_list_append(statuses, type); + purple_account_set_status_types(account, statuses); + /* purple_buddy_new will call purple_contact_manager_add_buddy. */ + buddy = purple_buddy_new(account, "buddy-name", "buddy-alias"); + /* Verify that we can find the created contact via id. */ + id = purple_buddy_get_id(buddy); + contact = purple_contact_manager_find_with_id(manager, account, id); + g_assert_nonnull(contact); + g_assert_true(PURPLE_IS_CONTACT(contact)); + /* Verify that we can find the created contact via username. */ + contact = purple_contact_manager_find_with_username(manager, account, + g_assert_nonnull(contact); + g_assert_true(PURPLE_IS_CONTACT(contact)); + /* Now check the alias and display name to make sure they were synced as + source = purple_buddy_get_local_alias(buddy); + destination = purple_contact_get_alias(contact); + g_assert_cmpstr(destination, ==, source); + source = purple_buddy_get_server_alias(buddy); + destination = purple_contact_get_display_name(contact); + g_assert_cmpstr(destination, ==, source); + /* Now let's change the settings in the buddy and verify they made it to the + /* We have to skip testing the name because we have to stand up a LOT more + * of libpurple to be able to change the name. + purple_buddy_set_name(buddy, "guy-name"); + g_assert_cmpstr(purple_contact_get_username(contact), ==, "guy-name"); + purple_buddy_set_local_alias(buddy, "guy-alias"); + g_assert_cmpstr(purple_contact_get_alias(contact), ==, "guy-alias"); + purple_buddy_set_server_alias(buddy, "server-guy"); + g_assert_cmpstr(purple_contact_get_display_name(contact), ==, + purple_contact_set_alias(contact, "friend-alias"); + g_assert_cmpstr(purple_buddy_get_local_alias(buddy), ==, "friend-alias"); + purple_contact_set_display_name(contact, "server-friend"); + g_assert_cmpstr(purple_buddy_get_server_alias(buddy), ==, "server-friend"); + /* We can't verify the presences changes because PurpleBuddy has to be in + * a PurpleMetaContact for that to not crash. + /* Since we're working on the default contact manager, make sure we remove + * any contacts for our test account. + purple_contact_manager_remove_all(manager, account); + g_clear_object(&account); + g_clear_object(&buddy); + g_clear_object(&contact); /******************************************************************************
*****************************************************************************/
@@ -286,5 +370,8 @@
g_test_add_func("/contact-manager/find/with-id",
test_purple_contact_manager_find_with_id);
+ g_test_add_func("/contact-manager/add-buddy", + test_purple_contact_manager_add_buddy); --- a/libpurple/tests/test_person.c Sat Oct 01 01:48:31 2022 -0500
+++ b/libpurple/tests/test_person.c Sat Oct 01 01:50:52 2022 -0500
@@ -236,19 +236,18 @@
priority = purple_person_get_priority_contact(person);
- /* Build the presence and status for the contact. */
- presence = g_object_new(PURPLE_TYPE_PRESENCE, NULL);
+ /* Now create a real contact. */ + contact = purple_contact_new(account, "username"); + purple_person_add_contact(person, contact); + /* Set the status of the contact. */ + presence = purple_contact_get_presence(contact); status_type = purple_status_type_new(PURPLE_STATUS_AVAILABLE, "available",
status = purple_status_new(status_type, presence);
g_object_set(G_OBJECT(presence), "active-status", status, NULL);
- /* Now create a real contact. */
- contact = purple_contact_new(account, "username");
- purple_contact_set_presence(contact, presence);
- purple_person_add_contact(person, contact);
priority = purple_person_get_priority_contact(person);
@@ -309,17 +308,16 @@
/* Set changed to false as it shouldn't be changed. */
- /* Build the presence and status for the contact. */
- presence = g_object_new(PURPLE_TYPE_PRESENCE, NULL);
- status = purple_status_new(offline, presence);
- g_object_set(G_OBJECT(presence), "active-status", status, NULL);
- g_clear_object(&status);
/* Now create a real contact. */
username = g_strdup_printf("username%d", i + 1);
contact = purple_contact_new(account, username);
- purple_contact_set_presence(contact, presence);
+ /* Set the status for the contact. */ + presence = purple_contact_get_presence(contact); + status = purple_status_new(offline, presence); + g_object_set(G_OBJECT(presence), "active-status", status, NULL); + g_clear_object(&status); purple_person_add_contact(person, contact);
@@ -336,7 +334,6 @@
g_clear_object(&contact);
- g_clear_object(&presence);
n_items = g_list_model_get_n_items(G_LIST_MODEL(person));