# HG changeset patch
# Node ID 2ae1bf0c87fc404e4e4b7ec52bad4702b1516eb1
# Parent  d06128ed058061d8ee1543f0e0d9b70d1e28ec43
diff --git a/libpurple/purpleconversationmanager.c b/libpurple/purpleconversationmanager.c
--- a/libpurple/purpleconversationmanager.c
+++ b/libpurple/purpleconversationmanager.c
@@ -38,6 +38,8 @@
 enum {
 	SIG_REGISTERED,
 	SIG_UNREGISTERED,
+	SIG_ADDED,
+	SIG_REMOVED,
 	SIG_CONVERSATION_CHANGED,
 	SIG_PRESENT_CONVERSATION,
 	N_SIGNALS,
@@ -225,6 +227,48 @@
 	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
 
 	/**
+	 * PurpleConversationManager::added:
+	 * @manager: The manager.
+	 * @conversation: The conversation that was added.
+	 *
+	 * Emitted after @conversation has been added to @manager.
+	 *
+	 * Since: 3.0
+	 */
+	signals[SIG_ADDED] = g_signal_new_class_handler(
+		"added",
+		G_OBJECT_CLASS_TYPE(klass),
+		G_SIGNAL_RUN_LAST,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		G_TYPE_NONE,
+		1,
+		PURPLE_TYPE_CONVERSATION);
+
+	/**
+	 * PurpleConversationManager::removed:
+	 * @manager: The manager.
+	 * @conversation: The conversation that was removed.
+	 *
+	 * Emitted after @conversation has been removed from @manager.
+	 *
+	 * Since: 3.0
+	 */
+	signals[SIG_REMOVED] = g_signal_new_class_handler(
+		"removed",
+		G_OBJECT_CLASS_TYPE(klass),
+		G_SIGNAL_RUN_LAST,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		G_TYPE_NONE,
+		1,
+		PURPLE_TYPE_CONVERSATION);
+
+	/**
 	 * PurpleConversationManager::registered:
 	 * @manager: The manager.
 	 * @conversation: The conversation that was registered.
@@ -232,6 +276,8 @@
 	 * Emitted after @conversation has been registered with @manager.
 	 *
 	 * Since: 3.0
+	 *
+	 * Deprecated: 3.0
 	 */
 	signals[SIG_REGISTERED] = g_signal_new_class_handler(
 		"registered",
@@ -253,6 +299,8 @@
 	 * Emitted after @conversation has been unregistered from @manager.
 	 *
 	 * Since: 3.0
+	 *
+	 * Deprecated: 3.0
 	 */
 	signals[SIG_UNREGISTERED] = g_signal_new_class_handler(
 		"unregistered",
@@ -343,6 +391,39 @@
 /******************************************************************************
  * Public API
  *****************************************************************************/
+gboolean
+purple_conversation_manager_add(PurpleConversationManager *manager,
+                                PurpleConversation *conversation)
+{
+	gboolean added = FALSE;
+
+	g_return_val_if_fail(PURPLE_IS_CONVERSATION_MANAGER(manager), FALSE);
+	g_return_val_if_fail(PURPLE_IS_CONVERSATION(conversation), FALSE);
+
+	/* g_hash_table_add calls the key_destroy_func if the key already exists
+	 * which means we don't need to worry about the reference we're creating
+	 * during the addition.
+	 */
+	added = g_hash_table_add(manager->conversations,
+	                         g_object_ref(conversation));
+
+	if(added) {
+		/* Register our signals that need to be propagated. */
+		g_signal_connect_object(conversation, "notify",
+		                        G_CALLBACK(purple_conversation_manager_conversation_changed_cb),
+		                        manager, 0);
+		g_signal_connect_object(conversation, "present",
+		                        G_CALLBACK(purple_conversation_manager_present_conversation_cb),
+		                        manager, 0);
+
+		/* Tell everyone about the new conversation. */
+		g_signal_emit(manager, signals[SIG_ADDED], 0, conversation);
+		g_signal_emit(manager, signals[SIG_REGISTERED], 0, conversation);
+	}
+
+	return added;
+}
+
 PurpleConversationManager *
 purple_conversation_manager_new(const char *filename) {
 	return g_object_new(
@@ -367,63 +448,20 @@
 purple_conversation_manager_register(PurpleConversationManager *manager,
                                      PurpleConversation *conversation)
 {
-	gboolean registered = FALSE;
-
 	g_return_val_if_fail(PURPLE_IS_CONVERSATION_MANAGER(manager), FALSE);
 	g_return_val_if_fail(PURPLE_IS_CONVERSATION(conversation), FALSE);
 
-	/* g_hash_table_add calls the key_destroy_func if the key already exists
-	 * which means we don't need to worry about the reference we're creating
-	 * during the addition.
-	 */
-	registered = g_hash_table_add(manager->conversations,
-	                              g_object_ref(conversation));
-
-	if(registered) {
-		/* Register our signals that need to be propagated. */
-		g_signal_connect_object(conversation, "notify",
-		                        G_CALLBACK(purple_conversation_manager_conversation_changed_cb),
-		                        manager, 0);
-		g_signal_connect_object(conversation, "present",
-		                        G_CALLBACK(purple_conversation_manager_present_conversation_cb),
-		                        manager, 0);
-
-		/* Tell everyone about the new conversation. */
-		g_signal_emit(manager, signals[SIG_REGISTERED], 0, conversation);
-	}
-
-	return registered;
+	return purple_conversation_manager_add(manager, conversation);
 }
 
 gboolean
 purple_conversation_manager_unregister(PurpleConversationManager *manager,
                                        PurpleConversation *conversation)
 {
-	gboolean unregistered = FALSE;
-
 	g_return_val_if_fail(PURPLE_IS_CONVERSATION_MANAGER(manager), FALSE);
 	g_return_val_if_fail(PURPLE_IS_CONVERSATION(conversation), FALSE);
 
-	/* Make sure we have a reference in case we need to emit signals. */
-	g_object_ref(conversation);
-
-	unregistered = g_hash_table_remove(manager->conversations, conversation);
-	if(unregistered) {
-		/* Disconnect all the signals we added for propagation. */
-		g_signal_handlers_disconnect_by_func(conversation,
-		                                     purple_conversation_manager_conversation_changed_cb,
-		                                     manager);
-		g_signal_handlers_disconnect_by_func(conversation,
-		                                     purple_conversation_manager_present_conversation_cb,
-		                                     manager);
-
-		/* Tell everyone about the unregistered conversation. */
-		g_signal_emit(manager, signals[SIG_UNREGISTERED], 0, conversation);
-	}
-
-	g_object_unref(conversation);
-
-	return unregistered;
+	return purple_conversation_manager_remove(manager, conversation);
 }
 
 gboolean
@@ -524,3 +562,35 @@
 	                                                 purple_conversation_has_id,
 	                                                 (gpointer)id);
 }
+
+gboolean
+purple_conversation_manager_remove(PurpleConversationManager *manager,
+                                   PurpleConversation *conversation)
+{
+	gboolean removed = FALSE;
+
+	g_return_val_if_fail(PURPLE_IS_CONVERSATION_MANAGER(manager), FALSE);
+	g_return_val_if_fail(PURPLE_IS_CONVERSATION(conversation), FALSE);
+
+	/* Make sure we have a reference in case we need to emit signals. */
+	g_object_ref(conversation);
+
+	removed = g_hash_table_remove(manager->conversations, conversation);
+	if(removed) {
+		/* Disconnect all the signals we added for propagation. */
+		g_signal_handlers_disconnect_by_func(conversation,
+		                                     purple_conversation_manager_conversation_changed_cb,
+		                                     manager);
+		g_signal_handlers_disconnect_by_func(conversation,
+		                                     purple_conversation_manager_present_conversation_cb,
+		                                     manager);
+
+		/* Tell everyone about the removed conversation. */
+		g_signal_emit(manager, signals[SIG_REMOVED], 0, conversation);
+		g_signal_emit(manager, signals[SIG_UNREGISTERED], 0, conversation);
+	}
+
+	g_object_unref(conversation);
+
+	return removed;
+}
diff --git a/libpurple/purpleconversationmanager.h b/libpurple/purpleconversationmanager.h
--- a/libpurple/purpleconversationmanager.h
+++ b/libpurple/purpleconversationmanager.h
@@ -63,6 +63,20 @@
 typedef void (*PurpleConversationManagerForeachFunc)(PurpleConversation *conversation, gpointer data);
 
 /**
+ * purple_conversation_manager_add:
+ * @manager: The #PurpleConversationManager instance.
+ * @conversation: The #PurpleConversation to add.
+ *
+ * Adds @conversation to @manager.
+ *
+ * Returns: %TRUE if @conversation was not yet added.
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+gboolean purple_conversation_manager_add(PurpleConversationManager *manager, PurpleConversation *conversation);
+
+/**
  * purple_conversation_manager_new:
  * @filename: (nullable): The filename to serialize to.
  *
@@ -118,7 +132,7 @@
  *
  * Since: 3.0
  */
-PURPLE_AVAILABLE_IN_3_0
+PURPLE_DEPRECATED_FOR(purple_conversation_manager_add)
 gboolean purple_conversation_manager_register(PurpleConversationManager *manager, PurpleConversation *conversation);
 
 /**
@@ -132,7 +146,7 @@
  *
  * Since: 3.0
  */
-PURPLE_AVAILABLE_IN_3_0
+PURPLE_DEPRECATED_FOR(purple_conversation_manager_remove)
 gboolean purple_conversation_manager_unregister(PurpleConversationManager *manager, PurpleConversation *conversation);
 
 /**
@@ -224,6 +238,20 @@
 PURPLE_AVAILABLE_IN_3_0
 PurpleConversation *purple_conversation_manager_find_with_id(PurpleConversationManager *manager, PurpleAccount *account, const char *id);
 
+/**
+ * purple_conversation_manager_remove:
+ * @manager: The #PurpleConversationManager instance.
+ * @conversation: The #PurpleConversation to remove.
+ *
+ * Removes @conversation from @manager.
+ *
+ * Returns: %TRUE if @conversation was found and removed.
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+gboolean purple_conversation_manager_remove(PurpleConversationManager *manager, PurpleConversation *conversation);
+
 G_END_DECLS
 
 #endif /* PURPLE_CONVERSATION_MANAGER_H */
diff --git a/libpurple/tests/test_conversation_manager.c b/libpurple/tests/test_conversation_manager.c
--- a/libpurple/tests/test_conversation_manager.c
+++ b/libpurple/tests/test_conversation_manager.c
@@ -70,12 +70,13 @@
 }
 
 static void
-test_purple_conversation_manager_register_unregister(void) {
+test_purple_conversation_manager_add_remove(void) {
 	PurpleAccount *account = NULL;
 	PurpleConversationManager *manager = NULL;
 	PurpleConversation *conversation = NULL;
 	GList *conversations = NULL;
-	guint registered_counter = 0, unregistered_counter = 0;
+	guint added_counter = 0;
+	guint removed_counter = 0;
 	gboolean result = FALSE;
 
 	manager = g_object_new(PURPLE_TYPE_CONVERSATION_MANAGER, NULL);
@@ -83,12 +84,12 @@
 	g_assert_true(PURPLE_IS_CONVERSATION_MANAGER(manager));
 
 	/* Wire up our signals. */
-	g_signal_connect(manager, "registered",
+	g_signal_connect(manager, "added",
 	                 G_CALLBACK(test_purple_conversation_manager_counter_cb),
-	                 &registered_counter);
-	g_signal_connect(manager, "unregistered",
+	                 &added_counter);
+	g_signal_connect(manager, "removed",
 	                 G_CALLBACK(test_purple_conversation_manager_counter_cb),
-	                 &unregistered_counter);
+	                 &removed_counter);
 
 	/* Create our account. */
 	account = purple_account_new("test", "test");
@@ -100,7 +101,7 @@
 		NULL);
 
 	/* Add the conversation to the manager. */
-	result = purple_conversation_manager_register(manager, conversation);
+	result = purple_conversation_manager_add(manager, conversation);
 	g_assert_true(result);
 
 	/* Make sure the conversation is available. */
@@ -110,12 +111,12 @@
 	g_list_free(conversations);
 
 	/* Make sure the registered signal was called. */
-	g_assert_cmpuint(registered_counter, ==, 1);
+	g_assert_cmpuint(added_counter, ==, 1);
 
 	/* Remove the contact. */
-	result = purple_conversation_manager_unregister(manager, conversation);
+	result = purple_conversation_manager_remove(manager, conversation);
 	g_assert_true(result);
-	g_assert_cmpuint(unregistered_counter, ==, 1);
+	g_assert_cmpuint(removed_counter, ==, 1);
 
 	/* Clean up.*/
 	g_clear_object(&conversation);
@@ -164,7 +165,7 @@
 		PURPLE_TYPE_CONVERSATION,
 		"account", account,
 		NULL);
-	purple_conversation_manager_register(manager, conversation);
+	purple_conversation_manager_add(manager, conversation);
 
 	/* Set the features and title of the conversation, and verify our counters. */
 	purple_conversation_set_title(conversation, "A place for kool kats");
@@ -178,7 +179,7 @@
 	/* Unregister the conversation, to make sure signals are no longer
 	 * propagated.
 	 */
-	result = purple_conversation_manager_unregister(manager, conversation);
+	result = purple_conversation_manager_remove(manager, conversation);
 	g_assert_true(result);
 
 	counter = 0;
@@ -215,14 +216,14 @@
 		"type", PURPLE_CONVERSATION_TYPE_DM,
 		NULL);
 
-	ret = purple_conversation_manager_register(manager, conversation);
+	ret = purple_conversation_manager_add(manager, conversation);
 	g_assert_true(ret);
 
 	g_assert_cmpuint(counter, ==, 0);
 	purple_conversation_present(conversation);
 	g_assert_cmpuint(counter, ==, 1);
 
-	ret = purple_conversation_manager_unregister(manager, conversation);
+	ret = purple_conversation_manager_remove(manager, conversation);
 	g_assert_true(ret);
 
 	g_assert_finalize_object(manager);
@@ -274,7 +275,7 @@
 		"account", account,
 		"type", PURPLE_CONVERSATION_TYPE_DM,
 		NULL);
