# HG changeset patch
# Node ID fa0caa4c7138
# Parent  cfa7c940ed62
diff --git a/ChangeLog.API b/ChangeLog.API
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -134,6 +134,9 @@ version 3.0.0 (??/??/????):
 		* PurpleContact and PurpleGroup inherit PurpleCountingNode
 		* PurpleBuddyList is now a GObject. Please see the documentation for
 		  details.
+		* PurpleFilterAccountFunc renamed to
+		  PurpleRequestFieldAccountFilterFunc, and now takes a user
+		  data parameter
 		* purple_find_buddies renamed to purple_blist_find_buddies
 		* purple_find_buddy_in_group renamed to purple_blist_find_buddy_in_group
 		* purple_find_buddy renamed to purple_blist_find_buddy
diff --git a/libpurple/account.h b/libpurple/account.h
--- a/libpurple/account.h
+++ b/libpurple/account.h
@@ -33,8 +33,6 @@
 
 typedef struct _PurpleAccount       PurpleAccount;
 
-typedef gboolean (*PurpleFilterAccountFunc)(PurpleAccount *account);
-
 #include "buddy.h"
 #include "connection.h"
 #include "group.h"
diff --git a/libpurple/plugins/idle/idle.c b/libpurple/plugins/idle/idle.c
--- a/libpurple/plugins/idle/idle.c
+++ b/libpurple/plugins/idle/idle.c
@@ -35,7 +35,7 @@
 static GList *idled_accts = NULL;
 
 static gboolean
-unidle_filter(PurpleAccount *acct)
+unidle_filter(PurpleAccount *acct, G_GNUC_UNUSED gpointer data)
 {
 	if (g_list_find(idled_accts, acct))
 		return TRUE;
@@ -44,7 +44,7 @@ unidle_filter(PurpleAccount *acct)
 }
 
 static gboolean
