# HG changeset patch
# Node ID fba96a4d56d3
# Parent  3bbd7c175d78
diff --git a/ChangeLog.API b/ChangeLog.API
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -328,6 +328,10 @@
 		* _XMLNodeType
 		* account-added signal. Use PurpleAccountManager::added
 		  instead.
+		* account-disabled signal. Use
+		  PurpleAccountManager::account-changed::enabled instead.
+		* account-enabled signal. Use
+		  PurpleAccountManager::account-changed::enabled instead.
 		* account-alias-changed signal
 		* account-authorization-denied, account-authorization-granted,
 		  account-authorization-requested,
diff --git a/doc/reference/libpurple/signals_account.md b/doc/reference/libpurple/signals_account.md
--- a/doc/reference/libpurple/signals_account.md
+++ b/doc/reference/libpurple/signals_account.md
@@ -7,8 +7,6 @@
 
 * [account-created](#account-created)
 * [account-destroying](#account-destroying)
-* [account-disabled](#account-disabled)
-* [account-enabled](#account-enabled)
 * [account-status-changed](#account-status-changed)
 * [account-actions-changed](#account-actions-changed)
 * [account-error-changed](#account-error-changed)
@@ -53,42 +51,6 @@
 
 ----
 
-#### account-disabled
-
-```c
-void user_function(PurpleAccount *account, gpointer user_data);
-```
-
-Emitted when an account is disabled.
-
-**Parameters:**
-
-**account**
-: The account that was disabled.
-
-**user_data**
-: User data set when the signal handler was connected.
-
-----
-
-#### account-enabled
-
-```c
-void user_function(PurpleAccount *account, gpointer user_data);
-```
-
-Emitted when an account is enabled.
-
-**Parameters**:
-
-**account**
-: The account that was enabled.
-
-**user_data**
-: User data set when the signal handler was connected.
-
-----
-
 #### account-status-changed
 
 ```c
diff --git a/finch/gntaccount.c b/finch/gntaccount.c
--- a/finch/gntaccount.c
+++ b/finch/gntaccount.c
@@ -861,14 +861,6 @@
 	edit_account(account);
 }
 
-static gpointer
-finch_accounts_get_handle(void)
-{
-	static int handle;
-
-	return &handle;
-}
-
 static void
 account_added_callback(G_GNUC_UNUSED PurpleAccountManager *manager,
                        PurpleAccount *account, G_GNUC_UNUSED gpointer data)
@@ -890,12 +882,16 @@
 }
 
 static void
-account_abled_cb(PurpleAccount *account, gpointer user_data)
+account_abled_cb(G_GNUC_UNUSED PurpleAccountManager *manager,
+                 PurpleAccount *account,
+                 G_GNUC_UNUSED gpointer data)
 {
-	if (accounts.window == NULL)
+	if(accounts.window == NULL) {
 		return;
+	}
+
 	gnt_tree_set_choice(GNT_TREE(accounts.tree), account,
-			GPOINTER_TO_INT(user_data));
+	                    purple_account_get_enabled(account));
 }
 
 void
@@ -903,23 +899,17 @@
 {
 	PurpleAccountManager *manager = NULL;
 	GListModel *manager_model = NULL;
-	gpointer account_handle = NULL;
 	guint n_items = 0;
 
 	manager = purple_account_manager_get_default();
 	manager_model = G_LIST_MODEL(manager);
-	account_handle = purple_accounts_get_handle();
 
 	g_signal_connect(manager, "added", G_CALLBACK(account_added_callback),
 	                 NULL);
 	g_signal_connect(manager, "removed", G_CALLBACK(account_removed_callback),
 	                 NULL);
-	purple_signal_connect(account_handle, "account-disabled",
-			finch_accounts_get_handle(),
-			G_CALLBACK(account_abled_cb), GINT_TO_POINTER(FALSE));
-	purple_signal_connect(account_handle, "account-enabled",
-			finch_accounts_get_handle(),
-			G_CALLBACK(account_abled_cb), GINT_TO_POINTER(TRUE));
+	g_signal_connect(manager, "account-changed::enabled",
+	                 G_CALLBACK(account_abled_cb), NULL);
 
 	n_items = g_list_model_get_n_items(manager_model);
 	if(n_items != 0) {
diff --git a/libpurple/account.c b/libpurple/account.c
--- a/libpurple/account.c
+++ b/libpurple/account.c
@@ -1500,15 +1500,11 @@
 
 	was_enabled = account->enabled;
 	account->enabled = value;
+	if(was_enabled != value) {
+		g_object_notify_by_pspec(G_OBJECT(account), properties[PROP_ENABLED]);
+	}
 
 	gc = purple_account_get_connection(account);
-	if(was_enabled && !value)
-		purple_signal_emit(purple_accounts_get_handle(), "account-disabled", account);
-	else if(!was_enabled && value)
-		purple_signal_emit(purple_accounts_get_handle(), "account-enabled", account);
-
-	g_object_notify_by_pspec(G_OBJECT(account), properties[PROP_ENABLED]);
-
 	if ((gc != NULL) && (_purple_connection_wants_to_die(gc)))
 		return;
 
diff --git a/libpurple/accounts.c b/libpurple/accounts.c
--- a/libpurple/accounts.c
+++ b/libpurple/accounts.c
@@ -680,14 +680,6 @@
 	void *handle = purple_accounts_get_handle();
 	void *conn_handle = purple_connections_get_handle();
 
-	purple_signal_register(handle, "account-disabled",
-						 purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
-						 PURPLE_TYPE_ACCOUNT);
-
-	purple_signal_register(handle, "account-enabled",
-						 purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
-						 PURPLE_TYPE_ACCOUNT);
-
 	purple_signal_register(handle, "account-created",
 						 purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
 						 PURPLE_TYPE_ACCOUNT);
diff --git a/libpurple/purpleaccountmanager.c b/libpurple/purpleaccountmanager.c
--- a/libpurple/purpleaccountmanager.c
+++ b/libpurple/purpleaccountmanager.c
@@ -26,6 +26,7 @@
 enum {
 	SIG_ADDED,
 	SIG_REMOVED,
+	SIG_ACCOUNT_CHANGED,
 	N_SIGNALS,
 };
 static guint signals[N_SIGNALS] = {0, };
@@ -39,6 +40,24 @@
 static PurpleAccountManager *default_manager = NULL;
 
 /******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+/* This is the callback for the notify signal on accounts. It re-emits the
+ * signal as coming from the manager and passes the account as a parameter to
+ * the callback. It supports details as well so you can use
+ * g_signal_connect(manager, "account-changed::enabled", ...) to just get
+ * called when an account's enabled property changes.
+ */
+static void
+purple_account_manager_account_notify_cb(GObject *source, GParamSpec *pspec,
+                                         gpointer data)
+{
+	g_signal_emit(data, signals[SIG_ACCOUNT_CHANGED],
+	              g_param_spec_get_name_quark(pspec),
+	              source);
+}
+
+/******************************************************************************
  * GListModel Implementation
  *****************************************************************************/
 static GType
@@ -144,6 +163,33 @@
 		G_TYPE_NONE,
 		1,
 		PURPLE_TYPE_ACCOUNT);
+
+	/**
+	 * PurpleAccountManager::account-changed:
+	 * @manager: The account manager instance.
+	 * @account: The account that was changed.
+	 *
+	 * This is a propagation of the notify signal from @account. This means
+	 * that your callback will be called for any account that @manager knows
+	 * about.
+	 *
+	 * This also supports details, so you can specify the signal name as
+	 * something like `account-changed::enabled` and your callback will only
+	 * be called when the enabled property of @account has been changed.
+	 *
+	 * Since: 3.0.0
+	 */
+	signals[SIG_ACCOUNT_CHANGED] = g_signal_new_class_handler(
+		"account-changed",
+		G_OBJECT_CLASS_TYPE(klass),
+		G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		G_TYPE_NONE,
+		1,
+		PURPLE_TYPE_ACCOUNT);
 }
 
 /******************************************************************************
@@ -193,6 +239,11 @@
 	 */
 	g_ptr_array_insert(manager->accounts, 0, account);
 
+	/* Connect to the signals of the account that we want to propagate. */
+	g_signal_connect_object(account, "notify",
+	                        G_CALLBACK(purple_account_manager_account_notify_cb),
+	                        manager, 0);
+
 	purple_accounts_schedule_save();
 
 	g_signal_emit(manager, signals[SIG_ADDED], 0, account);
diff --git a/pidgin/pidginaccountsdisabledmenu.c b/pidgin/pidginaccountsdisabledmenu.c
--- a/pidgin/pidginaccountsdisabledmenu.c
+++ b/pidgin/pidginaccountsdisabledmenu.c
@@ -62,7 +62,8 @@
 }
 
 static void
-pidgin_accounts_disabled_menu_changed_cb(G_GNUC_UNUSED PurpleAccount *account,
+pidgin_accounts_disabled_menu_changed_cb(G_GNUC_UNUSED PurpleAccountManager *manager,
+                                         G_GNUC_UNUSED PurpleAccount *account,
                                          gpointer data)
 {
 	PidginAccountsDisabledMenu *menu = data;
@@ -182,16 +183,11 @@
 
 static void
 pidgin_accounts_disabled_menu_init(PidginAccountsDisabledMenu *menu) {
-	gpointer handle = NULL;
+	PurpleAccountManager *manager = purple_account_manager_get_default();
 
-	/* Wire up the purple signals we care about. */
-	handle = purple_accounts_get_handle();
-	purple_signal_connect(handle, "account-enabled", menu,
-	                      G_CALLBACK(pidgin_accounts_disabled_menu_changed_cb),
-	                      menu);
-	purple_signal_connect(handle, "account-disabled", menu,
-	                      G_CALLBACK(pidgin_accounts_disabled_menu_changed_cb),
-	                      menu);
+	g_signal_connect_object(manager, "account-changed::enabled",
+	                        G_CALLBACK(pidgin_accounts_disabled_menu_changed_cb),
+	                        menu, 0);
 }
 
 static void
diff --git a/pidgin/pidginaccountsenabledmenu.c b/pidgin/pidginaccountsenabledmenu.c
--- a/pidgin/pidginaccountsenabledmenu.c
+++ b/pidgin/pidginaccountsenabledmenu.c
@@ -41,30 +41,30 @@
  * Callbacks
  *****************************************************************************/
 static void
-pidgin_accounts_enabled_menu_enabled_cb(PurpleAccount *account, gpointer data) {
+pidgin_accounts_enabled_menu_changed_cb(G_GNUC_UNUSED PurpleAccountManager *manager,
+                                        PurpleAccount *account,
+                                        gpointer data)
+{
 	PidginAccountsEnabledMenu *menu = data;
 
-	/* Add the account to the start of the list. */
-	g_queue_push_head(menu->accounts, g_object_ref(account));
+	if(purple_account_get_enabled(account)) {
+		/* Add the account to the start of the list. */
+		g_queue_push_head(menu->accounts, g_object_ref(account));
 
-	/* Tell everyone our model added a new item at position 0. */
-	g_menu_model_items_changed(G_MENU_MODEL(menu), 0, 0, 1);
-}
+		/* Tell everyone our model added a new item at position 0. */
+		g_menu_model_items_changed(G_MENU_MODEL(menu), 0, 0, 1);
+	} else {
+		gint index = g_queue_index(menu->accounts, account);
 
-static void
-pidgin_accounts_enabled_menu_disabled_cb(PurpleAccount *account, gpointer data)
-{
-	PidginAccountsEnabledMenu *menu = data;
-	gint index = -1;
+		if(index >= 0) {
+			g_queue_pop_nth(menu->accounts, index);
 
-	index = g_queue_index(menu->accounts, account);
-	if(index >= 0) {
-		g_queue_pop_nth(menu->accounts, index);
+			/* Tell the model that we removed one item at the given index. */
+			g_menu_model_items_changed(G_MENU_MODEL(menu), index, 1, 0);
 
-		/* Tell the model that we removed one item at the given index. */
-		g_menu_model_items_changed(G_MENU_MODEL(menu), index, 1, 0);
-
-		g_object_unref(account);
+			/* Remove the reference to the account that we were holding. */
+			g_object_unref(account);
+		}
 	}
 }
 
@@ -311,18 +311,18 @@
 
 static void
 pidgin_accounts_enabled_menu_init(PidginAccountsEnabledMenu *menu) {
+	PurpleAccountManager *manager = NULL;
 	gpointer handle = NULL;
 
 	menu->accounts = g_queue_new();
 
+	manager = purple_account_manager_get_default();
+	g_signal_connect_object(manager, "account-changed::enabled",
+	                        G_CALLBACK(pidgin_accounts_enabled_menu_changed_cb),
+	                        menu, 0);
+
 	/* Wire up the purple signals we care about. */
 	handle = purple_accounts_get_handle();
-	purple_signal_connect(handle, "account-enabled", menu,
-	                      G_CALLBACK(pidgin_accounts_enabled_menu_enabled_cb),
-	                      menu);
-	purple_signal_connect(handle, "account-disabled", menu,
-	                      G_CALLBACK(pidgin_accounts_enabled_menu_disabled_cb),
-	                      menu);
 
 	/* For the account actions, we also need to know when an account is online
 	 * or offline.