-	purple_conversation_manager_register(manager, conversation1);
+	purple_conversation_manager_add(manager, conversation1);
 	members = purple_conversation_get_members(conversation1);
 
 	purple_conversation_members_add_member(members,
@@ -285,7 +286,7 @@
 	g_assert_nonnull(conversation2);
 	g_assert_true(conversation1 == conversation2);
 
-	purple_conversation_manager_unregister(manager, conversation1);
+	purple_conversation_manager_remove(manager, conversation1);
 
 	g_assert_finalize_object(conversation1);
 	g_assert_finalize_object(contact);
@@ -328,7 +329,7 @@
 		"account", account1,
 		"type", PURPLE_CONVERSATION_TYPE_CHANNEL,
 		NULL);
-	purple_conversation_manager_register(manager, conversation1);
+	purple_conversation_manager_add(manager, conversation1);
 
 	/* Create a conversation with the contact's account that is a dm but not
 	 * with the contact.
@@ -338,7 +339,7 @@
 		"account", account1,
 		"type", PURPLE_CONVERSATION_TYPE_DM,
 		NULL);
-	purple_conversation_manager_register(manager, conversation2);
+	purple_conversation_manager_add(manager, conversation2);
 
 	/* Create a conversation with a different account. */
 	conversation3 = g_object_new(
@@ -346,14 +347,14 @@
 		"account", account2,
 		"type", PURPLE_CONVERSATION_TYPE_CHANNEL,
 		NULL);