-idleable_filter(PurpleAccount *account)
+idleable_filter(PurpleAccount *account, G_GNUC_UNUSED gpointer data)
 {
 	PurpleProtocol *protocol;
 
@@ -89,7 +89,7 @@ idle_action_ok(G_GNUC_UNUSED gpointer da
 	int tm = purple_request_page_get_integer(page, "mins");
 
 	/* only add the account to the GList if it's not already been idled */
-	if(!unidle_filter(acct)) {
+	if(!unidle_filter(acct, NULL)) {
 		purple_debug_misc("idle", "%s hasn't been idled yet; adding to list.",
 		                  purple_contact_info_get_username(info));
 		idled_accts = g_list_append(idled_accts, acct);
@@ -110,7 +110,7 @@ idle_all_action_ok(G_GNUC_UNUSED gpointe
 	for(iter = list; iter; iter = iter->next) {
 		acct = (PurpleAccount *)(iter->data);
 
-		if(acct && idleable_filter(acct)) {
+		if(acct && idleable_filter(acct, NULL)) {
 			PurpleContactInfo *info = PURPLE_CONTACT_INFO(acct);
 
 			purple_debug_misc("idle", "Idling %s.\n",
@@ -164,7 +164,7 @@ purple_idle_set_account_idle_time(G_GNUC
 
 	field = purple_request_field_account_new("acct", _("Account"), NULL);
 	afield = PURPLE_REQUEST_FIELD_ACCOUNT(field);
-	purple_request_field_account_set_filter(afield, idleable_filter);
+	purple_request_field_account_set_filter(afield, idleable_filter, NULL, NULL);
 	purple_request_field_account_set_show_all(afield, FALSE);
 	purple_request_group_add_field(group, field);
 
@@ -204,7 +204,7 @@ purple_idle_unset_account_idle_time(G_GN
 
 	field = purple_request_field_account_new("acct", _("Account"), NULL);
 	afield = PURPLE_REQUEST_FIELD_ACCOUNT(field);
-	purple_request_field_account_set_filter(afield, unidle_filter);
+	purple_request_field_account_set_filter(afield, unidle_filter, NULL, NULL);
 	purple_request_field_account_set_show_all(afield, FALSE);
 	purple_request_group_add_field(group, field);
 
diff --git a/libpurple/request/purplerequestfieldaccount.h b/libpurple/request/purplerequestfieldaccount.h
--- a/libpurple/request/purplerequestfieldaccount.h
+++ b/libpurple/request/purplerequestfieldaccount.h
@@ -33,6 +33,22 @@
 #include "account.h"
 #include "purplerequestfield.h"
 
+/**
+ * PurpleRequestFieldAccountFilterFunc:
+ * @account: The account.
+ * @user_data: The data passed to [method@Purple.RequestFieldAccount.set_filter].
+ *
+ * A function that is called to determine if the account should be matched.
+ *
+ * If the filter matches the account, this function must return %TRUE. If the
+ * account should be filtered out, %FALSE must be returned.
+ *
+ * Returns: %TRUE to keep the account.
+ *
+ * Since: 3.0.0
+ */
+typedef gboolean (*PurpleRequestFieldAccountFilterFunc)(PurpleAccount *account, gpointer user_data);
+
 G_BEGIN_DECLS
 
 /**
@@ -93,14 +109,17 @@ void purple_request_field_account_set_sh
 /**
  * purple_request_field_account_set_filter:
  * @field:       The account field.
- * @filter_func: (scope notified): The account filter function.
+ * @filter_func: (scope notified) (closure user_data): The account filter
+ *               function, or %NULL to disable additional filtering.
+ * @user_data: The data to pass to the filter callback.
+ * @destroy_data: A cleanup function for @user_data.
  *
  * Sets the account filter function in an account field.
  *
  * This function will determine which accounts get displayed and which
  * don't.
  */
-void purple_request_field_account_set_filter(PurpleRequestFieldAccount *field, PurpleFilterAccountFunc filter_func);
+void purple_request_field_account_set_filter(PurpleRequestFieldAccount *field, PurpleRequestFieldAccountFilterFunc filter_func, gpointer user_data, GDestroyNotify destroy_data);
 
 /**
  * purple_request_field_account_get_default_value:
@@ -136,17 +155,17 @@ PurpleAccount *purple_request_field_acco
 gboolean purple_request_field_account_get_show_all(PurpleRequestFieldAccount *field);
 
 /**
- * purple_request_field_account_get_filter: (skip):
+ * purple_request_field_account_match:
  * @field: The account field.
+ * @account: The account to check.
  *
- * Returns the account filter function in an account field.
+ * Returns whether the specified account is matched by the filter or not.
  *
- * This function will determine which accounts get displayed and which
- * don't.
+ * Returns: Whether or not to show the account.
  *
- * Returns: (transfer none): The account filter function.
+ * Since: 3.0.0
  */
-PurpleFilterAccountFunc purple_request_field_account_get_filter(PurpleRequestFieldAccount *field);
+gboolean purple_request_field_account_match(PurpleRequestFieldAccount *field, PurpleAccount *account);
 
 G_END_DECLS
 
diff --git a/libpurple/request/purplerequestfieldaccount.c b/libpurple/request/purplerequestfieldaccount.c
--- a/libpurple/request/purplerequestfieldaccount.c
+++ b/libpurple/request/purplerequestfieldaccount.c
@@ -33,7 +33,7 @@ struct _PurpleRequestFieldAccount {
 	PurpleAccount *account;
 	gboolean show_all;
 
-	PurpleFilterAccountFunc filter_func;
+	GClosure *filter_func;
 };
 
 enum {
@@ -108,6 +108,7 @@ purple_request_field_account_finalize(GO
 
 	g_clear_object(&field->default_account);
 	g_clear_object(&field->account);
+	g_clear_pointer(&field->filter_func, g_closure_unref);
 
 	G_OBJECT_CLASS(purple_request_field_account_parent_class)->finalize(obj);
 }
@@ -261,11 +262,20 @@ purple_request_field_account_set_show_al
 
 void
 purple_request_field_account_set_filter(PurpleRequestFieldAccount *field,
-                                        PurpleFilterAccountFunc filter_func)
+                                        PurpleRequestFieldAccountFilterFunc filter_func,
+                                        gpointer user_data,
+                                        GDestroyNotify destroy_data)
 {
 	g_return_if_fail(PURPLE_IS_REQUEST_FIELD_ACCOUNT(field));
 
-	field->filter_func = filter_func;
+	g_clear_pointer(&field->filter_func, g_closure_unref);
+	if(filter_func != NULL) {
+		field->filter_func = g_cclosure_new(G_CALLBACK(filter_func), user_data,
+		                                    (GClosureNotify)G_CALLBACK(destroy_data));
+		g_closure_ref(field->filter_func);
+		g_closure_sink(field->filter_func);
+		g_closure_set_marshal(field->filter_func, g_cclosure_marshal_generic);
+	}
 }
 
 PurpleAccount *
@@ -285,14 +295,34 @@ purple_request_field_account_get_value(P
 
 gboolean
 purple_request_field_account_get_show_all(PurpleRequestFieldAccount *field) {
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_ACCOUNT(field), FALSE);
 
 	return field->show_all;
 }
 
-PurpleFilterAccountFunc
-purple_request_field_account_get_filter(PurpleRequestFieldAccount *field) {
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
+gboolean
+purple_request_field_account_match(PurpleRequestFieldAccount *field,
+                                   PurpleAccount *account)
+{
+	gboolean ret = TRUE;
+
+	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_ACCOUNT(field), FALSE);
 
-	return field->filter_func;
+	if(field->filter_func != NULL) {
+		GValue result = G_VALUE_INIT;
+		GValue params[] = {G_VALUE_INIT};
+		g_value_init(&result, G_TYPE_BOOLEAN);
+		g_value_set_instance(g_value_init(&params[0], PURPLE_TYPE_ACCOUNT),
+		                     account);
+		g_closure_invoke(field->filter_func, &result,
+		                 G_N_ELEMENTS(params), params, NULL);
+		ret = g_value_get_boolean(&result);
+		g_value_unset(&result);
+		for(gsize i = 0; i < G_N_ELEMENTS(params); i++) {
+			g_value_unset(&params[i]);
+		}
+	}
+
+
+	return ret;
 }
diff --git a/pidgin/gtkrequest.c b/pidgin/gtkrequest.c
--- a/pidgin/gtkrequest.c
+++ b/pidgin/gtkrequest.c
@@ -1192,12 +1192,12 @@ create_image_field(PurpleRequestField *f
 }
 
 static gboolean
-field_custom_account_filter_cb(gpointer item, G_GNUC_UNUSED gpointer data) {
-	PurpleFilterAccountFunc func = data;
+field_custom_account_filter_cb(gpointer item, gpointer data) {
+	PurpleRequestFieldAccount *field = data;
 	gboolean ret = FALSE;
 
 	if(PURPLE_IS_ACCOUNT(item)) {
-		ret = func(PURPLE_ACCOUNT(item));
+		ret = purple_request_field_account_match(field, PURPLE_ACCOUNT(item));
 	}
 
 	return ret;
@@ -1209,7 +1209,7 @@ create_account_field(PurpleRequestField 
 	PurpleRequestFieldAccount *afield = NULL;
 	GtkWidget *widget = NULL;
 	PurpleAccount *account = NULL;
-	PurpleFilterAccountFunc account_filter = NULL;
+	GtkCustomFilter *custom_filter = NULL;
 	GtkFilter *filter = NULL;
 	const char *type_hint = NULL;
 
@@ -1217,15 +1217,9 @@ create_account_field(PurpleRequestField 
 	afield = PURPLE_REQUEST_FIELD_ACCOUNT(field);
 	account = purple_request_field_account_get_default_value(afield);
 
-	account_filter = purple_request_field_account_get_filter(afield);
-	if(account_filter != NULL) {
-		GtkCustomFilter *custom_filter = NULL;
-
-		custom_filter = gtk_custom_filter_new(field_custom_account_filter_cb,
-		                                      account_filter, NULL);
-
-		filter = GTK_FILTER(custom_filter);
-	}
+	custom_filter = gtk_custom_filter_new(field_custom_account_filter_cb,
+	                                      afield, NULL);
+	filter = GTK_FILTER(custom_filter);
 
 	if(!purple_request_field_account_get_show_all(afield)) {
 		GtkEveryFilter *every = NULL;
