Add Purple.ConversationManager.get_all_for_account

Tue, 15 Jul 2025 00:49:09 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Tue, 15 Jul 2025 00:49:09 -0500
changeset 43287
1de854696dfc
parent 43286
1861a365a664
child 43288
2865cd340992

Add Purple.ConversationManager.get_all_for_account

This method gets a list of all conversations belonging to an account which is
a pretty common use case and we had a number of places where we were doing
this build/check manually and this just helps avoid that.

This also removed Purple.ConversationManager.get_all as
Purple.ConversationManager implements Gio.ListModel so it wasn't necessary.

Testing Done:
Opened a conversation the echo user and then deleted my demo account and verified that the window was closed.

Also called in the turtles.

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

libpurple/accounts.c file | annotate | diff | comparison | revisions
libpurple/purpleconversationmanager.c file | annotate | diff | comparison | revisions
libpurple/purpleconversationmanager.h file | annotate | diff | comparison | revisions
libpurple/tests/test_conversation_manager.c file | annotate | diff | comparison | revisions
protocols/ircv3/purpleircv3connection.c file | annotate | diff | comparison | revisions
protocols/ircv3/purpleircv3messagehandlers.c file | annotate | diff | comparison | revisions
--- a/libpurple/accounts.c	Sun Jul 13 00:50:19 2025 -0500
+++ b/libpurple/accounts.c	Tue Jul 15 00:49:09 2025 -0500
@@ -479,7 +479,8 @@
 	PurpleAccountManager *manager = NULL;
 	PurpleConversationManager *conv_manager = NULL;
 	PurpleCredentialManager *cred_manager = NULL;
-	GList *iter = NULL;
+	GListModel *conversations = NULL;
+	guint n_items = 0;
 
 	g_return_if_fail(account != NULL);
 
@@ -496,18 +497,19 @@
 	manager = purple_account_manager_get_default();
 	purple_account_manager_remove(manager, account);
 
-	/* Remove any open conversation for this account */
+	/* Remove any conversations for this account. */
 	conv_manager = purple_conversation_manager_get_default();
