pidgin/pidgin

Make PurpleRequestFieldAccount work like a GtkCustomFilter

12 months ago, Elliott Sales de Andrade
0d14fedafd4a
Parents 7c16e3b1cce8
Children 6996b5faa09e
Make PurpleRequestFieldAccount work like a GtkCustomFilter

This makes the filtering better for introspection.

Also, fixed an incorrect type check.

Testing Done:
Enabled Demo and XMPP accounts, then tried the I'dle Mak'er plugin and confirmed that only XMPP showed in its "Set Account Idle Time" action request.

Bugs closed: PIDGIN-17780

Reviewed at https://reviews.imfreedom.org/r/2442/
--- a/ChangeLog.API Tue Apr 25 00:46:17 2023 -0500
+++ b/ChangeLog.API Tue Apr 25 01:02:47 2023 -0500
@@ -134,6 +134,9 @@
* 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
--- a/libpurple/account.h Tue Apr 25 00:46:17 2023 -0500
+++ b/libpurple/account.h Tue Apr 25 01:02:47 2023 -0500
@@ -33,8 +33,6 @@
typedef struct _PurpleAccount PurpleAccount;
-typedef gboolean (*PurpleFilterAccountFunc)(PurpleAccount *account);
-
#include "buddy.h"
#include "connection.h"
#include "group.h"
--- a/libpurple/plugins/idle/idle.c Tue Apr 25 00:46:17 2023 -0500
+++ b/libpurple/plugins/idle/idle.c Tue Apr 25 01:02:47 2023 -0500
@@ -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 @@
}
static gboolean
-idleable_filter(PurpleAccount *account)
+idleable_filter(PurpleAccount *account, G_GNUC_UNUSED gpointer data)
{
PurpleProtocol *protocol;
@@ -89,7 +89,7 @@
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 @@
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 @@
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 @@
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);
--- a/libpurple/request/purplerequestfieldaccount.c Tue Apr 25 00:46:17 2023 -0500
+++ b/libpurple/request/purplerequestfieldaccount.c Tue Apr 25 01:02:47 2023 -0500
@@ -33,7 +33,7 @@
PurpleAccount *account;
gboolean show_all;
- PurpleFilterAccountFunc filter_func;
+ GClosure *filter_func;
};
enum {
@@ -108,6 +108,7 @@
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 @@
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 @@
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;
}
--- a/libpurple/request/purplerequestfieldaccount.h Tue Apr 25 00:46:17 2023 -0500
+++ b/libpurple/request/purplerequestfieldaccount.h Tue Apr 25 01:02:47 2023 -0500
@@ -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 @@
/**
* 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 @@
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
--- a/pidgin/gtkrequest.c Tue Apr 25 00:46:17 2023 -0500
+++ b/pidgin/gtkrequest.c Tue Apr 25 01:02:47 2023 -0500
@@ -1192,12 +1192,12 @@
}
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 @@
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 @@
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;