# HG changeset patch
# Node ID cd2f5442b93e
# Parent  f6baa88826a7
diff --git a/finch/gntaccount.c b/finch/gntaccount.c
--- a/finch/gntaccount.c
+++ b/finch/gntaccount.c
@@ -693,7 +693,7 @@
 	}
 
 	manager = purple_notification_manager_get_default();
-	purple_notification_manager_remove_with_account(manager, account);
+	purple_notification_manager_remove_with_account(manager, account, TRUE);
 
 	purple_accounts_delete(account);
 }
diff --git a/libpurple/account.c b/libpurple/account.c
--- a/libpurple/account.c
+++ b/libpurple/account.c
@@ -1222,7 +1222,7 @@
 	g_return_if_fail(PURPLE_IS_ACCOUNT(account));
 
 	manager = purple_notification_manager_get_default();
-	purple_notification_manager_remove_with_account(manager, account);
+	purple_notification_manager_remove_with_account(manager, account, FALSE);
 }
 
 void
diff --git a/libpurple/purplenotificationmanager.h b/libpurple/purplenotificationmanager.h
--- a/libpurple/purplenotificationmanager.h
+++ b/libpurple/purplenotificationmanager.h
@@ -81,12 +81,18 @@
  * purple_notification_manager_remove_with_account:
  * @manager: The instance.
  * @account: The [class@Account] whose notifications to remove.
+ * @all: Whether or not to clear connection error notifications as well.
  *
  * Removes all notifications with @account from @manager.
  *
+ * If @all is set to %TRUE, notifications of type
+ * PURPLE_NOTIFICATION_TYPE_CONNECTION_ERROR will be removed as well. These are
+ * treated differently from other notifications tied to accounts, as those are
+ * transient and depend on the account being connected to be valid.
+ *
  * Since: 3.0.0
  */