-	iter = purple_conversation_manager_get_all(conv_manager);
-	while(iter != NULL) {
-		PurpleConversation *conv = iter->data;
+	conversations = purple_conversation_manager_get_all_for_account(conv_manager,
+	                                                                account);
+	n_items = g_list_model_get_n_items(G_LIST_MODEL(conversations));
+	for(guint i = 0; i < n_items; i++) {
+		PurpleConversation *conversation = NULL;
 
-		if(purple_conversation_get_account(conv) == account) {
-			g_object_unref(conv);
-		}
-
-		iter = g_list_delete_link(iter, iter);
+		conversation = g_list_model_get_item(G_LIST_MODEL(conversations), i);
+		purple_conversation_manager_remove(conv_manager, conversation);
+		g_clear_object(&conversation);
 	}
+	g_clear_object(&conversations);
 
 	/* This is async because we do not want the
 	 * account being overwritten before we are done.
--- a/libpurple/purpleconversationmanager.c	Sun Jul 13 00:50:19 2025 -0500
+++ b/libpurple/purpleconversationmanager.c	Tue Jul 15 00:49:09 2025 -0500
@@ -1085,19 +1085,30 @@
 	return manager->filename;
 }
 
-GList *
-purple_conversation_manager_get_all(PurpleConversationManager *manager) {
-	GList *result = NULL;
+GListModel *
+purple_conversation_manager_get_all_for_account(PurpleConversationManager *manager,
+                                                PurpleAccount *account)
+{
+	GListStore *model = NULL;
+
 	g_return_val_if_fail(PURPLE_IS_CONVERSATION_MANAGER(manager), NULL);
+	g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
+
+	model = g_list_store_new(PURPLE_TYPE_CONVERSATION);
 
 	for(guint i = 0; i < manager->conversations->len; i++) {
+		PurpleAccount *conv_account = NULL;
 		PurpleConversation *conversation = NULL;
 
 		conversation = g_ptr_array_index(manager->conversations, i);
-		result = g_list_append(result, conversation);
+		conv_account = purple_conversation_get_account(conversation);
+
+		if(conv_account == account) {
+			g_list_store_append(model, conversation);
+		}
 	}
 
-	return result;
+	return G_LIST_MODEL(model);
 }
 
 PurpleConversation *
--- a/libpurple/purpleconversationmanager.h	Sun Jul 13 00:50:19 2025 -0500
+++ b/libpurple/purpleconversationmanager.h	Tue Jul 15 00:49:09 2025 -0500
@@ -64,6 +64,20 @@
 gboolean purple_conversation_manager_add(PurpleConversationManager *manager, PurpleConversation *conversation);
 
 /**
+ * purple_conversation_manager_get_all_for_account:
+ * @account: the account
+ *
+ * Gets a list of conversations for a given account.
+ *
+ * Returns: (transfer full): The list of conversations.
+ *
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+GListModel *purple_conversation_manager_get_all_for_account(PurpleConversationManager *manager, PurpleAccount *account);
+
+/**
  * purple_conversation_manager_new:
  * @filename: (nullable): The filename to serialize to.
  *
@@ -122,20 +136,6 @@
 const char *purple_conversation_manager_get_filename(PurpleConversationManager *manager);
 
 /**
- * purple_conversation_manager_get_all:
- * @manager: The #PurpleConversationManager instance.
- *
- * Gets a list of all conversations that @manager knows about.
- *
- * Returns: (transfer container) (element-type PurpleConversation): A list of
- *          all of the conversations that @manager knows about.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-GList *purple_conversation_manager_get_all(PurpleConversationManager *manager);
-
-/**
  * purple_conversation_manager_find_dm:
  * @manager: The instance.
  * @contact: The contact.
--- a/libpurple/tests/test_conversation_manager.c	Sun Jul 13 00:50:19 2025 -0500
+++ b/libpurple/tests/test_conversation_manager.c	Tue Jul 15 00:49:09 2025 -0500
@@ -78,6 +78,8 @@
 	PurpleAccount *account = NULL;
 	PurpleConversationManager *manager = NULL;
 	PurpleConversation *conversation = NULL;
+	PurpleConversation *conversation1 = NULL;
+	GListModel *conversations = NULL;
 	guint added_counter = 0;
 	guint removed_counter = 0;
 	guint changed_counter = 0;
@@ -118,7 +120,20 @@
 	g_assert_cmpuint(changed_counter, ==, 1);
 	g_assert_cmpuint(g_list_model_get_n_items(G_LIST_MODEL(manager)), ==, 1);
 
-	/* Remove the contact. */
+	/* Verify that get_all_for_account works. */
+	conversations = purple_conversation_manager_get_all_for_account(manager,
+	                                                                account);
+	g_assert_true(G_IS_LIST_MODEL(conversations));
+	birb_assert_list_model_n_items(conversations, 1);
+
+	conversation1 = g_list_model_get_item(G_LIST_MODEL(conversations), 0);
+	birb_assert_type(conversation1, PURPLE_TYPE_CONVERSATION);
+	g_assert_true(conversation1 == conversation);
+	g_clear_object(&conversation1);
+
+	g_assert_finalize_object(conversations);
+
+	/* Remove the conversation. */
 	added_counter = 0;
 	removed_counter = 0;
 	changed_counter = 0;
--- a/protocols/ircv3/purpleircv3connection.c	Sun Jul 13 00:50:19 2025 -0500
+++ b/protocols/ircv3/purpleircv3connection.c	Tue Jul 15 00:49:09 2025 -0500
@@ -75,37 +75,43 @@
 purple_ircv3_connection_rejoin_channels(PurpleIRCv3Connection *connection) {
 	PurpleAccount *account = NULL;
 	PurpleConversationManager *manager = NULL;
-	GList *conversations = NULL;
+	GListModel *conversations = NULL;
+	guint n_items = 0;
 
 	account = purple_connection_get_account(PURPLE_CONNECTION(connection));
 	manager = purple_conversation_manager_get_default();
 
-	conversations = purple_conversation_manager_get_all(manager);
-	while(conversations != NULL) {
-		PurpleConversation *conversation = conversations->data;
-		PurpleAccount *conv_account = NULL;
+	conversations = purple_conversation_manager_get_all_for_account(manager,
+	                                                                account);
 
-		conv_account = purple_conversation_get_account(conversation);
-		if(conv_account == account) {
-			IbisMessage *message = NULL;
-			const char *id = purple_conversation_get_id(conversation);
+	n_items = g_list_model_get_n_items(G_LIST_MODEL(conversations));
+	for(guint i = 0; i < n_items; i++) {
+		PurpleConversation *conversation = NULL;
+
+		conversation = g_list_model_get_item(G_LIST_MODEL(conversations), i);
 
-			/* We set the online status and clear the error on the conversation
-			 * so that we can get any updated value if the join fails.
-			 */
-			purple_conversation_set_online(conversation, TRUE);
-			purple_conversation_set_error(conversation, NULL);
+		/* We set the online status and clear the error on the conversation
+		 * so that we can get any updated value if the join fails.
+		 */
+		purple_conversation_set_online(conversation, TRUE);
+		purple_conversation_set_error(conversation, NULL);
 
-			/* If this is not the status conversation we need to rejoin it. */
-			if(conversation != connection->status_conversation) {
-				message = ibis_message_new(IBIS_MSG_JOIN);
-				ibis_message_set_params(message, id, NULL);
-				ibis_client_write(connection->client, message);
-			}
+		/* If this is not the status conversation we need to rejoin it. */
+		if(conversation != connection->status_conversation) {
+			IbisMessage *message = NULL;
+			const char *id = NULL;
+
+			id = purple_conversation_get_id(conversation);
+
+			message = ibis_message_new(IBIS_MSG_JOIN);
+			ibis_message_set_params(message, id, NULL);
+			ibis_client_write(connection->client, message);
 		}
 
-		conversations = g_list_delete_link(conversations, conversations);
+		g_clear_object(&conversation);
 	}
+
+	g_clear_object(&conversations);
 }
 
 static inline void
--- a/protocols/ircv3/purpleircv3messagehandlers.c	Sun Jul 13 00:50:19 2025 -0500
+++ b/protocols/ircv3/purpleircv3messagehandlers.c	Tue Jul 15 00:49:09 2025 -0500
@@ -848,21 +848,24 @@
                                   IbisMessage *ibis_message,
                                   gpointer data)
 {
-	PurpleIRCv3Connection *connection = data;
+	PurpleIRCv3Connection *v3_connection = data;
+	PurpleAccount *account = NULL;
+	PurpleConnection *connection = data;
 	PurpleContact *contact = NULL;
 	PurpleContactInfo *info = NULL;
 	PurpleConversationManager *manager = NULL;
 	PurplePresence *presence = NULL;
-	GList *conversations = NULL;
+	GListModel *conversations = NULL;
 	GStrv params = NULL;
 	guint n_params = 0;
 	char *message = NULL;
 	char *reason = NULL;
+	guint n_items = 0;
 
 	params = ibis_message_get_params(ibis_message);
 	n_params = g_strv_length(params);
 
-	contact = purple_ircv3_connection_find_or_create_contact(connection,
+	contact = purple_ircv3_connection_find_or_create_contact(v3_connection,
 	                                                         ibis_message);
 	info = PURPLE_CONTACT_INFO(contact);
 
@@ -884,18 +887,24 @@
 	purple_presence_set_primitive(presence, PURPLE_PRESENCE_PRIMITIVE_OFFLINE);
 
 	manager = purple_conversation_manager_get_default();
-	conversations = purple_conversation_manager_get_all(manager);
-	while(conversations != NULL) {
-		PurpleConversation *conversation = conversations->data;
+	account = purple_connection_get_account(connection);
+	conversations = purple_conversation_manager_get_all_for_account(manager,
+	                                                                account);
+	n_items = g_list_model_get_n_items(G_LIST_MODEL(conversations));
+	for(guint i = 0; i < n_items; i++) {
+		PurpleConversation *conversation = NULL;
 		PurpleConversationMembers *members = NULL;
 
+		conversation = g_list_model_get_item(G_LIST_MODEL(conversations), i);
+
 		members = purple_conversation_get_members(conversation);
 		purple_conversation_members_remove_member(members, info, TRUE,
 		                                          message);
 
-		conversations = g_list_delete_link(conversations, conversations);
+		g_clear_object(&conversation);
 	}
 
+	g_clear_object(&conversations);
 	g_clear_pointer(&message, g_free);
 	g_clear_pointer(&reason, g_free);
 

mercurial