-	purple_conversation_manager_register(manager, conversation3);
+	purple_conversation_manager_add(manager, conversation3);
 
 	conversation4 = purple_conversation_manager_find_dm(manager, contact);
 	g_assert_null(conversation4);
 
-	purple_conversation_manager_unregister(manager, conversation1);
-	purple_conversation_manager_unregister(manager, conversation2);
-	purple_conversation_manager_unregister(manager, conversation3);
+	purple_conversation_manager_remove(manager, conversation1);
+	purple_conversation_manager_remove(manager, conversation2);
+	purple_conversation_manager_remove(manager, conversation3);
 
 	g_assert_finalize_object(conversation1);
 	g_assert_finalize_object(conversation2);
@@ -378,8 +379,8 @@
 	g_test_add_func("/conversation-manager/new/filename",
 	                test_purple_conversation_manager_new_filename);
 
-	g_test_add_func("/conversation-manager/register-unregister",
-	                test_purple_conversation_manager_register_unregister);
+	g_test_add_func("/conversation-manager/add-remove",
+	                test_purple_conversation_manager_add_remove);
 
 	g_test_add_func("/conversation-manager/signals/conversation-changed",
 	                test_purple_conversation_manager_signal_conversation_changed);
diff --git a/libpurple/tests/test_history_adapter.c b/libpurple/tests/test_history_adapter.c
--- a/libpurple/tests/test_history_adapter.c
+++ b/libpurple/tests/test_history_adapter.c
@@ -236,7 +236,6 @@
 test_purple_history_adapter_test_write(void) {
 	PurpleAccount *account = NULL;
 	PurpleConversation *conversation = NULL;
-	PurpleConversationManager *conversation_manager = NULL;
 	PurpleHistoryAdapter *adapter = test_purple_history_adapter_new();
 	PurpleMessage *message = NULL;
 	TestPurpleHistoryAdapter *ta = TEST_PURPLE_HISTORY_ADAPTER(adapter);
@@ -263,13 +262,6 @@
 
 	g_clear_object(&adapter);
 	g_clear_object(&message);
-
-	/* TODO: Conversations are automatically registered on construction for
-	 * legacy reasons, so we need to explicitly unregister to clean them up,
-	 * but this can go away once that stops happening. */
-	conversation_manager = purple_conversation_manager_get_default();
-	purple_conversation_manager_unregister(conversation_manager, conversation);
-
 	g_clear_object(&conversation);
 	g_clear_object(&account);
 }