-void purple_notification_manager_remove_with_account(PurpleNotificationManager *manager, PurpleAccount *account);
+void purple_notification_manager_remove_with_account(PurpleNotificationManager *manager, PurpleAccount *account, gboolean all);
 
 /**
  * purple_notification_manager_get_unread_count:
diff --git a/libpurple/purplenotificationmanager.c b/libpurple/purplenotificationmanager.c
--- a/libpurple/purplenotificationmanager.c
+++ b/libpurple/purplenotificationmanager.c
@@ -394,7 +394,8 @@
 */
 void
 purple_notification_manager_remove_with_account(PurpleNotificationManager *manager,
-                                                PurpleAccount *account)
+                                                PurpleAccount *account,
+                                                gboolean all)
 {
 	guint pos = 0, len = 0;
 	guint start = 0, count = 0;
@@ -407,13 +408,25 @@
 	for(pos = 0; pos < len; pos++) {
 		PurpleAccount *account2 = NULL;
 		PurpleNotification *notification = NULL;
+		PurpleNotificationType type;
+		gboolean can_remove = TRUE;
 
 		notification = g_list_model_get_item(G_LIST_MODEL(manager->notifications),
 		                                     pos);
 
+		/* If the notification's type is connection error, set can_remove to
+		 * the value of the all parameter.
+		 */
+		type = purple_notification_get_notification_type(notification);
+		if(type == PURPLE_NOTIFICATION_TYPE_CONNECTION_ERROR) {
+			can_remove = all;
+		}
+
 		account2 = purple_notification_get_account(notification);
-		if(account == account2) {
-			/* If this is the first item with the right account store its position. */
+		if(account == account2 && can_remove) {
+			/* If this is the first item with the right account store its
+			 * position.
+			 */
 			if(!have_same) {
 				count = 0;
 				start = pos;
diff --git a/libpurple/tests/test_notification_manager.c b/libpurple/tests/test_notification_manager.c
--- a/libpurple/tests/test_notification_manager.c
+++ b/libpurple/tests/test_notification_manager.c
@@ -173,14 +173,14 @@
 	account = purple_account_new("test", "test");
 
 	/* Make sure that nothing happens on an empty list. */
-	purple_notification_manager_remove_with_account(manager, account);
+	purple_notification_manager_remove_with_account(manager, account, TRUE);
 	g_assert_cmpuint(0, ==, g_list_model_get_n_items(model));
 
 	/* Add a single notification without the account */
 	notification = purple_notification_new(PURPLE_NOTIFICATION_TYPE_GENERIC,
 	                                       NULL, NULL, NULL);
 	purple_notification_manager_add(manager, notification);
-	purple_notification_manager_remove_with_account(manager, account);
+	purple_notification_manager_remove_with_account(manager, account, TRUE);
 	g_assert_cmpuint(1, ==, g_list_model_get_n_items(model));
 	g_list_store_remove_all(G_LIST_STORE(model));
 	g_clear_object(&notification);
@@ -189,7 +189,7 @@
 	notification = purple_notification_new(PURPLE_NOTIFICATION_TYPE_GENERIC,
 	                                       account, NULL, NULL);
 	purple_notification_manager_add(manager, notification);
-	purple_notification_manager_remove_with_account(manager, account);
+	purple_notification_manager_remove_with_account(manager, account, TRUE);
 	g_assert_cmpuint(0, ==, g_list_model_get_n_items(model));
 	g_list_store_remove_all(G_LIST_STORE(model));
 	g_clear_object(&notification);
@@ -224,9 +224,19 @@
 	}
 
 	g_assert_cmpuint(14, ==, g_list_model_get_n_items(model));
-	purple_notification_manager_remove_with_account(manager, accounts[0]);
+
+	/* Remove notifications for accounts[0]. */
+	purple_notification_manager_remove_with_account(manager, accounts[0], TRUE);
 	g_assert_cmpuint(6, ==, g_list_model_get_n_items(model));
 
+	/* Remove notifications for accounts[1]. */
+	purple_notification_manager_remove_with_account(manager, accounts[1], TRUE);
+	g_assert_cmpuint(2, ==, g_list_model_get_n_items(model));
+
+	/* Remove notifications for accounts[2]. */
+	purple_notification_manager_remove_with_account(manager, accounts[2], TRUE);
+	g_assert_cmpuint(0, ==, g_list_model_get_n_items(model));
+
 	g_clear_object(&manager);
 	g_clear_object(&accounts[0]);
 	g_clear_object(&accounts[1]);
@@ -234,6 +244,88 @@
 }
 
 static void
+test_purple_notification_manager_remove_with_account_all(void) {
+	PurpleNotificationManager *manager = NULL;
+	PurpleNotification *notification = NULL;
+	PurpleAccount *account = NULL;
+	GListModel *model = NULL;
+
+	/* This test will add 3 notifications to the notification manager for the
+	 * same account. In order, they will be of types generic, connection error,
+	 * and generic. We will also add a generic notification with no account, to
+	 * make sure notifications don't accidentally get removed.
+	 *
+	 * This ordering is specifically done because we batch remove items from
+	 * the list. So by calling purple_notification_manager_remove_with_account
+	 * with `all` set to FALSE, we should remove the first and third items,
+	 * but leave the second and fourth items.
+	 *
+	 * We then call purple_notification_manager_remove_with_account with `all`
+	 * set to TRUE, which will remove the connection error notification which
+	 * is now the first item.
+	 *
+	 * Finally, we empty the manager and verify that its count is at 0.
+	 */
+
+	manager = g_object_new(PURPLE_TYPE_NOTIFICATION_MANAGER, NULL);
+	model = purple_notification_manager_get_model(manager);
+	account = purple_account_new("test", "test");
+
+	/* Make sure that nothing happens on an empty list. */
+	purple_notification_manager_remove_with_account(manager, account, TRUE);
+	g_assert_cmpuint(0, ==, g_list_model_get_n_items(model));
+
+	/* Add a generic notification with an account. */
+	notification = purple_notification_new(PURPLE_NOTIFICATION_TYPE_GENERIC,
+	                                       account, NULL, NULL);
+	purple_notification_manager_add(manager, notification);
+	g_clear_object(&notification);
+
+	/* Add a connection error notification with the account. */
+	notification = purple_notification_new(PURPLE_NOTIFICATION_TYPE_CONNECTION_ERROR,
+	                                       account, NULL, NULL);
+	purple_notification_manager_add(manager, notification);
+	g_clear_object(&notification);
+
+	/* Add a generic notification with the account. */
+	notification = purple_notification_new(PURPLE_NOTIFICATION_TYPE_GENERIC,
+	                                       account, NULL, NULL);
+	purple_notification_manager_add(manager, notification);
+	g_clear_object(&notification);
+
+	/* Add a generic notification without an account. */
+	notification = purple_notification_new(PURPLE_NOTIFICATION_TYPE_GENERIC,
+	                                       NULL, NULL, NULL);
+	purple_notification_manager_add(manager, notification);
+	g_clear_object(&notification);
+
+
+	/* Verify that we have all of the notifications in the manager. */
+	g_assert_cmpuint(4, ==, g_list_model_get_n_items(model));
+
+	/* Remove the transient notifications for the account. */
+	purple_notification_manager_remove_with_account(manager, account, FALSE);
+	g_assert_cmpuint(2, ==, g_list_model_get_n_items(model));
+
+	/* Make sure that the first item is the connection error. */
+	notification = g_list_model_get_item(G_LIST_MODEL(model), 0);
+	g_assert_cmpint(purple_notification_get_notification_type(notification),
+	                ==, PURPLE_NOTIFICATION_TYPE_CONNECTION_ERROR);
+	g_clear_object(&notification);
+
+	/* Remove the non-transient notifications for the account. */
+	purple_notification_manager_remove_with_account(manager, account, TRUE);
+	g_assert_cmpuint(1, ==, g_list_model_get_n_items(model));
+
+	/* Remove the generic notification that's not tied to an account. */
+	g_list_store_remove_all(G_LIST_STORE(model));
+	g_assert_cmpuint(0, ==, g_list_model_get_n_items(model));
+
+	g_clear_object(&manager);
+	g_clear_object(&account);
+}
+
+static void
 test_purple_notification_manager_read_propagation(void) {
 	PurpleNotificationManager *manager = NULL;
 	PurpleNotification *notification = NULL;
@@ -319,6 +411,8 @@
 	                test_purple_notification_manager_remove_with_account_simple);
 	g_test_add_func("/notification-manager/remove-with-account/mixed",
 	                test_purple_notification_manager_remove_with_account_mixed);
+	g_test_add_func("/notification-manager/remove-with-account/all",
+	                test_purple_notification_manager_remove_with_account_all);
 
 	g_test_add_func("/notification-manager/read-propagation",
 	                test_purple_notification_manager_read_propagation);
diff --git a/pidgin/pidginaccountmanager.c b/pidgin/pidginaccountmanager.c
--- a/pidgin/pidginaccountmanager.c
+++ b/pidgin/pidginaccountmanager.c
@@ -210,6 +210,7 @@
 {
 	PidginAccountManager *manager = PIDGIN_ACCOUNT_MANAGER(dialog);
 	PurpleAccount *account = NULL;
+	PurpleNotificationManager *notification_manager = NULL;
 	GtkWidget *editor = NULL;
 
 	switch(response_id) {
@@ -232,6 +233,9 @@
 		case RESPONSE_REMOVE:
 			account = pidgin_account_manager_get_selected_account(manager);
 
+			notification_manager = purple_notification_manager_get_default();
+			purple_notification_manager_remove_with_account(notification_manager,
+			                                                account, TRUE);
 			purple_accounts_delete(account);
 
 			g_clear_object(&account);
