Convert PurpleRequestPage into a GObject

Tue, 07 Mar 2023 01:04:42 -0600

author
Elliott Sales de Andrade <quantum.analyst@gmail.com>
date
Tue, 07 Mar 2023 01:04:42 -0600
changeset 42128
118067ca0367
parent 42127
18acb99a0fa6
child 42129
7b3a4ffa7227

Convert PurpleRequestPage into a GObject

And rename it from `PurpleRequestFields`.

Also, implements `GListModel` for the groups, but nothing uses it that way get.

Testing Done:
Compiled, and opened Request Fields from Demo protocol.

Reviewed at https://reviews.imfreedom.org/r/2323/

ChangeLog.API file | annotate | diff | comparison | revisions
finch/gntblist.c file | annotate | diff | comparison | revisions
finch/gntplugin.c file | annotate | diff | comparison | revisions
finch/gntprefs.c file | annotate | diff | comparison | revisions
finch/gntrequest.c file | annotate | diff | comparison | revisions
finch/gntrequest.h file | annotate | diff | comparison | revisions
libpurple/account.c file | annotate | diff | comparison | revisions
libpurple/plugins/idle/idle.c file | annotate | diff | comparison | revisions
libpurple/protocols/demo/purpledemoprotocolactions.c file | annotate | diff | comparison | revisions
libpurple/protocols/facebook/util.c file | annotate | diff | comparison | revisions
libpurple/protocols/gg/multilogon.c file | annotate | diff | comparison | revisions
libpurple/protocols/gg/pubdir-prpl.c file | annotate | diff | comparison | revisions
libpurple/protocols/gg/status.c file | annotate | diff | comparison | revisions
libpurple/protocols/jabber/auth.c file | annotate | diff | comparison | revisions
libpurple/protocols/jabber/buddy.c file | annotate | diff | comparison | revisions
libpurple/protocols/jabber/jabber.c file | annotate | diff | comparison | revisions
libpurple/protocols/jabber/si.c file | annotate | diff | comparison | revisions
libpurple/protocols/jabber/xdata.c file | annotate | diff | comparison | revisions
libpurple/purplechatconversation.c file | annotate | diff | comparison | revisions
libpurple/purpleprivate.h file | annotate | diff | comparison | revisions
libpurple/purplerequestgroup.c file | annotate | diff | comparison | revisions
libpurple/purplerequestgroup.h file | annotate | diff | comparison | revisions
libpurple/purplerequestpage.c file | annotate | diff | comparison | revisions
libpurple/purplerequestpage.h file | annotate | diff | comparison | revisions
libpurple/request.c file | annotate | diff | comparison | revisions
libpurple/request.h file | annotate | diff | comparison | revisions
libpurple/tests/test_credential_manager.c file | annotate | diff | comparison | revisions
pidgin/gtkdialogs.c file | annotate | diff | comparison | revisions
pidgin/gtkrequest.c file | annotate | diff | comparison | revisions
pidgin/pidginmooddialog.c file | annotate | diff | comparison | revisions
--- a/ChangeLog.API	Tue Mar 07 00:22:36 2023 -0600
+++ b/ChangeLog.API	Tue Mar 07 01:04:42 2023 -0600
@@ -238,6 +238,8 @@
 		* PurpleRequestFieldGroup is now a GObject, and renamed to
 		  PurpleRequestGroup. Please see the documentation for
 		  details.
+		* PurpleRequestFields is now a GObject, and renamed to
+		  PurpleRequestPage. Please see the documentation for details.
 		* purple_request_field_get_field_type_hint renamed to
 		  purple_request_field_get_type_hint
 		* purple_request_field_group_get_tab
@@ -720,6 +722,7 @@
 		* purple_request_field_set_ui_data
 		* purple_request_field_group_destroy. Use g_object_unref
 		  instead.
+		* purple_request_fields_destroy. Use g_object_unref instead.
 		* purple_request_fields_get_autosensitive
 		* PurpleRoomlistRoomType
 		* purple_roomlist_expand_category
--- a/finch/gntblist.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/finch/gntblist.c	Tue Mar 07 01:04:42 2023 -0600
@@ -530,13 +530,12 @@
 }
 
 static void