diff --git a/libpurple/tests/test_history_manager.c b/libpurple/tests/test_history_manager.c
--- a/libpurple/tests/test_history_manager.c
+++ b/libpurple/tests/test_history_manager.c
@@ -315,7 +315,6 @@
 test_purple_history_manager_no_adapter_write(void) {
 	PurpleAccount *account = NULL;
 	PurpleConversation *conversation = NULL;
-	PurpleConversationManager *conversation_manager = NULL;
 	PurpleHistoryManager *manager = NULL;
 	PurpleMessage *message = NULL;
 	GError *error = NULL;
@@ -339,12 +338,6 @@
 
 	g_assert_false(result);
 
-	/* TODO: Conversations are automatically registered on construction for
-	 * legacy reasons, so we need to explicitly unregister to clean them up,
-	 * but this can go away once that stops happening. */
-	conversation_manager = purple_conversation_manager_get_default();
-	purple_conversation_manager_unregister(conversation_manager, conversation);
-
 	g_clear_object(&message);
 	g_clear_object(&conversation);
 	g_clear_object(&account);
@@ -435,7 +428,6 @@
 test_purple_history_manager_adapter_write(void) {
 	PurpleAccount *account = NULL;
 	PurpleConversation *conversation = NULL;
-	PurpleConversationManager *conversation_manager = NULL;
 	PurpleHistoryManager *manager = NULL;
 	PurpleHistoryAdapter *adapter = NULL;
 	PurpleMessage *message = NULL;
@@ -478,13 +470,6 @@
 
 	g_clear_object(&adapter);
 	g_clear_object(&message);
-
-	/* TODO: Conversations are automatically registered on construction for
-	 * legacy reasons, so we need to explicitly unregister to clean them up,
-	 * but this can go away once that stops happening. */
-	conversation_manager = purple_conversation_manager_get_default();
-	purple_conversation_manager_unregister(conversation_manager, conversation);
-
 	g_clear_object(&conversation);
 	g_clear_object(&account);
 	g_clear_object(&manager);