-add_buddy_cb(G_GNUC_UNUSED gpointer data, PurpleRequestFields *allfields)
-{
-	const char *username = purple_request_fields_get_string(allfields, "screenname");
-	const char *alias = purple_request_fields_get_string(allfields, "alias");
-	const char *group = purple_request_fields_get_string(allfields, "group");
-	const char *invite = purple_request_fields_get_string(allfields, "invite");
-	PurpleAccount *account = purple_request_fields_get_account(allfields, "account");
+add_buddy_cb(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
+	const char *username = purple_request_page_get_string(page, "screenname");
+	const char *alias = purple_request_page_get_string(page, "alias");
+	const char *group = purple_request_page_get_string(page, "group");
+	const char *invite = purple_request_page_get_string(page, "invite");
+	PurpleAccount *account = purple_request_page_get_account(page, "account");
 	const char *error = NULL;
 	PurpleGroup *grp;
 	PurpleBuddy *buddy;
@@ -582,11 +581,11 @@
                         PurpleAccount *account, const char *username,
                         const char *grp, const char *alias)
 {
-	PurpleRequestFields *fields = purple_request_fields_new();
+	PurpleRequestPage *page = purple_request_page_new();
 	PurpleRequestGroup *group = purple_request_group_new(NULL);
 	PurpleRequestField *field;
 
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("screenname", _("Username"), username, FALSE);
 	purple_request_group_add_field(group, field);
@@ -608,7 +607,7 @@
 	purple_request_group_add_field(group, field);
 
 	purple_request_fields(NULL, _("Add Buddy"), NULL, _("Please enter buddy information."),
-			fields,
+			page,
 			_("Add"), G_CALLBACK(add_buddy_cb),
 			_("Cancel"), NULL,
 			purple_request_cpar_from_account(account),
@@ -636,8 +635,7 @@
 }
 
 static void
-add_chat_cb(G_GNUC_UNUSED gpointer data, PurpleRequestFields *allfields)
-{
+add_chat_cb(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
 	PurpleAccount *account;
 	const char *alias, *name, *group;
 	PurpleChat *chat;
@@ -647,11 +645,11 @@
 	gboolean autojoin;
 	PurpleProtocol *protocol;
 
-	account = purple_request_fields_get_account(allfields, "account");
-	name = purple_request_fields_get_string(allfields, "name");
-	alias = purple_request_fields_get_string(allfields, "alias");
-	group = purple_request_fields_get_string(allfields, "group");
-	autojoin = purple_request_fields_get_bool(allfields, "autojoin");
+	account = purple_request_page_get_account(page, "account");
+	name = purple_request_page_get_string(page, "name");
+	alias = purple_request_page_get_string(page, "alias");
+	group = purple_request_page_get_string(page, "group");
+	autojoin = purple_request_page_get_bool(page, "autojoin");
 
 	if (!purple_account_is_connected(account) || !name || !*name)
 		return;
@@ -684,11 +682,11 @@
                        PurpleAccount *account, PurpleGroup *grp,
                        const char *alias, const char *name)
 {
-	PurpleRequestFields *fields = purple_request_fields_new();
+	PurpleRequestPage *page = purple_request_page_new();
 	PurpleRequestGroup *group = purple_request_group_new(NULL);
 	PurpleRequestField *field;
 
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_account_new("account", _("Account"), NULL);
 	purple_request_field_account_set_show_all(field, FALSE);
@@ -711,7 +709,7 @@
 
 	purple_request_fields(NULL, _("Add Chat"), NULL,
 			_("You can edit more information from the context menu later."),
-			fields, _("Add"), G_CALLBACK(add_chat_cb), _("Cancel"), NULL,
+			page, _("Add"), G_CALLBACK(add_chat_cb), _("Cancel"), NULL,
 			NULL, NULL);
 }
 
@@ -980,11 +978,13 @@
 }
 
 static void
-chat_components_edit_ok(PurpleChat *chat, PurpleRequestFields *allfields)
+chat_components_edit_ok(PurpleChat *chat, PurpleRequestPage *page)
 {
 	GList *groups, *fields;
 
-	for (groups = purple_request_fields_get_groups(allfields); groups; groups = groups->next) {
+	for(groups = purple_request_page_get_groups(page); groups;
+	    groups = groups->next)
+	{
 		fields = purple_request_group_get_fields(groups->data);
 		for (; fields; fields = fields->next) {
 			PurpleRequestField *field = fields->data;
@@ -1009,7 +1009,7 @@
 static void
 chat_components_edit(G_GNUC_UNUSED PurpleBlistNode *selected, PurpleChat *chat)
 {
-	PurpleRequestFields *fields = purple_request_fields_new();
+	PurpleRequestPage *page = purple_request_page_new();
 	PurpleRequestGroup *group = purple_request_group_new(NULL);
 	PurpleRequestField *field;
 	GList *parts, *iter;
@@ -1017,7 +1017,7 @@
 	PurpleProtocolChatEntry *pce;
 	PurpleConnection *gc;
 
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	gc = purple_account_get_connection(purple_chat_get_account(chat));
 	protocol = purple_connection_get_protocol(gc);
@@ -1048,7 +1048,7 @@
 	g_list_free(parts);
 
 	purple_request_fields(NULL, _("Edit Chat"), NULL, _("Please Update the necessary fields."),
-			fields, _("Edit"), G_CALLBACK(chat_components_edit_ok), _("Cancel"), NULL,
+			page, _("Edit"), G_CALLBACK(chat_components_edit_ok), _("Cancel"), NULL,
 			NULL, chat);
 }
 
@@ -2518,14 +2518,13 @@
 
 /* send_im_select* -- Xerox */
 static void
-send_im_select_cb(G_GNUC_UNUSED gpointer data, PurpleRequestFields *fields)
-{
+send_im_select_cb(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
 	PurpleAccount *account;
 	const char *username;
 	PurpleConversation *im;
 
-	account  = purple_request_fields_get_account(fields, "account");
-	username = purple_request_fields_get_string(fields,  "screenname");
+	account = purple_request_page_get_account(page, "account");
+	username = purple_request_page_get_string(page, "screenname");
 
 	im = purple_im_conversation_new(account, username);
 	purple_conversation_present(im);
@@ -2534,14 +2533,14 @@
 static void
 send_im_select(G_GNUC_UNUSED GntMenuItem *item, G_GNUC_UNUSED gpointer n)
 {
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("screenname", _("Name"), NULL, FALSE);
 	purple_request_field_set_type_hint(field, "screenname");
@@ -2560,13 +2559,12 @@
 	        purple_blist_get_default(), _("New Instant Message"), NULL,
 	        _("Please enter the username or alias of the person "
 	          "you would like to IM."),
-	        fields, _("OK"), G_CALLBACK(send_im_select_cb), _("Cancel"),
+	        page, _("OK"), G_CALLBACK(send_im_select_cb), _("Cancel"),
 	        NULL, NULL, NULL);
 }
 
 static void
-join_chat_select_cb(G_GNUC_UNUSED gpointer data, PurpleRequestFields *fields)
-{
+join_chat_select_cb(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
 	PurpleAccount *account;
 	const char *name;
 	PurpleConnection *gc;
@@ -2575,8 +2573,8 @@
 	GHashTable *hash = NULL;
 	PurpleConversation *conv;
 
-	account = purple_request_fields_get_account(fields, "account");
-	name = purple_request_fields_get_string(fields,  "chat");
+	account = purple_request_page_get_account(page, "account");
+	name = purple_request_page_get_string(page, "chat");
 
 	if (!purple_account_is_connected(account))
 		return;
@@ -2610,14 +2608,14 @@
 static void
 join_chat_select(G_GNUC_UNUSED GntMenuItem *item, G_GNUC_UNUSED gpointer n)
 {
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("chat", _("Channel"), NULL, FALSE);
 	purple_request_field_set_required(field, TRUE);
@@ -2634,7 +2632,7 @@
 	purple_request_fields(
 	        purple_blist_get_default(), _("Join a Chat"), NULL,
 	        _("Please enter the name of the chat you want to join."),
-	        fields, _("Join"), G_CALLBACK(join_chat_select_cb), _("Cancel"),
+	        page, _("Join"), G_CALLBACK(join_chat_select_cb), _("Cancel"),
 	        NULL, NULL, NULL);
 }
 
--- a/finch/gntplugin.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/finch/gntplugin.c	Tue Mar 07 01:04:42 2023 -0600
@@ -534,13 +534,13 @@
 process_pref_frame(PurplePluginPrefFrame *frame)
 {
 	PurpleRequestField *field;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group = NULL;
 	GList *prefs;
 	GList *stringlist = NULL;
 	GntWidget *ret = NULL;
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 
 	for (prefs = purple_plugin_pref_frame_get_prefs(frame); prefs; prefs = prefs->next) {
 		PurplePluginPref *pref = prefs->data;
@@ -556,7 +556,7 @@
 				purple_request_group_add_field(group, field);
 			} else {
 				group = purple_request_group_new(label);
-				purple_request_fields_add_group(fields, group);
+				purple_request_page_add_group(page, group);
 			}
 			continue;
 		}
@@ -624,13 +624,13 @@
 		if (field) {
 			if (group == NULL) {
 				group = purple_request_group_new(_("Preferences"));
-				purple_request_fields_add_group(fields, group);
+				purple_request_page_add_group(page, group);
 			}
 			purple_request_group_add_field(group, field);
 		}
 	}
 
-	ret = purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields,
+	ret = purple_request_fields(NULL, _("Preferences"), NULL, NULL, page,
 			_("Save"), G_CALLBACK(finch_request_save_in_prefs), _("Cancel"), NULL,
 			NULL, NULL);
 	g_signal_connect_swapped(G_OBJECT(ret), "destroy", G_CALLBACK(free_stringlist), stringlist);
--- a/finch/gntprefs.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/finch/gntprefs.c	Tue Mar 07 01:04:42 2023 -0600
@@ -230,21 +230,19 @@
 }
 
 static void
-save_cb(void *data, PurpleRequestFields *allfields)
-{
-	finch_request_save_in_prefs(data, allfields);
+save_cb(void *data, PurpleRequestPage *page) {
+	finch_request_save_in_prefs(data, page);
 	free_strings();
 }
 
 static void
-add_pref_group(PurpleRequestFields *fields, const char *title, Prefs *prefs)
-{
+add_pref_group(PurpleRequestPage *page, const char *title, Prefs *prefs) {
 	PurpleRequestField *field;
 	PurpleRequestGroup *group;
 	int i;
 
 	group = purple_request_group_new(title);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 	for (i = 0; prefs[i].pref; i++)
 	{
 		field = get_pref_field(prefs + i);
@@ -256,22 +254,22 @@
 void
 finch_prefs_show_all(void)
 {
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 
 	if (pref_request.showing) {
 		gnt_window_present(pref_request.window);
 		return;
 	}
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 
-	add_pref_group(fields, _("Buddy List"), blist);
-	add_pref_group(fields, _("Conversations"), convs);
-	add_pref_group(fields, _("Idle"), idle);
-	add_pref_group(fields, _("Credentials"), credentials);
+	add_pref_group(page, _("Buddy List"), blist);
+	add_pref_group(page, _("Conversations"), convs);
+	add_pref_group(page, _("Idle"), idle);
+	add_pref_group(page, _("Credentials"), credentials);
 
 	pref_request.showing = TRUE;
-	pref_request.window = purple_request_fields(NULL, _("Preferences"), NULL, NULL, fields,
+	pref_request.window = purple_request_fields(NULL, _("Preferences"), NULL, NULL, page,
 			_("Save"), G_CALLBACK(save_cb), _("Cancel"), free_strings,
 			NULL, NULL);
 }
--- a/finch/gntrequest.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/finch/gntrequest.c	Tue Mar 07 01:04:42 2023 -0600
@@ -167,14 +167,8 @@
 }
 
 static void
-finch_close_request(PurpleRequestType type, gpointer ui_handle)
-{
+finch_close_request(G_GNUC_UNUSED PurpleRequestType type, gpointer ui_handle) {
 	GntWidget *widget = GNT_WIDGET(ui_handle);
-	if (type == PURPLE_REQUEST_FIELDS) {
-		PurpleRequestFields *fields = g_object_get_data(G_OBJECT(widget), "fields");
-		purple_request_fields_destroy(fields);
-	}
-
 	widget = gnt_widget_get_toplevel(widget);
 	gnt_widget_destroy(widget);
 }
@@ -278,8 +272,7 @@
 }
 
 static void
-request_fields_cb(GntWidget *button, PurpleRequestFields *fields)
-{
+request_fields_cb(GntWidget *button, PurpleRequestPage *page) {
 	PurpleRequestFieldsCb callback = g_object_get_data(G_OBJECT(button), "activate-callback");
 	gpointer data = g_object_get_data(G_OBJECT(button), "activate-userdata");
 	GList *list;
@@ -290,8 +283,7 @@
 	 * instantly whenever a change is made. That allows it to make sure the
 	 * 'required' fields are entered before the user can hit OK. It's not the case
 	 * here, although it can be done. */
-	for (list = purple_request_fields_get_groups(fields); list; list = list->next)
-	{
+	for(list = purple_request_page_get_groups(page); list; list = list->next) {
 		PurpleRequestGroup *group = list->data;
 		GList *fields = purple_request_group_get_fields(group);
 
@@ -381,16 +373,17 @@
 	purple_notify_close_with_handle(button);
 
 	if (!g_object_get_data(G_OBJECT(button), "cancellation-function") &&
-			(!purple_request_fields_all_required_filled(fields) ||
-			!purple_request_fields_all_valid(fields))) {
+			(!purple_request_page_all_required_filled(page) ||
+			!purple_request_page_all_valid(page))) {
 		purple_notify_error(button, _("Error"),
 			_("You must properly fill all the required fields."),
 			_("The required fields are underlined."), NULL);
 		return;
 	}
 
-	if (callback)
-		callback(data, fields);
+	if(callback) {
+		callback(data, page);
+	}
 
 	window = gnt_widget_get_toplevel(button);
 	purple_request_close(PURPLE_REQUEST_FIELDS, window);
@@ -583,8 +576,7 @@
 }
 
 static void
-multifield_extra_cb(GntWidget *button, PurpleRequestFields *allfields)
-{
+multifield_extra_cb(GntWidget *button, PurpleRequestPage *page) {
 	PurpleRequestFieldsCb cb;
 	gpointer cb_data;
 	gpointer handle;
@@ -593,8 +585,9 @@
 	cb = g_object_get_data(G_OBJECT(button), "extra-cb");
 	cb_data = g_object_get_data(G_OBJECT(button), "extra-cb-data");
 
-	if (cb != NULL)
-		cb(cb_data, allfields);
+	if(cb != NULL) {
+		cb(cb_data, page);
+	}
 
 	action_performed(button, handle);
 	purple_request_close(PURPLE_REQUEST_FIELDS, handle);
@@ -602,7 +595,7 @@
 
 static void *
 finch_request_fields(const char *title, const char *primary,
-		const char *secondary, PurpleRequestFields *allfields,
+		const char *secondary, PurpleRequestPage *page,
 		const char *ok, GCallback ok_cb,
 		const char *cancel, GCallback cancel_cb,
 		PurpleRequestCommonParameters *cpar,
@@ -623,7 +616,8 @@
 	box = gnt_vbox_new(FALSE);
 	gnt_box_set_pad(GNT_BOX(box), 0);
 	gnt_box_set_fill(GNT_BOX(box), TRUE);
-	for (grlist = purple_request_fields_get_groups(allfields); grlist; grlist = grlist->next)
+	for(grlist = purple_request_page_get_groups(page); grlist;
+	    grlist = grlist->next)
 	{
 		PurpleRequestGroup *group = grlist->data;
 		GList *fields = purple_request_group_get_fields(group);
@@ -684,8 +678,8 @@
 	}
 	gnt_box_add_widget(GNT_BOX(window), box);
 
-	box = setup_button_box(window, userdata, request_fields_cb, allfields,
-			ok, ok_cb, cancel, cancel_cb, NULL);
+	box = setup_button_box(window, userdata, request_fields_cb, page,
+	                       ok, ok_cb, cancel, cancel_cb, NULL);
 
 	extra_actions = purple_request_cpar_get_extra_actions(cpar);
 	for (GSList *it = extra_actions; it; it = it->next) {
@@ -697,7 +691,7 @@
 		g_object_set_data(G_OBJECT(button), "extra-cb", extra_action->value);
 		g_object_set_data(G_OBJECT(button), "extra-cb-data", userdata);
 		g_signal_connect(G_OBJECT(button), "activate",
-			G_CALLBACK(multifield_extra_cb), allfields);
+		                 G_CALLBACK(multifield_extra_cb), page);
 	}
 
 	help_cb = purple_request_cpar_get_help_cb(cpar, &help_data);
@@ -717,7 +711,7 @@
 		g_signal_connect(username, "completion", G_CALLBACK(update_selected_account), accountlist);
 	}
 
-	g_object_set_data(G_OBJECT(window), "fields", allfields);
+	g_object_set_data_full(G_OBJECT(window), "fields", page, g_object_unref);
 
 	return window;
 }
@@ -857,10 +851,10 @@
 
 void
 finch_request_save_in_prefs(G_GNUC_UNUSED gpointer data,
-                            PurpleRequestFields *allfields)
+                            PurpleRequestPage *page)
 {
 	GList *list;
-	for (list = purple_request_fields_get_groups(allfields); list; list = list->next) {
+	for(list = purple_request_page_get_groups(page); list; list = list->next) {
 		PurpleRequestGroup *group = list->data;
 		GList *fields = purple_request_group_get_fields(group);
 
--- a/finch/gntrequest.h	Tue Mar 07 00:22:36 2023 -0600
+++ b/finch/gntrequest.h	Tue Mar 07 01:04:42 2023 -0600
@@ -61,12 +61,12 @@
 /**
  * finch_request_save_in_prefs:
  * @data: No longer used, set to %NULL.
- * @fields: The #PurpleRequestFields to save.
+ * @page: The #PurpleRequestPage to save.
  *
  * Save the request fields in preferences where the id attribute of each field is the
  * id of a preference.
  */
-void finch_request_save_in_prefs(gpointer data, PurpleRequestFields *fields);
+void finch_request_save_in_prefs(gpointer data, PurpleRequestPage *page);
 
 /**
  * finch_request_field_get_widget:
--- a/libpurple/account.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/account.c	Tue Mar 07 01:04:42 2023 -0600
@@ -227,13 +227,12 @@
 }
 
 static void
-request_password_ok_cb(PurpleAccount *account, PurpleRequestFields *fields)
-{
+request_password_ok_cb(PurpleAccount *account, PurpleRequestPage *page) {
 	const char *entry;
 	gboolean remember;
 
-	entry = purple_request_fields_get_string(fields, "password");
-	remember = purple_request_fields_get_bool(fields, "remember");
+	entry = purple_request_page_get_string(page, "password");
+	remember = purple_request_page_get_bool(page, "remember");
 
 	if (!entry || !*entry)
 	{
@@ -266,7 +265,7 @@
 
 static void
 request_password_cancel_cb(PurpleAccount *account,
-                           G_GNUC_UNUSED PurpleRequestFields *fields)
+                           G_GNUC_UNUSED PurpleRequestPage *page)
 {
 	/* Disable the account as the user has cancelled connecting */
 	purple_account_set_enabled(account, FALSE);
@@ -315,13 +314,12 @@
 }
 
 static void
-change_password_cb(PurpleAccount *account, PurpleRequestFields *fields)
-{
+change_password_cb(PurpleAccount *account, PurpleRequestPage *page) {
 	const char *orig_pass, *new_pass_1, *new_pass_2;
 
-	orig_pass  = purple_request_fields_get_string(fields, "password");
-	new_pass_1 = purple_request_fields_get_string(fields, "new_password_1");
-	new_pass_2 = purple_request_fields_get_string(fields, "new_password_2");
+	orig_pass = purple_request_page_get_string(page, "password");
+	new_pass_1 = purple_request_page_get_string(page, "new_password_1");
+	new_pass_2 = purple_request_page_get_string(page, "new_password_2");
 
 	if (g_utf8_collate(new_pass_1, new_pass_2))
 	{
@@ -332,12 +330,12 @@
 		return;
 	}
 
-	if ((purple_request_fields_is_field_required(fields, "password") &&
-			(orig_pass == NULL || *orig_pass == '\0')) ||
-		(purple_request_fields_is_field_required(fields, "new_password_1") &&
-			(new_pass_1 == NULL || *new_pass_1 == '\0')) ||
-		(purple_request_fields_is_field_required(fields, "new_password_2") &&
-			(new_pass_2 == NULL || *new_pass_2 == '\0')))
+	if((purple_request_page_is_field_required(page, "password") &&
+	    purple_strempty(orig_pass)) ||
+	   (purple_request_page_is_field_required(page, "new_password_1") &&
+	    purple_strempty(new_pass_1)) ||
+	   (purple_request_page_is_field_required(page, "new_password_2") &&
+	    purple_strempty(new_pass_2)))
 	{
 		purple_notify_error(account, NULL,
 			_("Fill out all fields completely."), NULL,
@@ -1065,7 +1063,7 @@
 	const gchar *username;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 
 	/* Close any previous password request windows */
 	purple_request_close_with_handle(account);
@@ -1074,9 +1072,9 @@
 	primary = g_strdup_printf(_("Enter password for %s (%s)"), username,
 								  purple_account_get_protocol_name(account));
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("password", _("Enter Password"), NULL, FALSE);
 	purple_request_field_string_set_masked(field, TRUE);
@@ -1086,7 +1084,7 @@
 	field = purple_request_field_bool_new("remember", _("Save password"), FALSE);
 	purple_request_group_add_field(group, field);
 
-	purple_request_fields(account, NULL, primary, NULL, fields, _("OK"),
+	purple_request_fields(account, NULL, primary, NULL, page, _("OK"),
 		ok_cb, _("Cancel"), cancel_cb,
 		purple_request_cpar_from_account(account), user_data);
 	g_free(primary);
@@ -1095,7 +1093,7 @@
 void
 purple_account_request_change_password(PurpleAccount *account)
 {
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 	PurpleConnection *gc;
@@ -1109,10 +1107,10 @@
 	if (gc != NULL)
 		protocol = purple_connection_get_protocol(gc);
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("password", _("Original password"),
 										  NULL, FALSE);
@@ -1144,7 +1142,7 @@
 
 	purple_request_fields(purple_account_get_connection(account), NULL,
 		primary, _("Please enter your current password and your new "
-		"password."), fields, _("OK"), G_CALLBACK(change_password_cb),
+		"password."), page, _("OK"), G_CALLBACK(change_password_cb),
 		_("Cancel"), NULL, purple_request_cpar_from_account(account),
 		account);
 }
--- a/libpurple/plugins/idle/idle.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/plugins/idle/idle.c	Tue Mar 07 01:04:42 2023 -0600
@@ -83,11 +83,10 @@
 }
 
 static void
-idle_action_ok(G_GNUC_UNUSED gpointer data, PurpleRequestFields *fields)
-{
-	PurpleAccount *acct = purple_request_fields_get_account(fields, "acct");
+idle_action_ok(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
+	PurpleAccount *acct = purple_request_page_get_account(page, "acct");
 	PurpleContactInfo *info = PURPLE_CONTACT_INFO(acct);
-	int tm = purple_request_fields_get_integer(fields, "mins");
+	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)) {
@@ -100,12 +99,11 @@
 }
 
 static void
-idle_all_action_ok(G_GNUC_UNUSED gpointer data, PurpleRequestFields *fields)
-{
+idle_all_action_ok(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
 	PurpleAccountManager *manager = NULL;
 	PurpleAccount *acct = NULL;
 	GList *list, *iter;
-	int tm = purple_request_fields_get_integer(fields, "mins");
+	int tm = purple_request_page_get_integer(page, "mins");
 
 	manager = purple_account_manager_get_default();
 	list = purple_account_manager_get_enabled(manager);
@@ -129,9 +127,8 @@
 }
 
 static void
-unidle_action_ok(G_GNUC_UNUSED gpointer data, PurpleRequestFields *fields)
-{
-	PurpleAccount *acct = purple_request_fields_get_account(fields, "acct");
+unidle_action_ok(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
+	PurpleAccount *acct = purple_request_page_get_account(page, "acct");
 
 	set_idle_time(acct, 0); /* unidle the account */
 
@@ -158,7 +155,7 @@
 {
 	/* Use the super fancy request API */
 
-	PurpleRequestFields *request;
+	PurpleRequestPage *request;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
@@ -172,8 +169,8 @@
 	field = purple_request_field_int_new("mins", _("Minutes"), 10, 0, 9999);
 	purple_request_group_add_field(group, field);
 
-	request = purple_request_fields_new();
-	purple_request_fields_add_group(request, group);
+	request = purple_request_page_new();
+	purple_request_page_add_group(request, group);
 
 	purple_request_fields(data,
 			N_("I'dle Mak'er"),
@@ -190,7 +187,7 @@
                                     G_GNUC_UNUSED GVariant *parameter,
                                     gpointer data)
 {
-	PurpleRequestFields *request;
+	PurpleRequestPage *request;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
@@ -207,8 +204,8 @@
 	purple_request_field_account_set_show_all(field, FALSE);
 	purple_request_group_add_field(group, field);
 
-	request = purple_request_fields_new();
-	purple_request_fields_add_group(request, group);
+	request = purple_request_page_new();
+	purple_request_page_add_group(request, group);
 
 	purple_request_fields(data,
 			N_("I'dle Mak'er"),
@@ -225,7 +222,7 @@
                                        G_GNUC_UNUSED GVariant *parameter,
                                        gpointer data)
 {
-	PurpleRequestFields *request;
+	PurpleRequestPage *request;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
@@ -234,8 +231,8 @@
 	field = purple_request_field_int_new("mins", _("Minutes"), 10, 0, 9999);
 	purple_request_group_add_field(group, field);
 
-	request = purple_request_fields_new();
-	purple_request_fields_add_group(request, group);
+	request = purple_request_page_new();
+	purple_request_page_add_group(request, group);
 
 	purple_request_fields(data,
 			N_("I'dle Mak'er"),
--- a/libpurple/protocols/demo/purpledemoprotocolactions.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/demo/purpledemoprotocolactions.c	Tue Mar 07 01:04:42 2023 -0600
@@ -367,7 +367,7 @@
 
 static void
 purple_demo_protocol_request_fields_ok_cb(G_GNUC_UNUSED gpointer data,
-                                          PurpleRequestFields *fields)
+                                          PurpleRequestPage *page)
 {
 	PurpleAccount *account = NULL;
 	PurpleRequestField *field = NULL;
@@ -378,30 +378,30 @@
 	info = g_string_new(_("Basic group:\n"));
 
 	g_string_append_printf(info, _("\tString: %s\n"),
-	                       purple_request_fields_get_string(fields, "string"));
+	                       purple_request_page_get_string(page, "string"));
 	g_string_append_printf(info, _("\tMultiline string: %s\n"),
-	                       purple_request_fields_get_string(fields,
-	                                                        "multiline-string"));
+	                       purple_request_page_get_string(page,
+	                                                      "multiline-string"));
 	g_string_append_printf(info, _("\tMasked string: %s\n"),
-	                       purple_request_fields_get_string(fields,
-	                                                        "masked-string"));
+	                       purple_request_page_get_string(page,
+	                                                      "masked-string"));
 	g_string_append_printf(info, _("\tAlphanumeric string: %s\n"),
-	                       purple_request_fields_get_string(fields,
-	                                                        "alphanumeric"));
+	                       purple_request_page_get_string(page,
+	                                                      "alphanumeric"));
 	g_string_append_printf(info, _("\tEmail string: %s\n"),
-	                       purple_request_fields_get_string(fields, "email"));
+	                       purple_request_page_get_string(page, "email"));
 	g_string_append_printf(info, _("\tInteger: %d\n"),
-	                       purple_request_fields_get_integer(fields, "int"));
+	                       purple_request_page_get_integer(page, "int"));
 	g_string_append_printf(info, _("\tBoolean: %s\n"),
-	                       purple_request_fields_get_bool(fields, "bool") ?
+	                       purple_request_page_get_bool(page, "bool") ?
 	                       _("TRUE") : _("FALSE"));
 
 	g_string_append(info, _("Multiple-choice group:\n"));
 
-	tmp = (const char *)purple_request_fields_get_choice(fields, "choice");
+	tmp = (const char *)purple_request_page_get_choice(page, "choice");
 	g_string_append_printf(info, _("\tChoice: %s\n"), tmp);
 
-	field = purple_request_fields_get_field(fields, "list");
+	field = purple_request_page_get_field(page, "list");
 	list = purple_request_field_list_get_selected(field);
 	if(list != NULL) {
 		tmp = (const char *)list->data;
@@ -410,7 +410,7 @@
 	}
 	g_string_append_printf(info, _("\tList: %s\n"), tmp);
 
-	field = purple_request_fields_get_field(fields, "multilist");
+	field = purple_request_page_get_field(page, "multilist");
 	list = purple_request_field_list_get_selected(field);
 	g_string_append(info, _("\tMulti-list: ["));
 	while(list != NULL) {
@@ -423,7 +423,7 @@
 
 	g_string_append(info, _("Special group:\n"));
 
-	account = purple_request_fields_get_account(fields, "account");
+	account = purple_request_page_get_account(page, "account");
 	if(PURPLE_IS_ACCOUNT(account)) {
 		tmp = purple_contact_info_get_name_for_display(PURPLE_CONTACT_INFO(account));
 	} else {
@@ -438,7 +438,7 @@
 
 static void
 purple_demo_protocol_request_fields_cancel_cb(G_GNUC_UNUSED gpointer data,
-                                              G_GNUC_UNUSED PurpleRequestFields *fields)
+                                              G_GNUC_UNUSED PurpleRequestPage *page)
 {
 	g_message(_("UI cancelled field request"));
 }
@@ -452,7 +452,7 @@
 	const gchar *account_id = NULL;
 	PurpleAccountManager *manager = NULL;
 	PurpleAccount *account = NULL;
-	PurpleRequestFields *fields = NULL;
+	PurpleRequestPage *page = NULL;
 	PurpleRequestGroup *group = NULL;
 	PurpleRequestField *field = NULL;
 	GBytes *icon = NULL;
@@ -470,11 +470,11 @@
 	account = purple_account_manager_find_by_id(manager, account_id);
 	connection = purple_account_get_connection(account);
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 
 	/* This group will contain basic fields. */
 	group = purple_request_group_new(_("Basic"));
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_label_new("basic-label",
 	                                       _("This group contains basic fields"));
@@ -512,7 +512,7 @@
 
 	/* This group will contain fields with multiple options. */
 	group = purple_request_group_new(_("Multiple"));
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_label_new("multiple-label",
 	                                       _("This group contains fields with multiple options"));
@@ -542,7 +542,7 @@
 
 	/* This group will contain specialized fields. */
 	group = purple_request_group_new(_("Special"));
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_label_new("special-label",
 	                                       _("This group contains specialized fields"));
@@ -562,7 +562,7 @@
 	purple_request_group_add_field(group, field);
 
 	purple_request_fields(connection, _("Request Fields Demo"),
-	                      _("Please fill out these fields…"), NULL, fields,
+	                      _("Please fill out these fields…"), NULL, page,
 	                      _("OK"),
 	                      G_CALLBACK(purple_demo_protocol_request_fields_ok_cb),
 	                      _("Cancel"),
--- a/libpurple/protocols/facebook/util.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/facebook/util.c	Tue Mar 07 01:04:42 2023 -0600
@@ -295,8 +295,7 @@
 }
 
 static void
-fb_util_request_buddy_ok(gpointer *request_data, PurpleRequestFields *fields)
-{
+fb_util_request_buddy_ok(gpointer *request_data, PurpleRequestPage *page) {
 	FbUtilRequestBuddyFunc func = request_data[0];
 	GList *l;
 	GList *select;
@@ -310,7 +309,7 @@
 		return;
 	}
 
-	field = purple_request_fields_get_field(fields, "buddy");
+	field = purple_request_page_get_field(page, "buddy");
 	select = purple_request_field_list_get_selected(field);
 
 	for (l = select; l != NULL; l = l->next) {
@@ -327,7 +326,7 @@
 
 static void
 fb_util_request_buddy_cancel(gpointer *request_data,
-                             G_GNUC_UNUSED PurpleRequestFields *fields)
+                             G_GNUC_UNUSED PurpleRequestPage *page)
 {
 	FbUtilRequestBuddyFunc func = request_data[1];
 	gpointer data = request_data[2];
@@ -382,7 +381,7 @@
 	PurpleRequestCommonParameters *cpar;
 	PurpleRequestField *field;
 	PurpleRequestGroup *group;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 
 	request_data = g_new0(gpointer, 3);
 	request_data[0] = ok_cb;
@@ -393,9 +392,9 @@
 	buddies = purple_blist_find_buddies(acct, NULL);
 	buddies = g_slist_sort(buddies, fb_buddy_cmp);
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_list_new("buddy", NULL);
 	purple_request_field_list_set_multi_select(field, multi);
@@ -422,7 +421,7 @@
 	g_list_free_full(items, g_free);
 
 	cpar = purple_request_cpar_from_connection(gc);
-	return purple_request_fields(gc, title, primary, secondary, fields,
+	return purple_request_fields(gc, title, primary, secondary, page,
 	                             _("Ok"),
 	                             G_CALLBACK(fb_util_request_buddy_ok),
 				     _("Cancel"),
--- a/libpurple/protocols/gg/multilogon.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/gg/multilogon.c	Tue Mar 07 01:04:42 2023 -0600
@@ -217,7 +217,7 @@
 {
 	ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc);
 	PurpleRequestField *field;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestCommonParameters *cpar;
 	PurpleRequestDatasheet *sheet;
@@ -227,9 +227,9 @@
 	if (mldata->dialog_handle != NULL)
 		return;
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	sheet = purple_request_datasheet_new();
 	purple_request_datasheet_add_column(sheet,
@@ -253,7 +253,7 @@
 	purple_request_cpar_set_icon(cpar, PURPLE_REQUEST_ICON_DIALOG);
 
 	dialog_handle = purple_request_fields(gc,
-		_("Other Gadu-Gadu sessions"), NULL, NULL, fields,
+		_("Other Gadu-Gadu sessions"), NULL, NULL, page,
 		NULL, NULL, _("Close"), NULL,
 		cpar, NULL);
 	mldata->sheet_handle = sheet;
--- a/libpurple/protocols/gg/pubdir-prpl.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/gg/pubdir-prpl.c	Tue Mar 07 01:04:42 2023 -0600
@@ -727,16 +727,15 @@
 }
 
 static void
-ggp_pubdir_search_request(PurpleConnection *gc, PurpleRequestFields *fields)
-{
+ggp_pubdir_search_request(PurpleConnection *gc, PurpleRequestPage *page) {
 	ggp_pubdir_search_form *form = g_new0(ggp_pubdir_search_form, 1);
 
 	purple_debug_info("gg", "ggp_pubdir_search_request");
 
-	form->nick = g_strdup(purple_request_fields_get_string(fields, "name"));
-	form->city = g_strdup(purple_request_fields_get_string(fields, "city"));
+	form->nick = g_strdup(purple_request_page_get_string(page, "name"));
+	form->city = g_strdup(purple_request_page_get_string(page, "city"));
 	form->gender =
-	        GPOINTER_TO_INT(purple_request_fields_get_choice(fields, "gender"));
+	        GPOINTER_TO_INT(purple_request_page_get_choice(page, "gender"));
 	form->offset = 0;
 	form->limit = GGP_PUBDIR_SEARCH_PER_PAGE;
 
@@ -747,15 +746,15 @@
 void
 ggp_pubdir_search(PurpleConnection *gc, const ggp_pubdir_search_form *form)
 {
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
 	purple_debug_info("gg", "ggp_pubdir_search");
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("name", _("Name"),
 	                                        form ? form->nick : NULL, FALSE);
@@ -775,7 +774,7 @@
 	purple_request_group_add_field(group, field);
 
 	purple_request_fields(gc, _("Find buddies"), _("Find buddies"),
-	                      _("Please, enter your search criteria below"), fields,
+	                      _("Please, enter your search criteria below"), page,
 	                      _("OK"), G_CALLBACK(ggp_pubdir_search_request),
 	                      _("Cancel"), NULL,
 	                      purple_request_cpar_from_connection(gc), gc);
@@ -892,7 +891,7 @@
 }
 
 static void
-ggp_pubdir_set_info_request(PurpleConnection *gc, PurpleRequestFields *fields)
+ggp_pubdir_set_info_request(PurpleConnection *gc, PurpleRequestPage *page)
 {
 	PurpleAccount *account = purple_connection_get_account(gc);
 	PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
@@ -904,24 +903,23 @@
 	purple_debug_info("gg", "ggp_pubdir_set_info_request");
 
 	record->uin = uin;
-	record->first_name =
-	        g_strdup(purple_request_fields_get_string(fields, "first_name"));
-	record->last_name =
-	        g_strdup(purple_request_fields_get_string(fields, "last_name"));
-	record->gender =
-	        GPOINTER_TO_INT(purple_request_fields_get_choice(fields, "gender"));
-	record->city = g_strdup(purple_request_fields_get_string(fields, "city"));
-	record->province = GPOINTER_TO_INT(
-	        purple_request_fields_get_choice(fields, "province"));
+	record->first_name = g_strdup(purple_request_page_get_string(page,
+	                                                             "first_name"));
+	record->last_name = g_strdup(purple_request_page_get_string(page,
+	                                                            "last_name"));
+	record->gender = GPOINTER_TO_INT(purple_request_page_get_choice(page,
+	                                                                "gender"));
+	record->city = g_strdup(purple_request_page_get_string(page, "city"));
+	record->province = GPOINTER_TO_INT(purple_request_page_get_choice(page,
+	                                                                  "province"));
 
-	birth_s = g_strdup_printf(
-	        "%sT10:00:00+00:00",
-	        purple_request_fields_get_string(fields, "birth_date"));
+	birth_s = g_strdup_printf("%sT10:00:00+00:00",
+	                          purple_request_page_get_string(page, "birth_date"));
 	record->birth = g_date_time_new_from_iso8601(birth_s, NULL);
 	g_free(birth_s);
 	purple_debug_info("gg", "ggp_pubdir_set_info_request: birth [%lu][%s]",
 	                  g_date_time_to_unix(record->birth),
-	                  purple_request_fields_get_string(fields, "birth_date"));
+	                  purple_request_page_get_string(page, "birth_date"));
 
 	url = g_strdup_printf("http://api.gadu-gadu.pl/users/%u.xml", uin);
 	ggp_oauth_request(gc, ggp_pubdir_set_info_got_token, record, "PUT", url);
@@ -934,7 +932,7 @@
                            G_GNUC_UNUSED int next_offset,
                            G_GNUC_UNUSED gpointer data)
 {
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 	gchar *bday = NULL;
@@ -946,9 +944,9 @@
 
 	record = (records_count == 1 ? &records[0] : NULL);
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("first_name", _("First name"),
 	                                        record ? record->first_name : NULL,
@@ -1005,7 +1003,7 @@
 	}
 
 	purple_request_fields(gc, _("Set User Info"), _("Set User Info"), NULL,
-	                      fields, _("OK"),
+	                      page, _("OK"),
 	                      G_CALLBACK(ggp_pubdir_set_info_request), _("Cancel"),
 	                      NULL, purple_request_cpar_from_connection(gc), gc);
 }
--- a/libpurple/protocols/gg/status.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/gg/status.c	Tue Mar 07 01:04:42 2023 -0600
@@ -204,11 +204,6 @@
  * Own status.
  ******************************************************************************/
 
-static void ggp_status_broadcasting_dialog_ok(PurpleConnection *gc,
-	PurpleRequestFields *fields);
-
-/******************************************************************************/
-
 void ggp_status_set_initial(PurpleConnection *gc, struct gg_login_params *glp)
 {
 	ggp_status_session_data *ssdata = ggp_status_get_ssdata(gc);
@@ -339,15 +334,23 @@
 		purple_account_get_active_status(account));
 }
 
+static void
+ggp_status_broadcasting_dialog_ok(PurpleConnection *gc,
+                                  PurpleRequestPage *page)
+{
+	gboolean buddies_only = purple_request_page_get_bool(page, "buddies_only");
+	ggp_status_set_status_broadcasting(gc, !buddies_only);
+}
+
 void ggp_status_broadcasting_dialog(PurpleConnection *gc)
 {
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_bool_new("buddies_only",
 		_("Show status only for buddies"),
@@ -358,19 +361,12 @@
 		_("Change status broadcasting"),
 		_("Please, select who can see your status"),
 		NULL,
-		fields,
+		page,
 		_("OK"), G_CALLBACK(ggp_status_broadcasting_dialog_ok),
 		_("Cancel"), NULL,
 		purple_request_cpar_from_connection(gc), gc);
 }
 
-static void ggp_status_broadcasting_dialog_ok(PurpleConnection *gc,
-	PurpleRequestFields *fields)
-{
-	ggp_status_set_status_broadcasting(gc,
-		!purple_request_fields_get_bool(fields, "buddies_only"));
-}
-
 /*******************************************************************************
  * Buddy status.
  ******************************************************************************/
--- a/libpurple/protocols/jabber/auth.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/jabber/auth.c	Tue Mar 07 01:04:42 2023 -0600
@@ -74,8 +74,7 @@
 }
 
 static void
-auth_old_pass_cb(PurpleConnection *gc, PurpleRequestFields *fields)
-{
+auth_old_pass_cb(PurpleConnection *gc, PurpleRequestPage *page) {
 	PurpleAccount *account;
 	JabberStream *js;
 	const char *entry;
@@ -87,8 +86,8 @@
 	account = purple_connection_get_account(gc);
 	js = purple_connection_get_protocol_data(gc);
 
-	entry = purple_request_fields_get_string(fields, "password");
-	remember = purple_request_fields_get_bool(fields, "remember");
+	entry = purple_request_page_get_string(page, "password");
+	remember = purple_request_page_get_bool(page, "remember");
 
 	if (!entry || !*entry)
 	{
@@ -116,9 +115,7 @@
 }
 
 static void
-auth_no_pass_cb(PurpleConnection *gc,
-                G_GNUC_UNUSED PurpleRequestFields *fields)
-{
+auth_no_pass_cb(PurpleConnection *gc, G_GNUC_UNUSED PurpleRequestPage *page) {
 	/* TODO: the password prompt dialog doesn't get disposed if the account disconnects */
 	PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
 
--- a/libpurple/protocols/jabber/buddy.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/jabber/buddy.c	Tue Mar 07 01:04:42 2023 -0600
@@ -555,8 +555,7 @@
  * Sets the vCard with data from PurpleRequestFields.
  */
 static void
-jabber_format_info(PurpleConnection *gc, PurpleRequestFields *fields)
-{
+jabber_format_info(PurpleConnection *gc, PurpleRequestPage *page) {
 	PurpleXmlNode *vc_node;
 	PurpleRequestField *field;
 	PurpleProtocol *protocol = NULL;
@@ -574,7 +573,7 @@
 		if (*vc_tp->label == '\0')
 			continue;
 
-		field = purple_request_fields_get_field(fields, vc_tp->tag);
+		field = purple_request_page_get_field(page, vc_tp->tag);
 		text  = purple_request_field_string_get_value(field);
 
 
@@ -619,7 +618,7 @@
 	PurpleAccountManager *manager = NULL;
 	PurpleAccount *account = NULL;
 	PurpleConnection *connection = NULL;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 	const struct vcard_template *vc_tp;
@@ -637,9 +636,9 @@
 	account = purple_account_manager_find_by_id(manager, account_id);
 	connection = purple_account_get_connection(account);
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	/*
 	 * Get existing, XML-formatted, user info
@@ -691,7 +690,7 @@
 	                      _("Edit XMPP vCard"),
 	                      _("All items below are optional. Enter only the "
 	                        "information with which you feel comfortable."),
-	                      fields,
+	                      page,
 	                      _("Save"), G_CALLBACK(jabber_format_info),
 	                      _("Cancel"), NULL,
 	                      purple_request_cpar_from_connection(connection),
--- a/libpurple/protocols/jabber/jabber.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/jabber/jabber.c	Tue Mar 07 01:04:42 2023 -0600
@@ -1861,15 +1861,14 @@
 	g_free(data);
 }
 
-static void jabber_password_change_cb(JabberStream *js,
-		PurpleRequestFields *fields)
-{
+static void
+jabber_password_change_cb(JabberStream *js, PurpleRequestPage *page) {
 	const char *p1, *p2;
 	JabberIq *iq;
 	PurpleXmlNode *query, *y;
 
-	p1 = purple_request_fields_get_string(fields, "password1");
-	p2 = purple_request_fields_get_string(fields, "password2");
+	p1 = purple_request_page_get_string(page, "password1");
+	p2 = purple_request_page_get_string(page, "password2");
 
 	if(!purple_strequal(p1, p2)) {
 		purple_notify_error(js->gc, NULL,
@@ -1903,7 +1902,7 @@
 	PurpleAccount *account = NULL;
 	PurpleConnection *connection = NULL;
 	JabberStream *js = NULL;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
@@ -1918,9 +1917,9 @@
 	connection = purple_account_get_connection(account);
 	js = purple_connection_get_protocol_data(connection);
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("password1", _("Password"),
 			"", FALSE);
@@ -1937,7 +1936,7 @@
 	purple_request_fields(connection, _("Change XMPP Password"),
 	                      _("Change XMPP Password"),
 	                      _("Please enter your new password"),
-	                      fields,
+	                      page,
 	                      _("OK"), G_CALLBACK(jabber_password_change_cb),
 	                      _("Cancel"), NULL,
 	                      purple_request_cpar_from_connection(connection), js);
@@ -2613,17 +2612,15 @@
 
 static void
 jabber_media_cancel_cb(JabberMediaRequest *request,
-                       G_GNUC_UNUSED PurpleRequestFields *fields)
+                       G_GNUC_UNUSED PurpleRequestPage *page)
 {
 	g_free(request->who);
 	g_free(request);
 }
 
 static void
-jabber_media_ok_cb(JabberMediaRequest *request, PurpleRequestFields *fields)
-{
-	PurpleRequestField *field =
-			purple_request_fields_get_field(fields, "resource");
+jabber_media_ok_cb(JabberMediaRequest *request, PurpleRequestPage *page) {
+	PurpleRequestField *field = purple_request_page_get_field(page, "resource");
 	const gchar *selected = purple_request_field_choice_get_value(field);
 	gchar *who = g_strdup_printf("%s/%s", request->who, selected);
 	jabber_initiate_media(request->media, request->account, who, request->type);
@@ -2697,12 +2694,12 @@
 		 * we need to pick one to initiate with */
 		GList *l;
 		char *msg;
-		PurpleRequestFields *fields;
-		PurpleRequestField *field = purple_request_field_choice_new(
-				"resource", _("Resource"), 0);
-		PurpleRequestGroup *group;
+		PurpleRequestPage *page = NULL;
+		PurpleRequestField *field = NULL;
+		PurpleRequestGroup *group = NULL;
 		JabberMediaRequest *request;
 
+		field = purple_request_field_choice_new("resource", _("Resource"), 0);
 		for(l = jb->resources; l; l = l->next)
 		{
 			JabberBuddyResource *ljbr = l->data;
@@ -2750,7 +2747,7 @@
 		}
 
 		msg = g_strdup_printf(_("Please select the resource of %s with which you would like to start a media session."), who);
-		fields = purple_request_fields_new();
+		page = purple_request_page_new();
 		group =	purple_request_group_new(NULL);
 		request = g_new0(JabberMediaRequest, 1);
 		request->media = media;
@@ -2759,9 +2756,9 @@
 		request->type = type;
 
 		purple_request_group_add_field(group, field);
-		purple_request_fields_add_group(fields, group);
+		purple_request_page_add_group(page, group);
 		purple_request_fields(account, _("Select a Resource"), msg,
-				NULL, fields, _("Initiate Media"),
+				NULL, page, _("Initiate Media"),
 				G_CALLBACK(jabber_media_ok_cb), _("Cancel"),
 				G_CALLBACK(jabber_media_cancel_cb),
 				purple_request_cpar_from_account(account),
--- a/libpurple/protocols/jabber/si.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/jabber/si.c	Tue Mar 07 01:04:42 2023 -0600
@@ -1469,7 +1469,7 @@
 
 static void
 resource_select_cancel_cb(PurpleXfer *xfer,
-                          G_GNUC_UNUSED PurpleRequestFields *fields)
+                          G_GNUC_UNUSED PurpleRequestPage *page)
 {
 	purple_xfer_cancel_local(xfer);
 }
@@ -1516,9 +1516,10 @@
 	g_free(who);
 }
 
-static void resource_select_ok_cb(PurpleXfer *xfer, PurpleRequestFields *fields)
+static void
+resource_select_ok_cb(PurpleXfer *xfer, PurpleRequestPage *page)
 {
-	PurpleRequestField *field = purple_request_fields_get_field(fields, "resource");
+	PurpleRequestField *field = purple_request_page_get_field(page, "resource");
 	const char *selected_label = purple_request_field_choice_get_value(field);
 
 	do_transfer_send(xfer, selected_label);
@@ -1587,7 +1588,7 @@
 			/* we've got multiple resources, we need to pick one to send to */
 			GList *l;
 			char *msg = g_strdup_printf(_("Please select the resource of %s to which you would like to send a file"), purple_xfer_get_remote_user(xfer));
-			PurpleRequestFields *fields = purple_request_fields_new();
+			PurpleRequestPage *page = purple_request_page_new();
 			PurpleRequestField *field = purple_request_field_choice_new("resource", _("Resource"), 0);
 			PurpleRequestGroup *group = purple_request_group_new(NULL);
 
@@ -1598,9 +1599,9 @@
 
 			purple_request_group_add_field(group, field);
 
-			purple_request_fields_add_group(fields, group);
+			purple_request_page_add_group(page, group);
 
-			purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, fields,
+			purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, page,
 					_("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb),
 					purple_request_cpar_from_connection(jsx->js->gc), xfer);
 
--- a/libpurple/protocols/jabber/xdata.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/protocols/jabber/xdata.c	Tue Mar 07 01:04:42 2023 -0600
@@ -47,7 +47,8 @@
 	PurpleRequestGroup *actiongroup;
 };
 
-static void jabber_x_data_ok_cb(struct jabber_x_data_data *data, PurpleRequestFields *fields) {
+static void
+jabber_x_data_ok_cb(struct jabber_x_data_data *data, PurpleRequestPage *page) {
 	PurpleXmlNode *result = purple_xmlnode_new("x");
 	GCallback cb = data->cb;
 	gpointer user_data = data->user_data;
@@ -59,7 +60,7 @@
 	purple_xmlnode_set_namespace(result, "jabber:x:data");
 	purple_xmlnode_set_attrib(result, "type", "submit");
 
-	for(groups = purple_request_fields_get_groups(fields); groups; groups = groups->next) {
+	for(groups = purple_request_page_get_groups(page); groups; groups = groups->next) {
 		if(groups->data == data->actiongroup) {
 			for(flds = purple_request_group_get_fields(groups->data); flds; flds = flds->next) {
 				PurpleRequestField *field = flds->data;
@@ -157,7 +158,7 @@
 
 static void
 jabber_x_data_cancel_cb(struct jabber_x_data_data *data,
-                        G_GNUC_UNUSED PurpleRequestFields *fields)
+                        G_GNUC_UNUSED PurpleRequestPage *page)
 {
 	PurpleXmlNode *result = purple_xmlnode_new("x");
 	GCallback cb = data->cb;
@@ -190,7 +191,7 @@
 {
 	void *handle;
 	PurpleXmlNode *fn, *x;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field = NULL;
 
@@ -204,9 +205,9 @@
 	data->cb = G_CALLBACK(cb);
 	data->js = js;
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	for(fn = purple_xmlnode_get_child(packet, "field"); fn; fn = purple_xmlnode_get_next_twin(fn)) {
 		PurpleXmlNode *valuenode;
@@ -366,7 +367,7 @@
 		int i;
 
 		data->actiongroup = group = purple_request_group_new(_("Actions"));
-		purple_request_fields_add_group(fields, group);
+		purple_request_page_add_group(page, group);
 		actionfield = purple_request_field_choice_new("libpurple:jabber:xdata:actions", _("Select an action"), GINT_TO_POINTER(defaultaction));
 
 		for(i = 0, action = actions; action; action = g_list_next(action), i++) {
@@ -385,7 +386,7 @@
 	if((x = purple_xmlnode_get_child(packet, "instructions")))
 		instructions = purple_xmlnode_get_data(x);
 
-	handle = purple_request_fields(js->gc, title, title, instructions, fields,
+	handle = purple_request_fields(js->gc, title, title, instructions, page,
 			_("OK"), G_CALLBACK(jabber_x_data_ok_cb),
 			_("Cancel"), G_CALLBACK(jabber_x_data_cancel_cb),
 			purple_request_cpar_from_connection(js->gc),
--- a/libpurple/purplechatconversation.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/purplechatconversation.c	Tue Mar 07 01:04:42 2023 -0600
@@ -1035,7 +1035,7 @@
 }
 
 static void
-invite_user_to_chat(gpointer data, PurpleRequestFields *fields) {
+invite_user_to_chat(gpointer data, PurpleRequestPage *page) {
 	PurpleChatConversation *chat;
 	PurpleChatConversationPrivate *priv;
 	PurpleConnection *pc;
@@ -1044,8 +1044,8 @@
 	chat = PURPLE_CHAT_CONVERSATION(data);
 	priv = purple_chat_conversation_get_instance_private(chat);
 
-	user = purple_request_fields_get_string(fields, "screenname");
-	message = purple_request_fields_get_string(fields, "message");
+	user = purple_request_page_get_string(page, "screenname");
+	message = purple_request_page_get_string(page, "message");
 
 	pc = purple_conversation_get_connection(PURPLE_CONVERSATION(chat));
 	purple_serv_chat_invite(pc, priv->id, message, user);
@@ -1057,7 +1057,7 @@
                                      gboolean confirm)
 {
 	PurpleAccount *account;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
@@ -1076,9 +1076,9 @@
 		return;
 	}
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	group = purple_request_group_new(_("Invite to chat"));
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("screenname", _("Buddy"), user,
 	                                        FALSE);
@@ -1093,7 +1093,7 @@
 	purple_request_fields(chat, _("Invite to chat"), NULL,
 	                      _("Please enter the name of the user you wish to "
 	                        "invite, along with an optional invite message."),
-	                      fields,
+	                      page,
 	                      _("Invite"), G_CALLBACK(invite_user_to_chat),
 	                      _("Cancel"), NULL,
 	                      purple_request_cpar_from_conversation(PURPLE_CONVERSATION(chat)),
--- a/libpurple/purpleprivate.h	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/purpleprivate.h	Tue Mar 07 01:04:42 2023 -0600
@@ -338,10 +338,10 @@
  */
 G_GNUC_INTERNAL void purple_account_set_enabled_plain(PurpleAccount *account, gboolean enabled);
 
-G_GNUC_INTERNAL void _purple_request_field_list_add_field(PurpleRequestFields *fields, PurpleRequestField *field);
-G_GNUC_INTERNAL void _purple_request_field_list_set_field_required(PurpleRequestFields *fields, PurpleRequestField *field, gboolean required);
-G_GNUC_INTERNAL void _purple_request_field_list_set_field_validator(PurpleRequestFields *fields, PurpleRequestField *field, gboolean validator);
-G_GNUC_INTERNAL void _purple_request_group_set_field_list(PurpleRequestGroup *group, PurpleRequestFields *fields);
+G_GNUC_INTERNAL void _purple_request_page_add_field(PurpleRequestPage *fields, PurpleRequestField *field);
+G_GNUC_INTERNAL void _purple_request_page_set_field_required(PurpleRequestPage *fields, PurpleRequestField *field, gboolean required);
+G_GNUC_INTERNAL void _purple_request_page_set_field_validator(PurpleRequestPage *fields, PurpleRequestField *field, gboolean validator);
+G_GNUC_INTERNAL void _purple_request_group_set_page(PurpleRequestGroup *group, PurpleRequestPage *fields);
 G_GNUC_INTERNAL void _purple_request_group_set_field_required(PurpleRequestGroup *group, PurpleRequestField *field, gboolean required);
 G_GNUC_INTERNAL void _purple_request_group_set_field_validator(PurpleRequestGroup *group, PurpleRequestField *field, gboolean validator);
 G_GNUC_INTERNAL void _purple_request_field_set_group(PurpleRequestField *field, PurpleRequestGroup *group);
--- a/libpurple/purplerequestgroup.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/purplerequestgroup.c	Tue Mar 07 01:04:42 2023 -0600
@@ -28,7 +28,7 @@
 struct _PurpleRequestGroup {
 	GObject parent;
 
-	PurpleRequestFields *fields_list;
+	PurpleRequestPage *page;
 
 	char *title;
 
@@ -171,12 +171,12 @@
 }
 
 void
-_purple_request_group_set_field_list(PurpleRequestGroup *group,
-                                     PurpleRequestFields *fields)
+_purple_request_group_set_page(PurpleRequestGroup *group,
+                               PurpleRequestPage *page)
 {
 	g_return_if_fail(PURPLE_IS_REQUEST_GROUP(group));
 
-	group->fields_list = fields;
+	group->page = page;
 }
 
 void
@@ -186,8 +186,7 @@
 {
 	g_return_if_fail(PURPLE_IS_REQUEST_GROUP(group));
 
-	_purple_request_field_list_set_field_required(group->fields_list, field,
-	                                              required);
+	_purple_request_page_set_field_required(group->page, field, required);
 }
 
 void
@@ -197,8 +196,7 @@
 {
 	g_return_if_fail(PURPLE_IS_REQUEST_GROUP(group));
 
-	_purple_request_field_list_set_field_validator(group->fields_list, field,
-	                                               validator);
+	_purple_request_page_set_field_validator(group->page, field, validator);
 }
 
 void
@@ -213,8 +211,8 @@
 	position = g_list_length(group->fields);
 	group->fields = g_list_append(group->fields, field);
 
-	if(group->fields_list != NULL) {
-		_purple_request_field_list_add_field(group->fields_list, field);
+	if(PURPLE_IS_REQUEST_PAGE(group->page)) {
+		_purple_request_page_add_field(group->page, field);
 	}
 
 	_purple_request_field_set_group(field, group);
@@ -238,10 +236,10 @@
 	return group->fields;
 }
 
-PurpleRequestFields *
-purple_request_group_get_fields_list(PurpleRequestGroup *group)
+PurpleRequestPage *
+purple_request_group_get_page(PurpleRequestGroup *group)
 {
 	g_return_val_if_fail(PURPLE_IS_REQUEST_GROUP(group), NULL);
 
-	return group->fields_list;
+	return group->page;
 }
--- a/libpurple/purplerequestgroup.h	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/purplerequestgroup.h	Tue Mar 07 01:04:42 2023 -0600
@@ -87,14 +87,14 @@
 GList *purple_request_group_get_fields(PurpleRequestGroup *group);
 
 /**
- * purple_request_group_get_fields_list:
+ * purple_request_group_get_page:
  * @group: The group.
  *
  * Returns a list of all fields in a group.
  *
  * Returns: (transfer none): The list of fields in the group.
  */
-PurpleRequestFields *purple_request_group_get_fields_list(PurpleRequestGroup *group);
+PurpleRequestPage *purple_request_group_get_page(PurpleRequestGroup *group);
 
 G_END_DECLS
 
--- a/libpurple/purplerequestpage.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/purplerequestpage.c	Tue Mar 07 01:04:42 2023 -0600
@@ -25,8 +25,9 @@
 #include "purplerequestpage.h"
 #include "purpleprivate.h"
 
-struct _PurpleRequestFields
-{
+struct _PurpleRequestPage {
+	GObject parent;
+
 	GList *groups;
 
 	GHashTable *fields;
@@ -38,92 +39,134 @@
 	void *ui_data;
 };
 
-PurpleRequestFields *
-purple_request_fields_new(void)
-{
-	PurpleRequestFields *fields;
+/******************************************************************************
+ * GListModel Implementation
+ *****************************************************************************/
+static GType
+purple_request_page_get_item_type(G_GNUC_UNUSED GListModel *model) {
+	return PURPLE_TYPE_REQUEST_GROUP;
+}
+
+static guint
+purple_request_page_get_n_items(GListModel *model) {
+	PurpleRequestPage *page = PURPLE_REQUEST_PAGE(model);
+
+	return g_list_length(page->groups);
+}
+
+static gpointer
+purple_request_page_get_item(GListModel *model, guint index) {
+	PurpleRequestPage *page = PURPLE_REQUEST_PAGE(model);
+
+	return g_list_nth_data(page->groups, index);
+}
+
+static void
+purple_request_page_list_model_init(GListModelInterface *iface) {
+	iface->get_item_type = purple_request_page_get_item_type;
+	iface->get_item = purple_request_page_get_item;
+	iface->get_n_items = purple_request_page_get_n_items;
+}
 
-	fields = g_new0(PurpleRequestFields, 1);
+/******************************************************************************
+ * GObject Implementation
+ *****************************************************************************/
+G_DEFINE_TYPE_WITH_CODE(PurpleRequestPage, purple_request_page, G_TYPE_OBJECT,
+                        G_IMPLEMENT_INTERFACE(G_TYPE_LIST_MODEL,
+                                              purple_request_page_list_model_init))
+
+static void
+purple_request_page_finalize(GObject *obj) {
+	PurpleRequestPage *page = PURPLE_REQUEST_PAGE(obj);
+
+	g_list_free_full(page->groups, g_object_unref);
+	g_list_free(page->required_fields);
+	g_list_free(page->validated_fields);
+	g_hash_table_destroy(page->fields);
+
+	G_OBJECT_CLASS(purple_request_page_parent_class)->finalize(obj);
+}
 
-	fields->fields = g_hash_table_new_full(g_str_hash, g_str_equal,
-										   g_free, NULL);
+static void
+purple_request_page_init(PurpleRequestPage *page) {
+	page->fields = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+}
+
+static void
+purple_request_page_class_init(PurpleRequestPageClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
-	return fields;
+	obj_class->finalize = purple_request_page_finalize;
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+PurpleRequestPage *
+purple_request_page_new(void) {
+	return g_object_new(PURPLE_TYPE_REQUEST_PAGE, NULL);
 }
 
 void
-purple_request_fields_destroy(PurpleRequestFields *fields)
+_purple_request_page_set_field_required(PurpleRequestPage *page,
+                                        PurpleRequestField *field,
+                                        gboolean required)
 {
-	g_return_if_fail(fields != NULL);
-
-	g_list_free_full(fields->groups, g_object_unref);
-	g_list_free(fields->required_fields);
-	g_list_free(fields->validated_fields);
-	g_hash_table_destroy(fields->fields);
-	g_free(fields);
-}
-
-void
-_purple_request_field_list_set_field_required(PurpleRequestFields *fields,
-                                              PurpleRequestField *field,
-                                              gboolean required)
-{
-	g_return_if_fail(fields != NULL);
+	g_return_if_fail(PURPLE_IS_REQUEST_PAGE(page));
 
 	if(required) {
-		fields->required_fields = g_list_append(fields->required_fields, field);
+		page->required_fields = g_list_append(page->required_fields, field);
 	} else {
-		fields->required_fields = g_list_remove(fields->required_fields, field);
+		page->required_fields = g_list_remove(page->required_fields, field);
 	}
 }
 
 void
-_purple_request_field_list_set_field_validator(PurpleRequestFields *fields,
-                                               PurpleRequestField *field,
-                                               gboolean validator)
+_purple_request_page_set_field_validator(PurpleRequestPage *page,
+                                         PurpleRequestField *field,
+                                         gboolean validator)
 {
-	g_return_if_fail(fields != NULL);
+	g_return_if_fail(PURPLE_IS_REQUEST_PAGE(page));
 
-	fields->validated_fields = g_list_remove(fields->validated_fields, field);
+	page->validated_fields = g_list_remove(page->validated_fields, field);
 	if(validator) {
-		fields->validated_fields = g_list_append(fields->validated_fields,
-		                                         field);
+		page->validated_fields = g_list_append(page->validated_fields, field);
 	}
 }
 
 void
-_purple_request_field_list_add_field(PurpleRequestFields *fields,
-                                     PurpleRequestField *field)
+_purple_request_page_add_field(PurpleRequestPage *page,
+                               PurpleRequestField *field)
 {
-	g_return_if_fail(fields != NULL);
+	g_return_if_fail(PURPLE_IS_REQUEST_PAGE(page));
 
-	g_hash_table_insert(fields->fields,
+	g_hash_table_insert(page->fields,
 	                    g_strdup(purple_request_field_get_id(field)), field);
 
 	if(purple_request_field_is_required(field)) {
-		fields->required_fields = g_list_append(fields->required_fields,
-		                                        field);
+		page->required_fields = g_list_append(page->required_fields, field);
 	}
 
 	if(purple_request_field_is_validatable(field)) {
-		fields->validated_fields = g_list_append(fields->validated_fields,
-		                                         field);
+		page->validated_fields = g_list_append(page->validated_fields, field);
 	}
 }
 
 void
-purple_request_fields_add_group(PurpleRequestFields *fields,
-                                PurpleRequestGroup *group)
+purple_request_page_add_group(PurpleRequestPage *page,
+                              PurpleRequestGroup *group)
 {
+	guint position;
 	GList *l;
 	PurpleRequestField *field;
 
-	g_return_if_fail(fields != NULL);
+	g_return_if_fail(PURPLE_IS_REQUEST_PAGE(page));
 	g_return_if_fail(PURPLE_IS_REQUEST_GROUP(group));
 
-	fields->groups = g_list_append(fields->groups, group);
+	position = g_list_length(page->groups);
+	page->groups = g_list_append(page->groups, group);
 
-	_purple_request_group_set_field_list(group, fields);
+	_purple_request_group_set_page(group, page);
 
 	for (l = purple_request_group_get_fields(group);
 		 l != NULL;
@@ -131,78 +174,75 @@
 
 		field = l->data;
 
-		g_hash_table_insert(fields->fields,
-			g_strdup(purple_request_field_get_id(field)), field);
+		g_hash_table_insert(page->fields,
+		                    g_strdup(purple_request_field_get_id(field)),
+		                    field);
 
 		if (purple_request_field_is_required(field)) {
-			fields->required_fields =
-				g_list_append(fields->required_fields, field);
+			page->required_fields = g_list_append(page->required_fields,
+			                                      field);
 		}
 
 		if (purple_request_field_is_validatable(field)) {
-			fields->validated_fields =
-				g_list_append(fields->validated_fields, field);
+			page->validated_fields = g_list_append(page->validated_fields,
+			                                       field);
 		}
 	}
+
+	g_list_model_items_changed(G_LIST_MODEL(page), position, 0, 1);
 }
 
 GList *
-purple_request_fields_get_groups(const PurpleRequestFields *fields)
-{
-	g_return_val_if_fail(fields != NULL, NULL);
+purple_request_page_get_groups(PurpleRequestPage *page) {
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), NULL);
 
-	return fields->groups;
+	return page->groups;
 }
 
 gboolean
-purple_request_fields_exists(const PurpleRequestFields *fields, const char *id)
-{
-	g_return_val_if_fail(fields != NULL, FALSE);
+purple_request_page_exists(PurpleRequestPage *page, const char *id) {
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), FALSE);
 	g_return_val_if_fail(id     != NULL, FALSE);
 
-	return (g_hash_table_lookup(fields->fields, id) != NULL);
+	return (g_hash_table_lookup(page->fields, id) != NULL);
 }
 
 const GList *
-purple_request_fields_get_required(const PurpleRequestFields *fields)
-{
-	g_return_val_if_fail(fields != NULL, NULL);
+purple_request_page_get_required(PurpleRequestPage *page) {
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), NULL);
 
-	return fields->required_fields;
+	return page->required_fields;
 }
 
 const GList *
-purple_request_fields_get_validatable(const PurpleRequestFields *fields)
-{
-	g_return_val_if_fail(fields != NULL, NULL);
+purple_request_page_get_validatable(PurpleRequestPage *page) {
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), NULL);
 
-	return fields->validated_fields;
+	return page->validated_fields;
 }
 
 gboolean
-purple_request_fields_is_field_required(const PurpleRequestFields *fields,
-									  const char *id)
+purple_request_page_is_field_required(PurpleRequestPage *page, const char *id)
 {
 	PurpleRequestField *field;
 
-	g_return_val_if_fail(fields != NULL, FALSE);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), FALSE);
 	g_return_val_if_fail(id     != NULL, FALSE);
 
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
+	if((field = purple_request_page_get_field(page, id)) == NULL) {
 		return FALSE;
+	}
 
 	return purple_request_field_is_required(field);
 }
 
 gboolean
-purple_request_fields_all_required_filled(const PurpleRequestFields *fields)
-{
+purple_request_page_all_required_filled(PurpleRequestPage *page) {
 	GList *l;
 
-	g_return_val_if_fail(fields != NULL, FALSE);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), FALSE);
 
-	for (l = fields->required_fields; l != NULL; l = l->next)
-	{
+	for(l = page->required_fields; l != NULL; l = l->next) {
 		PurpleRequestField *field = PURPLE_REQUEST_FIELD(l->data);
 
 		if (!purple_request_field_is_filled(field))
@@ -213,14 +253,12 @@
 }
 
 gboolean
-purple_request_fields_all_valid(const PurpleRequestFields *fields)
-{
+purple_request_page_all_valid(PurpleRequestPage *page) {
 	GList *l;
 
-	g_return_val_if_fail(fields != NULL, FALSE);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), FALSE);
 
-	for (l = fields->validated_fields; l != NULL; l = l->next)
-	{
+	for(l = page->validated_fields; l != NULL; l = l->next) {
 		PurpleRequestField *field = PURPLE_REQUEST_FIELD(l->data);
 
 		if (!purple_request_field_is_valid(field, NULL))
@@ -231,14 +269,13 @@
 }
 
 PurpleRequestField *
-purple_request_fields_get_field(const PurpleRequestFields *fields, const char *id)
-{
+purple_request_page_get_field(PurpleRequestPage *page, const char *id) {
 	PurpleRequestField *field;
 
-	g_return_val_if_fail(fields != NULL, NULL);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), NULL);
 	g_return_val_if_fail(id     != NULL, NULL);
 
-	field = g_hash_table_lookup(fields->fields, id);
+	field = g_hash_table_lookup(page->fields, id);
 
 	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
 
@@ -246,88 +283,85 @@
 }
 
 const char *
-purple_request_fields_get_string(const PurpleRequestFields *fields, const char *id)
-{
+purple_request_page_get_string(PurpleRequestPage *page, const char *id) {
 	PurpleRequestField *field;
 
-	g_return_val_if_fail(fields != NULL, NULL);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), NULL);
 	g_return_val_if_fail(id     != NULL, NULL);
 
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
+	if((field = purple_request_page_get_field(page, id)) == NULL) {
 		return NULL;
+	}
 
 	return purple_request_field_string_get_value(field);
 }
 
 int
-purple_request_fields_get_integer(const PurpleRequestFields *fields,
-								const char *id)
-{
+purple_request_page_get_integer(PurpleRequestPage *page, const char *id) {
 	PurpleRequestField *field;
 
-	g_return_val_if_fail(fields != NULL, 0);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), 0);
 	g_return_val_if_fail(id     != NULL, 0);
 
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
+	if((field = purple_request_page_get_field(page, id)) == NULL) {
 		return 0;
+	}
 
 	return purple_request_field_int_get_value(field);
 }
 
 gboolean
-purple_request_fields_get_bool(const PurpleRequestFields *fields, const char *id)
-{
+purple_request_page_get_bool(PurpleRequestPage *page, const char *id) {
 	PurpleRequestField *field;
 
-	g_return_val_if_fail(fields != NULL, FALSE);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), FALSE);
 	g_return_val_if_fail(id     != NULL, FALSE);
 
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
+	if((field = purple_request_page_get_field(page, id)) == NULL) {
 		return FALSE;
+	}
 
 	return purple_request_field_bool_get_value(field);
 }
 
 gpointer
-purple_request_fields_get_choice(const PurpleRequestFields *fields,
-	const char *id)
-{
+purple_request_page_get_choice(PurpleRequestPage *page, const char *id) {
 	PurpleRequestField *field;
 
-	g_return_val_if_fail(fields != NULL, NULL);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), NULL);
 	g_return_val_if_fail(id != NULL, NULL);
 
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
+	if((field = purple_request_page_get_field(page, id)) == NULL) {
 		return NULL;
+	}
 
 	return purple_request_field_choice_get_value(field);
 }
 
 PurpleAccount *
-purple_request_fields_get_account(const PurpleRequestFields *fields,
-								const char *id)
-{
+purple_request_page_get_account(PurpleRequestPage *page, const char *id) {
 	PurpleRequestField *field;
 
-	g_return_val_if_fail(fields != NULL, NULL);
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), NULL);
 	g_return_val_if_fail(id     != NULL, NULL);
 
-	if ((field = purple_request_fields_get_field(fields, id)) == NULL)
+	if((field = purple_request_page_get_field(page, id)) == NULL) {
 		return NULL;
+	}
 
 	return purple_request_field_account_get_value(field);
 }
 
-gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields)
-{
-	g_return_val_if_fail(fields != NULL, NULL);
+gpointer
+purple_request_page_get_ui_data(PurpleRequestPage *page) {
+	g_return_val_if_fail(PURPLE_IS_REQUEST_PAGE(page), NULL);
 
-	return fields->ui_data;
+	return page->ui_data;
 }
 
-void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data)
-{
-	g_return_if_fail(fields != NULL);
+void
+purple_request_page_set_ui_data(PurpleRequestPage *page, gpointer ui_data) {
+	g_return_if_fail(PURPLE_IS_REQUEST_PAGE(page));
 
-	fields->ui_data = ui_data;
+	page->ui_data = ui_data;
 }
--- a/libpurple/purplerequestpage.h	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/purplerequestpage.h	Tue Mar 07 01:04:42 2023 -0600
@@ -33,11 +33,11 @@
 #include <glib-object.h>
 
 /**
- * PurpleRequestFields:
+ * PurpleRequestPage:
  *
  * Multiple fields request data.
  */
-typedef struct _PurpleRequestFields PurpleRequestFields;
+typedef struct _PurpleRequestPage PurpleRequestPage;
 
 #include "account.h"
 #include "purplerequestgroup.h"
@@ -45,185 +45,169 @@
 
 G_BEGIN_DECLS
 
-/**
- * purple_request_fields_new:
- *
- * Creates a list of fields to pass to purple_request_fields().
- *
- * Returns: (transfer full): A PurpleRequestFields structure.
- */
-PurpleRequestFields *purple_request_fields_new(void);
+#define PURPLE_TYPE_REQUEST_PAGE (purple_request_page_get_type())
+G_DECLARE_FINAL_TYPE(PurpleRequestPage, purple_request_page,
+                     PURPLE, REQUEST_PAGE, GObject)
 
 /**
- * purple_request_fields_destroy:
- * @fields: The list of fields to destroy.
+ * purple_request_page_new:
+ *
+ * Creates a page of fields to pass to [func@Purple.request_fields].
  *
- * Destroys a list of fields.
+ * Returns: (transfer full): The new request page.
  */
-void purple_request_fields_destroy(PurpleRequestFields *fields);
+PurpleRequestPage *purple_request_page_new(void);
 
 /**
- * purple_request_fields_add_group:
- * @fields: The fields list.
- * @group:  The group to add.
+ * purple_request_page_add_group:
+ * @page: The fields page.
+ * @group: (transfer full): The group to add.
  *
  * Adds a group of fields to the list.
  */
-void purple_request_fields_add_group(PurpleRequestFields *fields, PurpleRequestGroup *group);
+void purple_request_page_add_group(PurpleRequestPage *page, PurpleRequestGroup *group);
 
 /**
- * purple_request_fields_get_groups:
- * @fields: The fields list.
+ * purple_request_page_get_groups:
+ * @page: The fields page.
  *
  * Returns a list of all groups in a field list.
  *
  * Returns: (element-type PurpleRequestGroup) (transfer none): A list of groups.
  */
-GList *purple_request_fields_get_groups(const PurpleRequestFields *fields);
+GList *purple_request_page_get_groups(PurpleRequestPage *page);
 
 /**
- * purple_request_fields_exists:
- * @fields: The fields list.
- * @id:     The ID of the field.
+ * purple_request_page_exists:
+ * @page: The fields page.
+ * @id: The ID of the field.
  *
  * Returns whether or not the field with the specified ID exists.
  *
  * Returns: TRUE if the field exists, or FALSE.
  */
-gboolean purple_request_fields_exists(const PurpleRequestFields *fields,
-									const char *id);
+gboolean purple_request_page_exists(PurpleRequestPage *page, const char *id);
 
 /**
- * purple_request_fields_get_required:
- * @fields: The fields list.
+ * purple_request_page_get_required:
+ * @page: The fields page.
  *
  * Returns a list of all required fields.
  *
  * Returns: (element-type PurpleRequestField) (transfer none): The list of required fields.
  */
-const GList *purple_request_fields_get_required(
-	const PurpleRequestFields *fields);
+const GList *purple_request_page_get_required(PurpleRequestPage *page);
 
 /**
- * purple_request_fields_get_validatable:
- * @fields: The fields list.
+ * purple_request_page_get_validatable:
+ * @page: The fields page.
  *
  * Returns a list of all validated fields.
  *
  * Returns: (element-type PurpleRequestField) (transfer none): The list of validated fields.
  */
-const GList *purple_request_fields_get_validatable(
-	const PurpleRequestFields *fields);
+const GList *purple_request_page_get_validatable(PurpleRequestPage *page);
 
 /**
- * purple_request_fields_is_field_required:
- * @fields: The fields list.
- * @id:     The field ID.
+ * purple_request_page_is_field_required:
+ * @page: The fields page.
+ * @id: The field ID.
  *
  * Returns whether or not a field with the specified ID is required.
  *
  * Returns: TRUE if the specified field is required, or FALSE.
  */
-gboolean purple_request_fields_is_field_required(const PurpleRequestFields *fields,
-											   const char *id);
+gboolean purple_request_page_is_field_required(PurpleRequestPage *page, const char *id);
 
 /**
- * purple_request_fields_all_required_filled:
- * @fields: The fields list.
+ * purple_request_page_all_required_filled:
+ * @page: The fields page.
  *
  * Returns whether or not all required fields have values.
  *
  * Returns: TRUE if all required fields have values, or FALSE.
  */
-gboolean purple_request_fields_all_required_filled(
-	const PurpleRequestFields *fields);
+gboolean purple_request_page_all_required_filled(PurpleRequestPage *page);
 
 /**
- * purple_request_fields_all_valid:
- * @fields: The fields list.
+ * purple_request_page_all_valid:
+ * @page: The fields page.
  *
  * Returns whether or not all fields are valid.
  *
  * Returns: TRUE if all fields are valid, or FALSE.
  */
-gboolean purple_request_fields_all_valid(const PurpleRequestFields *fields);
+gboolean purple_request_page_all_valid(PurpleRequestPage *page);
 
 /**
- * purple_request_fields_get_field:
- * @fields: The fields list.
- * @id:     The ID of the field.
+ * purple_request_page_get_field:
+ * @page: The fields page.
+ * @id: The ID of the field.
  *
  * Return the field with the specified ID.
  *
  * Returns: (transfer none): The field, if found.
  */
-PurpleRequestField *purple_request_fields_get_field(
-		const PurpleRequestFields *fields, const char *id);
+PurpleRequestField *purple_request_page_get_field(PurpleRequestPage *page, const char *id);
 
 /**
- * purple_request_fields_get_string:
- * @fields: The fields list.
- * @id:     The ID of the field.
+ * purple_request_page_get_string:
+ * @page: The fields page.
+ * @id: The ID of the field.
  *
  * Returns the string value of a field with the specified ID.
  *
  * Returns: The string value, if found, or %NULL otherwise.
  */
-const char *purple_request_fields_get_string(const PurpleRequestFields *fields,
-										   const char *id);
+const char *purple_request_page_get_string(PurpleRequestPage *page, const char *id);
 
 /**
- * purple_request_fields_get_integer:
- * @fields: The fields list.
- * @id:     The ID of the field.
+ * purple_request_page_get_integer:
+ * @page: The fields page.
+ * @id: The ID of the field.
  *
  * Returns the integer value of a field with the specified ID.
  *
  * Returns: The integer value, if found, or 0 otherwise.
  */
-int purple_request_fields_get_integer(const PurpleRequestFields *fields,
-									const char *id);
+int purple_request_page_get_integer(PurpleRequestPage *page, const char *id);
 
 /**
- * purple_request_fields_get_bool:
- * @fields: The fields list.
- * @id:     The ID of the field.
+ * purple_request_page_get_bool:
+ * @page: The fields page.
+ * @id: The ID of the field.
  *
  * Returns the boolean value of a field with the specified ID.
  *
  * Returns: The boolean value, if found, or %FALSE otherwise.
  */
-gboolean purple_request_fields_get_bool(const PurpleRequestFields *fields,
-									  const char *id);
+gboolean purple_request_page_get_bool(PurpleRequestPage *page, const char *id);
 
 /**
- * purple_request_fields_get_choice:
- * @fields: The fields list.
+ * purple_request_page_get_choice:
+ * @page: The fields page.
  * @id:     The ID of the field.
  *
  * Returns the choice index of a field with the specified ID.
  *
  * Returns: The choice value, if found, or NULL otherwise.
  */
-gpointer
-purple_request_fields_get_choice(const PurpleRequestFields *fields,
-	const char *id);
+gpointer purple_request_page_get_choice(PurpleRequestPage *page, const char *id);
 
 /**
- * purple_request_fields_get_account:
- * @fields: The fields list.
+ * purple_request_page_get_account:
+ * @page: The fields page.
  * @id:     The ID of the field.
  *
  * Returns the account of a field with the specified ID.
  *
  * Returns: (transfer none): The account value, if found, or %NULL otherwise.
  */
-PurpleAccount *purple_request_fields_get_account(const PurpleRequestFields *fields,
-											 const char *id);
+PurpleAccount *purple_request_page_get_account(PurpleRequestPage *page, const char *id);
 
 /**
- * purple_request_fields_get_ui_data:
- * @fields: The fields list.
+ * purple_request_page_get_ui_data:
+ * @page: The fields page.
  *
  * Returns the UI data associated with this object.
  *
@@ -231,16 +215,16 @@
  *         convenience field provided to the UIs--it is not
  *         used by the libpurple core.
  */
-gpointer purple_request_fields_get_ui_data(const PurpleRequestFields *fields);
+gpointer purple_request_page_get_ui_data(PurpleRequestPage *page);
 
 /**
- * purple_request_fields_set_ui_data:
- * @fields: The fields list.
+ * purple_request_page_set_ui_data:
+ * @page: The fields page.
  * @ui_data: A pointer to associate with this object.
  *
  * Set the UI data associated with this object.
  */
-void purple_request_fields_set_ui_data(PurpleRequestFields *fields, gpointer ui_data);
+void purple_request_page_set_ui_data(PurpleRequestPage *page, gpointer ui_data);
 
 G_END_DECLS
 
--- a/libpurple/request.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/request.c	Tue Mar 07 01:04:42 2023 -0600
@@ -621,11 +621,11 @@
 }
 
 static void
-purple_request_fields_strip_html(PurpleRequestFields *fields)
+purple_request_fields_strip_html(PurpleRequestPage *page)
 {
 	GList *itg;
 
-	for (itg = purple_request_fields_get_groups(fields);
+	for (itg = purple_request_page_get_groups(page);
 	     itg != NULL;
 	     itg = g_list_next(itg))
 	{
@@ -652,18 +652,18 @@
 
 void *
 purple_request_fields(void *handle, const char *title, const char *primary,
-	const char *secondary, PurpleRequestFields *fields, const char *ok_text,
+	const char *secondary, PurpleRequestPage *page, const char *ok_text,
 	GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
 	PurpleRequestCommonParameters *cpar, void *user_data)
 {
 	PurpleRequestUiOps *ops;
 
-	if (G_UNLIKELY(fields == NULL ||
+	if(G_UNLIKELY(!PURPLE_IS_REQUEST_PAGE(page) ||
 		((ok_text == NULL) != (ok_cb == NULL)) ||
 		cancel_text == NULL))
 	{
 		purple_request_cpar_unref(cpar);
-		g_warn_if_fail(fields != NULL);
+		g_warn_if_fail(PURPLE_IS_REQUEST_PAGE(page));
 		g_warn_if_fail((ok_text == NULL) != (ok_cb == NULL));
 		g_warn_if_fail(cancel_text != NULL);
 		g_return_val_if_reached(NULL);
@@ -674,7 +674,7 @@
 	if (purple_request_cpar_is_html(cpar) &&
 		!((ops->features & PURPLE_REQUEST_FEATURE_HTML)))
 	{
-		purple_request_fields_strip_html(fields);
+		purple_request_fields_strip_html(page);
 	}
 
 	if (ops != NULL && ops->request_fields != NULL) {
@@ -687,8 +687,9 @@
 		info->type      = PURPLE_REQUEST_FIELDS;
 		info->handle    = handle;
 		info->ui_handle = ops->request_fields(title, primary, secondary,
-			fields, ok_text, ok_cb, cancel_text, cancel_cb,
-			cpar, user_data);
+		                                      page, ok_text, ok_cb,
+		                                      cancel_text, cancel_cb, cpar,
+		                                      user_data);
 
 		handles = g_list_append(handles, info);
 
--- a/libpurple/request.h	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/request.h	Tue Mar 07 01:04:42 2023 -0600
@@ -165,7 +165,7 @@
 		gfloat fraction);
 
 	void *(*request_fields)(const char *title, const char *primary,
-		const char *secondary, PurpleRequestFields *fields,
+		const char *secondary, PurpleRequestPage *page,
 		const char *ok_text, GCallback ok_cb,
 		const char *cancel_text, GCallback cancel_cb,
 		PurpleRequestCommonParameters *cpar, void *user_data);
@@ -210,7 +210,7 @@
  * values of those choice.
  */
 typedef void (*PurpleRequestChoiceCb)(void *data, gpointer value);
-typedef void (*PurpleRequestFieldsCb)(void *data, PurpleRequestFields *fields);
+typedef void (*PurpleRequestFieldsCb)(void *data, PurpleRequestPage *page);
 typedef void (*PurpleRequestFileCb)(void *data, const char *filename);
 typedef void (*PurpleRequestHelpCb)(gpointer data);
 
@@ -461,7 +461,7 @@
  *        #PurpleRequestFieldsCb function to use when the button is clicked.
  *        Should be terminated with the NULL label.
  *
- * Sets extra actions for the PurpleRequestFields dialog.
+ * Sets extra actions for the PurpleRequestPage dialog.
  */
 void
 purple_request_cpar_set_extra_actions(PurpleRequestCommonParameters *cpar, ...);
@@ -470,7 +470,7 @@
  * purple_request_cpar_get_extra_actions:
  * @cpar: The parameters set (may be %NULL).
  *
- * Gets extra actions for the PurpleRequestFields dialog.
+ * Gets extra actions for the PurpleRequestPage dialog.
  *
  * Returns: (element-type PurpleKeyValuePair) (transfer none): A list of actions (pairs of arguments, as in
  *          setter).
@@ -763,7 +763,7 @@
  * @primary:     The main point of the message, or %NULL if you're
  *               feeling enigmatic.
  * @secondary:   Secondary information, or %NULL if there is none.
- * @fields:      The list of fields.
+ * @page:        The page of fields.
  * @ok_text:     The text for the <literal>OK</literal> button, which may not be
  *               %NULL.
  * @ok_cb: (scope notified):       The callback for the <literal>OK</literal> button, which may
@@ -783,7 +783,7 @@
  */
 void *
 purple_request_fields(void *handle, const char *title, const char *primary,
-	const char *secondary, PurpleRequestFields *fields,
+	const char *secondary, PurpleRequestPage *page,
 	const char *ok_text, GCallback ok_cb,
 	const char *cancel_text, GCallback cancel_cb,
 	PurpleRequestCommonParameters *cpar,
--- a/libpurple/tests/test_credential_manager.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/libpurple/tests/test_credential_manager.c	Tue Mar 07 01:04:42 2023 -0600
@@ -54,8 +54,6 @@
 
 struct _TestPurpleCredentialProvider {
 	PurpleCredentialProvider parent;
-
-	PurpleRequestFields *fields;
 };
 
 G_DEFINE_TYPE(TestPurpleCredentialProvider,
--- a/pidgin/gtkdialogs.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/pidgin/gtkdialogs.c	Tue Mar 07 01:04:42 2023 -0600
@@ -47,30 +47,29 @@
 };
 
 static void
-pidgin_dialogs_im_cb(G_GNUC_UNUSED gpointer data, PurpleRequestFields *fields)
-{
+pidgin_dialogs_im_cb(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
 	PurpleAccount *account;
 	const char *username;
 
-	account  = purple_request_fields_get_account(fields, "account");
-	username = purple_request_fields_get_string(fields,  "screenname");
+	account = purple_request_page_get_account(page, "account");
+	username = purple_request_page_get_string(page,  "screenname");
 
 	pidgin_dialogs_im_with_user(account, username);
 }
 
 static gboolean
 pidgin_dialogs_im_name_validator(G_GNUC_UNUSED PurpleRequestField *field,
-                                 char **errmsg, gpointer _fields)
+                                 char **errmsg, gpointer data)
 {
-	PurpleRequestFields *fields = _fields;
+	PurpleRequestPage *page = data;
 	PurpleAccount *account;
 	PurpleProtocol *protocol;
 	const char *username;
 	gboolean valid = FALSE;
 
-	account = purple_request_fields_get_account(fields, "account");
+	account = purple_request_page_get_account(page, "account");
 	protocol = purple_account_get_protocol(account);
-	username = purple_request_fields_get_string(fields, "screenname");
+	username = purple_request_page_get_string(page, "screenname");
 
 	if (username) {
 		valid = purple_validate(protocol, username);
@@ -85,19 +84,19 @@
 void
 pidgin_dialogs_im(void)
 {
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("screenname", _("_Name"), NULL, FALSE);
 	purple_request_field_set_type_hint(field, "screenname");
 	purple_request_field_set_required(field, TRUE);
-	purple_request_field_set_validator(field, pidgin_dialogs_im_name_validator, fields);
+	purple_request_field_set_validator(field, pidgin_dialogs_im_name_validator, page);
 	purple_request_group_add_field(group, field);
 
 	field = purple_request_field_account_new("account", _("_Account"), NULL);
@@ -112,7 +111,7 @@
 	        purple_blist_get_default(), _("New Instant Message"), NULL,
 	        _("Please enter the username or alias of the person "
 	          "you would like to IM."),
-	        fields, _("OK"), G_CALLBACK(pidgin_dialogs_im_cb), _("Cancel"),
+	        page, _("OK"), G_CALLBACK(pidgin_dialogs_im_cb), _("Cancel"),
 	        NULL, NULL, NULL);
 }
 
@@ -137,16 +136,14 @@
 }
 
 static void
-pidgin_dialogs_info_cb(G_GNUC_UNUSED gpointer data,
-                       PurpleRequestFields *fields)
-{
+pidgin_dialogs_info_cb(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) {
 	char *username;
 	PurpleAccount *account;
 	const gchar *screenname = NULL;
 
-	account = purple_request_fields_get_account(fields, "account");
+	account = purple_request_page_get_account(page, "account");
 
-	screenname = purple_request_fields_get_string(fields,  "screenname");
+	screenname = purple_request_page_get_string(page, "screenname");
 	username = g_strdup(purple_normalize(account, screenname));
 
 	if(username != NULL && *username != '\0' && account != NULL) {
@@ -160,14 +157,14 @@
 void
 pidgin_dialogs_info(void)
 {
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *group;
 	PurpleRequestField *field;
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 
 	group = purple_request_group_new(NULL);
-	purple_request_fields_add_group(fields, group);
+	purple_request_page_add_group(page, group);
 
 	field = purple_request_field_string_new("screenname", _("_Name"), NULL, FALSE);
 	purple_request_field_set_type_hint(field, "screenname");
@@ -186,7 +183,7 @@
 	        purple_blist_get_default(), _("Get User Info"), NULL,
 	        _("Please enter the username or alias of the person "
 	          "whose info you would like to view."),
-	        fields, _("OK"), G_CALLBACK(pidgin_dialogs_info_cb),
+	        page, _("OK"), G_CALLBACK(pidgin_dialogs_info_cb),
 	        _("Cancel"), NULL, NULL, NULL);
 }
 
--- a/pidgin/gtkrequest.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/pidgin/gtkrequest.c	Tue Mar 07 01:04:42 2023 -0600
@@ -65,7 +65,7 @@
 
 		struct
 		{
-			PurpleRequestFields *fields;
+			PurpleRequestPage *page;
 
 		} multifield;
 
@@ -226,16 +226,16 @@
                          PurpleRequestField *field)
 {
 	PurpleRequestGroup *group;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PidginRequestData *req_data;
 
 	group = purple_request_field_get_group(field);
-	fields = purple_request_group_get_fields_list(group);
-	req_data = purple_request_fields_get_ui_data(fields);
+	page = purple_request_group_get_page(group);
+	req_data = purple_request_page_get_ui_data(page);
 
 	gtk_widget_set_sensitive(req_data->ok_button,
-		purple_request_fields_all_required_filled(fields) &&
-		purple_request_fields_all_valid(fields));
+		purple_request_page_all_required_filled(page) &&
+		purple_request_page_all_valid(page));
 }
 
 static void
@@ -283,7 +283,7 @@
 
 	if (data->cbs[0] != NULL)
 		((PurpleRequestFieldsCb)data->cbs[0])(data->user_data,
-											data->u.multifield.fields);
+		                                      data->u.multifield.page);
 
 	purple_request_close(PURPLE_REQUEST_FIELDS, data);
 }
@@ -295,7 +295,7 @@
 
 	if (data->cbs[1] != NULL)
 		((PurpleRequestFieldsCb)data->cbs[1])(data->user_data,
-											data->u.multifield.fields);
+		                                      data->u.multifield.page);
 
 	purple_request_close(PURPLE_REQUEST_FIELDS, data);
 }
@@ -310,7 +310,7 @@
 	cb = g_object_get_data(G_OBJECT(button), "extra-cb");
 
 	if (cb != NULL)
-		cb(data->user_data, data->u.multifield.fields);
+		cb(data->user_data, data->u.multifield.page);
 
 	purple_request_close(PURPLE_REQUEST_FIELDS, data);
 }
@@ -1879,7 +1879,7 @@
 
 static void *
 pidgin_request_fields(const char *title, const char *primary,
-	const char *secondary, PurpleRequestFields *fields, const char *ok_text,
+	const char *secondary, PurpleRequestPage *page, const char *ok_text,
 	GCallback ok_cb, const char *cancel_text, GCallback cancel_cb,
 	PurpleRequestCommonParameters *cpar, void *user_data)
 {
@@ -1905,9 +1905,9 @@
 	data            = g_new0(PidginRequestData, 1);
 	data->type      = PURPLE_REQUEST_FIELDS;
 	data->user_data = user_data;
-	data->u.multifield.fields = fields;
-
-	purple_request_fields_set_ui_data(fields, data);
+	data->u.multifield.page = page;
+
+	purple_request_page_set_ui_data(page, data);
 
 	extra_actions = purple_request_cpar_get_extra_actions(cpar);
 
@@ -2005,10 +2005,7 @@
 		gtk_box_append(GTK_BOX(vbox), label);
 	}
 
-	for (gl = purple_request_fields_get_groups(fields);
-		 gl != NULL;
-		 gl = gl->next)
-	{
+	for(gl = purple_request_page_get_groups(page); gl != NULL; gl = gl->next) {
 		GList *field_list;
 		size_t field_count = 0;
 		size_t cols = 1;
@@ -2199,11 +2196,13 @@
 	g_object_unref(sg);
 	g_object_unref(datasheet_buttons_sg);
 
-	if (!purple_request_fields_all_required_filled(fields))
+	if(!purple_request_page_all_required_filled(page)) {
 		gtk_widget_set_sensitive(data->ok_button, FALSE);
-
-	if (!purple_request_fields_all_valid(fields))
+	}
+
+	if(!purple_request_page_all_valid(page)) {
 		gtk_widget_set_sensitive(data->ok_button, FALSE);
+	}
 
 	pidgin_auto_parent_window(win);
 
@@ -2424,8 +2423,9 @@
 		gtk_window_destroy(GTK_WINDOW(data->dialog));
 	}
 
-	if (type == PURPLE_REQUEST_FIELDS)
-		purple_request_fields_destroy(data->u.multifield.fields);
+	if(type == PURPLE_REQUEST_FIELDS) {
+		g_clear_object(&data->u.multifield.page);
+	}
 
 	g_free(data);
 }
--- a/pidgin/pidginmooddialog.c	Tue Mar 07 00:22:36 2023 -0600
+++ b/pidgin/pidginmooddialog.c	Tue Mar 07 01:04:42 2023 -0600
@@ -57,19 +57,19 @@
 /*< private
  * pidgin_mood_edit_cb:
  * @connection: The #PurpleConnection instance.
- * @fields: The #PurpleRequestFields
+ * @page: The #PurpleRequestPage
  *
  * This a callback function for when the request dialog has been accepted.
  */
 static void
 pidgin_mood_dialog_edit_cb(PurpleConnection *connection,
-                           PurpleRequestFields *fields)
+                           PurpleRequestPage *page)
 {
 	PurpleRequestField *mood_field = NULL;
 	GList *l = NULL;
 	const gchar *mood = NULL;
 
-	mood_field = purple_request_fields_get_field(fields, "mood");
+	mood_field = purple_request_page_get_field(page, "mood");
 	l = purple_request_field_list_get_selected(mood_field);
 
 	if(l == NULL) {
@@ -87,7 +87,7 @@
 		if (flags & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES) {
 			PurpleRequestField *text_field = NULL;
 
-			text_field = purple_request_fields_get_field(fields, "text");
+			text_field = purple_request_page_get_field(page, "text");
 			text = purple_request_field_string_get_value(text_field);
 		} else {
 			text = NULL;
@@ -245,7 +245,7 @@
 void
 pidgin_mood_dialog_show(PurpleAccount *account) {
 	const gchar *current_mood;
-	PurpleRequestFields *fields;
+	PurpleRequestPage *page;
 	PurpleRequestGroup *g;
 	PurpleRequestField *f;
 	PurpleConnection *gc = NULL;
@@ -264,7 +264,7 @@
 		current_mood = pidgin_mood_get_global_status();
 	}
 
-	fields = purple_request_fields_new();
+	page = purple_request_page_new();
 	g = purple_request_group_new(NULL);
 	f = purple_request_field_list_new("mood", _("Please select your mood from the list"));
 
@@ -299,7 +299,7 @@
 	}
 	purple_request_group_add_field(g, f);
 
-	purple_request_fields_add_group(fields, g);
+	purple_request_page_add_group(page, g);
 
 	/* if the connection allows setting a mood message */
 	if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES)) {
@@ -307,11 +307,11 @@
 		f = purple_request_field_string_new("text",
 		    _("Message (optional)"), NULL, FALSE);
 		purple_request_group_add_field(g, f);
-		purple_request_fields_add_group(fields, g);
+		purple_request_page_add_group(page, g);
 	}
 
 	purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"),
-	                      NULL, fields,
+	                      NULL, page,
 	                      _("OK"), G_CALLBACK(pidgin_mood_dialog_edit_cb),
 	                      _("Cancel"), NULL,
 	                      purple_request_cpar_from_connection(gc), gc);

mercurial