# HG changeset patch
# Node ID f7236e23d4d9
# Parent  ced2446a2560
diff --git a/libpurple/meson.build b/libpurple/meson.build
--- a/libpurple/meson.build
+++ b/libpurple/meson.build
@@ -100,6 +100,7 @@ purple_coresources = [
 	'request/purplerequestfieldaccount.c',
 	'request/purplerequestfieldbool.c',
 	'request/purplerequestfieldchoice.c',
+	'request/purplerequestfielddatasheet.c',
 	'request/purplerequestfieldimage.c',
 	'request/purplerequestfieldint.c',
 	'request/purplerequestfieldlabel.c',
@@ -231,6 +232,7 @@ purple_request_headers = [
 	'request/purplerequestfieldaccount.h',
 	'request/purplerequestfieldbool.h',
 	'request/purplerequestfieldchoice.h',
+	'request/purplerequestfielddatasheet.h',
 	'request/purplerequestfieldimage.h',
 	'request/purplerequestfieldint.h',
 	'request/purplerequestfieldlabel.h',
diff --git a/libpurple/purplerequestfield.h b/libpurple/purplerequestfield.h
--- a/libpurple/purplerequestfield.h
+++ b/libpurple/purplerequestfield.h
@@ -64,14 +64,12 @@ struct _PurpleRequestFieldClass {
 /**
  * PurpleRequestFieldType:
  * @PURPLE_REQUEST_FIELD_NONE: No field.
- * @PURPLE_REQUEST_FIELD_DATASHEET: Datasheet field.
  *
  * A type of field.
  */
 typedef enum
 {
 	PURPLE_REQUEST_FIELD_NONE,
-	PURPLE_REQUEST_FIELD_DATASHEET
 
 } PurpleRequestFieldType;
 
@@ -305,34 +303,6 @@ void purple_request_field_set_sensitive(
 gboolean purple_request_field_is_sensitive(PurpleRequestField *field);
 
 /**************************************************************************/
-/* Datasheet Field API                                                    */
-/**************************************************************************/
-
-/**
- * purple_request_field_datasheet_new:
- * @id:    The field ID.
- * @text:  The label of the field, may be %NULL.
- * @sheet: The datasheet.
- *
- * Creates a datasheet item field.
- *
- * Returns: (transfer full): The new field.
- */
-PurpleRequestField *purple_request_field_datasheet_new(const char *id,
-	const gchar *text, PurpleRequestDatasheet *sheet);
-
-/**
- * purple_request_field_datasheet_get_sheet:
- * @field: The field.
- *
- * Returns a datasheet for a field.
- *
- * Returns: (transfer none): The datasheet object.
- */
-PurpleRequestDatasheet *purple_request_field_datasheet_get_sheet(
-	PurpleRequestField *field);
-
-/**************************************************************************/
 /* Validators for request fields.                                         */
 /**************************************************************************/
 
diff --git a/libpurple/purplerequestfield.h b/libpurple/request/purplerequestfielddatasheet.h
copy from libpurple/purplerequestfield.h
copy to libpurple/request/purplerequestfielddatasheet.h
--- a/libpurple/purplerequestfield.h
+++ b/libpurple/request/purplerequestfielddatasheet.h
@@ -24,8 +24,8 @@
 # error "only <purple.h> may be included directly"
 #endif
 
-#ifndef PURPLE_REQUEST_FIELD_H
-#define PURPLE_REQUEST_FIELD_H
+#ifndef PURPLE_REQUEST_FIELD_DATASHEET_H
+#define PURPLE_REQUEST_FIELD_DATASHEET_H
 
 #include <stdlib.h>
 
@@ -44,269 +44,11 @@ typedef struct _PurpleRequestField Purpl
 
 #define PURPLE_DEFAULT_ACTION_NONE	-1
 
-/**
- * PurpleRequestFieldClass:
- *
- * #PurpleRequestFieldClass defines the interface for a request field.
- *
- * Since: 3.0.0
- */
-struct _PurpleRequestFieldClass {
-	/*< private >*/
-	GObjectClass parent_class;
-
-	/*< public >*/
-
-	/*< private >*/
-	gpointer reserved[4];
-};
-
-/**
- * PurpleRequestFieldType:
- * @PURPLE_REQUEST_FIELD_NONE: No field.
- * @PURPLE_REQUEST_FIELD_DATASHEET: Datasheet field.
- *
- * A type of field.
- */
-typedef enum
-{
-	PURPLE_REQUEST_FIELD_NONE,
-	PURPLE_REQUEST_FIELD_DATASHEET
-
-} PurpleRequestFieldType;
-
-typedef gboolean (*PurpleRequestFieldValidator)(PurpleRequestField *field,
-	gchar **errmsg, gpointer user_data);
-
 G_BEGIN_DECLS
 
-/**************************************************************************/
-/* Field API                                                              */
-/**************************************************************************/
-
-#define PURPLE_TYPE_REQUEST_FIELD (purple_request_field_get_type())
-G_DECLARE_DERIVABLE_TYPE(PurpleRequestField, purple_request_field,
-                         PURPLE, REQUEST_FIELD, GObject)
-
-/**
- * purple_request_field_new:
- * @id:   The field ID.
- * @text: The text label of the field.
- * @type: The type of field.
- *
- * Creates a field of the specified type.
- *
- * Returns: (transfer full): The new field.
- */
-PurpleRequestField *purple_request_field_new(const char *id, const char *text,
-										 PurpleRequestFieldType type);
-
-/**
- * purple_request_field_set_label:
- * @field: The field.
- * @label: The text label.
- *
- * Sets the label text of a field.
- */
-void purple_request_field_set_label(PurpleRequestField *field, const char *label);
-
-/**
- * purple_request_field_set_visible:
- * @field:   The field.
- * @visible: TRUE if visible, or FALSE if not.
- *
- * Sets whether or not a field is visible.
- */
-void purple_request_field_set_visible(PurpleRequestField *field, gboolean visible);
-
-/**
- * purple_request_field_set_type_hint:
- * @field:     The field.
- * @type_hint: The type hint.
- *
- * Sets the type hint for the field.
- *
- * This is optionally used by the UIs to provide such features as
- * auto-completion for type hints like "account" and "screenname".
- */
-void purple_request_field_set_type_hint(PurpleRequestField *field,
-									  const char *type_hint);
-
-/**
- * purple_request_field_set_tooltip:
- * @field:     The field.
- * @tooltip:   The tooltip text.
- *
- * Sets the tooltip for the field.
- *
- * This is optionally used by the UIs to provide a tooltip for
- * the field.
- */
-void purple_request_field_set_tooltip(PurpleRequestField *field,
-									const char *tooltip);
-
-/**
- * purple_request_field_set_required:
- * @field:    The field.
- * @required: TRUE if required, or FALSE.
- *
- * Sets whether or not a field is required.
- */
-void purple_request_field_set_required(PurpleRequestField *field,
-									 gboolean required);
-
-/**
- * purple_request_field_get_field_type:
- * @field: The field.
- *
- * Returns the type of a field.
- *
- * Returns: The field's type.
- */
-PurpleRequestFieldType purple_request_field_get_field_type(PurpleRequestField *field);
-
-/**
- * purple_request_field_get_group:
- * @field: The field.
- *
- * Returns the group for the field.
- *
- * Returns: (transfer none): The UI data.
- */
-PurpleRequestGroup *purple_request_field_get_group(PurpleRequestField *field);
-
-/**
- * purple_request_field_get_id:
- * @field: The field.
- *
- * Returns the ID of a field.
- *
- * Returns: The ID
- */
-const char *purple_request_field_get_id(PurpleRequestField *field);
-
-/**
- * purple_request_field_get_label:
- * @field: The field.
- *
- * Returns the label text of a field.
- *
- * Returns: The label text.
- */
-const char *purple_request_field_get_label(PurpleRequestField *field);
-
-/**
- * purple_request_field_is_visible:
- * @field: The field.
- *
- * Returns whether or not a field is visible.
- *
- * Returns: TRUE if the field is visible. FALSE otherwise.
- */
-gboolean purple_request_field_is_visible(PurpleRequestField *field);
-
-/**
- * purple_request_field_get_type_hint:
- * @field: The field.
- *
- * Returns the field's type hint.
- *
- * Returns: The field's type hint.
- */
-const char *purple_request_field_get_type_hint(PurpleRequestField *field);
-
-/**
- * purple_request_field_get_tooltip:
- * @field: The field.
- *
- * Returns the field's tooltip.
- *
- * Returns: The field's tooltip.
- */
-const char *purple_request_field_get_tooltip(PurpleRequestField *field);
-
-/**
- * purple_request_field_is_required:
- * @field: The field.
- *
- * Returns whether or not a field is required.
- *
- * Returns: TRUE if the field is required, or FALSE.
- */
-gboolean purple_request_field_is_required(PurpleRequestField *field);
-
-/**
- * purple_request_field_is_filled:
- * @field: The field.
- *
- * Checks, if specified field has value.
- *
- * Returns: TRUE if the field has value, or FALSE.
- */
-gboolean purple_request_field_is_filled(PurpleRequestField *field);
-
-/**
- * purple_request_field_set_validator:
- * @field:     The field.
- * @validator: (scope notified): The validator callback, NULL to disable validation.
- * @user_data: The data to pass to the callback.
- *
- * Sets validator for a single field.
- */
-void purple_request_field_set_validator(PurpleRequestField *field,
-	PurpleRequestFieldValidator validator, void *user_data);
-
-/**
- * purple_request_field_is_validatable:
- * @field: The field.
- *
- * Returns whether or not field has validator set.
- *
- * Returns: TRUE if the field has validator, or FALSE.
- */
-gboolean purple_request_field_is_validatable(PurpleRequestField *field);
-
-/**
- * purple_request_field_is_valid:
- * @field:  The field.
- * @errmsg: If non-NULL, the memory area, where the pointer to validation
- *         failure message will be set.
- *
- * Checks, if specified field is valid.
- *
- * If detailed message about failure reason is needed, there is an option to
- * return (via errmsg argument) pointer to newly allocated error message.
- * It must be freed with g_free after use.
- *
- * Note: empty, not required fields are valid.
- *
- * Returns: TRUE, if the field is valid, FALSE otherwise.
- */
-gboolean purple_request_field_is_valid(PurpleRequestField *field, gchar **errmsg);
-
-/**
- * purple_request_field_set_sensitive:
- * @field:     The field.
- * @sensitive: TRUE if the field should be sensitive for user input.
- *
- * Sets field editable.
- */
-void purple_request_field_set_sensitive(PurpleRequestField *field,
-	gboolean sensitive);
-
-/**
- * purple_request_field_is_sensitive:
- * @field: The field.
- *
- * Checks, if field is editable.
- *
- * Returns: TRUE, if the field is sensitive for user input.
- */
-gboolean purple_request_field_is_sensitive(PurpleRequestField *field);
-
-/**************************************************************************/
-/* Datasheet Field API                                                    */
-/**************************************************************************/
+#define PURPLE_TYPE_REQUEST_FIELD_DATASHEET (purple_request_field_datasheet_get_type())
+G_DECLARE_FINAL_TYPE(PurpleRequestFieldDatasheet, purple_request_field_datasheet,
+                     PURPLE, REQUEST_FIELD_DATASHEET, PurpleRequestField)
 
 /**
  * purple_request_field_datasheet_new:
@@ -318,8 +60,7 @@ gboolean purple_request_field_is_sensiti
  *
  * Returns: (transfer full): The new field.
  */
-PurpleRequestField *purple_request_field_datasheet_new(const char *id,
-	const gchar *text, PurpleRequestDatasheet *sheet);
+PurpleRequestField *purple_request_field_datasheet_new(const char *id, const gchar *text, PurpleRequestDatasheet *sheet);
 
 /**
  * purple_request_field_datasheet_get_sheet:
@@ -329,44 +70,8 @@ PurpleRequestField *purple_request_field
  *
  * Returns: (transfer none): The datasheet object.
  */
-PurpleRequestDatasheet *purple_request_field_datasheet_get_sheet(
-	PurpleRequestField *field);
-
-/**************************************************************************/
-/* Validators for request fields.                                         */
-/**************************************************************************/
-
-/**
- * purple_request_field_email_validator:
- * @field: The field.
- * @errmsg: (out) (optional): destination for error message.
- * @user_data: Ignored.
- *
- * Validates a field which should contain an email address.
- *
- * See purple_request_field_set_validator().
- *
- * Returns: TRUE, if field contains valid email address.
- */
-gboolean purple_request_field_email_validator(PurpleRequestField *field,
-	gchar **errmsg, void *user_data);
-
-/**
- * purple_request_field_alphanumeric_validator:
- * @field: The field.
- * @errmsg: (allow-none): destination for error message.
- * @allowed_characters: (allow-none): allowed character list
- *                      (NULL-terminated string).
- *
- * Validates a field which should contain alphanumeric content.
- *
- * See purple_request_field_set_validator().
- *
- * Returns: TRUE, if field contains only alphanumeric characters.
- */
-gboolean purple_request_field_alphanumeric_validator(PurpleRequestField *field,
-	gchar **errmsg, void *allowed_characters);
+PurpleRequestDatasheet *purple_request_field_datasheet_get_sheet(PurpleRequestFieldDatasheet *field);
 
 G_END_DECLS
 
-#endif /* PURPLE_REQUEST_FIELD_H */
+#endif /* PURPLE_REQUEST_FIELD_DATASHEET_H */
diff --git a/libpurple/purplerequestfield.c b/libpurple/purplerequestfield.c
--- a/libpurple/purplerequestfield.c
+++ b/libpurple/purplerequestfield.c
@@ -40,12 +40,6 @@ typedef struct {
 	gboolean required;
 	gboolean sensitive;
 
-	union {
-		struct {
-			PurpleRequestDatasheet *sheet;
-		} datasheet;
-	} u;
-
 	void *ui_data;
 	char *tooltip;
 
@@ -189,10 +183,6 @@ purple_request_field_finalize(GObject *o
 	g_free(priv->type_hint);
 	g_free(priv->tooltip);
 
-	if(priv->type == PURPLE_REQUEST_FIELD_DATASHEET) {
-		purple_request_datasheet_free(priv->u.datasheet.sheet);
-	}
-
 	G_OBJECT_CLASS(purple_request_field_parent_class)->finalize(obj);
 }
 
@@ -624,34 +614,3 @@ purple_request_field_is_sensitive(Purple
 
 	return priv->sensitive;
 }
-
-PurpleRequestField *
-purple_request_field_datasheet_new(const char *id,
-	const gchar *text, PurpleRequestDatasheet *sheet)
-{
-	PurpleRequestField *field;
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(id != NULL, NULL);
-	g_return_val_if_fail(sheet != NULL, NULL);
-
-	field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_DATASHEET);
-	priv = purple_request_field_get_instance_private(field);
-
-	priv->u.datasheet.sheet = sheet;
-
-	return field;
-}
-
-PurpleRequestDatasheet *
-purple_request_field_datasheet_get_sheet(PurpleRequestField *field)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
-
-	priv = purple_request_field_get_instance_private(field);
-	g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_DATASHEET, NULL);
-
-	return priv->u.datasheet.sheet;
-}
diff --git a/libpurple/purplerequestfield.c b/libpurple/request/purplerequestfielddatasheet.c
copy from libpurple/purplerequestfield.c
copy to libpurple/request/purplerequestfielddatasheet.c
--- a/libpurple/purplerequestfield.c
+++ b/libpurple/request/purplerequestfielddatasheet.c
@@ -22,116 +22,51 @@
 #include <glib/gi18n-lib.h>
 
 #include "glibcompat.h"
-#include "request.h"
-#include "request/purplerequestfieldstring.h"
-#include "debug.h"
-#include "purplekeyvaluepair.h"
-#include "purpleprivate.h"
-
-typedef struct {
-	PurpleRequestFieldType type;
-	PurpleRequestGroup *group;
-
-	char *id;
-	char *label;
-	char *type_hint;
+#include "purplerequestfield.h"
+#include "purplerequestfielddatasheet.h"
 
-	gboolean visible;
-	gboolean required;
-	gboolean sensitive;
+struct _PurpleRequestFieldDatasheet {
+	PurpleRequestField parent;
 
-	union {
-		struct {
-			PurpleRequestDatasheet *sheet;
-		} datasheet;
-	} u;
-
-	void *ui_data;
-	char *tooltip;
-
-	PurpleRequestFieldValidator validator;
-	void *validator_data;
-} PurpleRequestFieldPrivate;
+	PurpleRequestDatasheet *sheet;
+};
 
 enum {
 	PROP_0,
-	PROP_ID,
-	PROP_LABEL,
-	PROP_VISIBLE,
-	PROP_SENSITIVE,
-	PROP_TYPE_HINT,
-	PROP_TOOLTIP,
-	PROP_REQUIRED,
-	PROP_IS_VALIDATABLE,
+	PROP_SHEET,
 	N_PROPERTIES,
 };
 static GParamSpec *properties[N_PROPERTIES] = {NULL, };
 
-G_DEFINE_TYPE_WITH_PRIVATE(PurpleRequestField, purple_request_field, G_TYPE_OBJECT)
-
 /******************************************************************************
  * Helpers
  *****************************************************************************/
 static void
-purple_request_field_set_id(PurpleRequestField *field, const char *id) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	priv = purple_request_field_get_instance_private(field);
-
-	g_free(priv->id);
-	priv->id = g_strdup(id);
+purple_request_field_datasheet_set_sheet(PurpleRequestFieldDatasheet *field,
+                                         PurpleRequestDatasheet *sheet)
+{
+	g_clear_pointer(&field->sheet, purple_request_datasheet_free);
+	field->sheet = sheet;
 
-	g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_ID]);
-}
-
-static void
-purple_request_field_set_field_type(PurpleRequestField *field,
-                                    PurpleRequestFieldType type)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	priv = purple_request_field_get_instance_private(field);
-
-	priv->type = type;
+	g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_SHEET]);
 }
 
 /******************************************************************************
  * GObject Implementation
  *****************************************************************************/
+G_DEFINE_TYPE(PurpleRequestFieldDatasheet, purple_request_field_datasheet,
+              PURPLE_TYPE_REQUEST_FIELD)
+
 static void
-purple_request_field_get_property(GObject *obj, guint param_id, GValue *value,
-                                  GParamSpec *pspec)
+purple_request_field_datasheet_get_property(GObject *obj, guint param_id,
+                                            GValue *value, GParamSpec *pspec)
 {
-	PurpleRequestField *field = PURPLE_REQUEST_FIELD(obj);
+	PurpleRequestFieldDatasheet *field = PURPLE_REQUEST_FIELD_DATASHEET(obj);
 
 	switch(param_id) {
-		case PROP_ID:
-			g_value_set_string(value, purple_request_field_get_id(field));
-			break;
-		case PROP_LABEL:
-			g_value_set_string(value, purple_request_field_get_label(field));
-			break;
-		case PROP_VISIBLE:
-			g_value_set_boolean(value, purple_request_field_is_visible(field));
-			break;
-		case PROP_SENSITIVE:
-			g_value_set_boolean(value,
-			                    purple_request_field_is_sensitive(field));
-			break;
-		case PROP_TYPE_HINT:
-			g_value_set_string(value,
-			                   purple_request_field_get_type_hint(field));
-			break;
-		case PROP_TOOLTIP:
-			g_value_set_string(value, purple_request_field_get_tooltip(field));
-			break;
-		case PROP_REQUIRED:
-			g_value_set_boolean(value,
-			                    purple_request_field_is_required(field));
-			break;
-		case PROP_IS_VALIDATABLE:
-			g_value_set_boolean(value,
-			                    purple_request_field_is_validatable(field));
+		case PROP_SHEET:
+			g_value_set_pointer(value,
+			                    purple_request_field_datasheet_get_sheet(field));
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -140,36 +75,16 @@ purple_request_field_get_property(GObjec
 }
 
 static void
-purple_request_field_set_property(GObject *obj, guint param_id,
-                                  const GValue *value, GParamSpec *pspec)
+purple_request_field_datasheet_set_property(GObject *obj, guint param_id,
+                                            const GValue *value,
+                                            GParamSpec *pspec)
 {
-	PurpleRequestField *field = PURPLE_REQUEST_FIELD(obj);
+	PurpleRequestFieldDatasheet *field = PURPLE_REQUEST_FIELD_DATASHEET(obj);
 
 	switch(param_id) {
-		case PROP_ID:
-			purple_request_field_set_id(field, g_value_get_string(value));
-			break;
-		case PROP_LABEL:
-			purple_request_field_set_label(field, g_value_get_string(value));
-			break;
-		case PROP_VISIBLE:
-			purple_request_field_set_visible(field,
-			                                 g_value_get_boolean(value));
-			break;
-		case PROP_SENSITIVE:
-			purple_request_field_set_sensitive(field,
-			                                   g_value_get_boolean(value));
-			break;
-		case PROP_TYPE_HINT:
-			purple_request_field_set_type_hint(field,
-			                                   g_value_get_string(value));
-			break;
-		case PROP_TOOLTIP:
-			purple_request_field_set_tooltip(field, g_value_get_string(value));
-			break;
-		case PROP_REQUIRED:
-			purple_request_field_set_required(field,
-			                                  g_value_get_boolean(value));
+		case PROP_SHEET:
+			purple_request_field_datasheet_set_sheet(field,
+			                                         g_value_get_pointer(value));
 			break;
 		default:
 			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
@@ -178,145 +93,37 @@ purple_request_field_set_property(GObjec
 }
 
 static void
-purple_request_field_finalize(GObject *obj) {
-	PurpleRequestField *field = PURPLE_REQUEST_FIELD(obj);
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	priv = purple_request_field_get_instance_private(field);
-
-	g_free(priv->id);
-	g_free(priv->label);
-	g_free(priv->type_hint);
-	g_free(priv->tooltip);
+purple_request_field_datasheet_finalize(GObject *obj) {
+	PurpleRequestFieldDatasheet *field = PURPLE_REQUEST_FIELD_DATASHEET(obj);
 
-	if(priv->type == PURPLE_REQUEST_FIELD_DATASHEET) {
-		purple_request_datasheet_free(priv->u.datasheet.sheet);
-	}
-
-	G_OBJECT_CLASS(purple_request_field_parent_class)->finalize(obj);
-}
+	g_clear_pointer(&field->sheet, purple_request_datasheet_free);
 
-static void
-purple_request_field_init(PurpleRequestField *field) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	priv = purple_request_field_get_instance_private(field);
-
-	priv->visible = TRUE;
-	priv->sensitive = TRUE;
+	G_OBJECT_CLASS(purple_request_field_datasheet_parent_class)->finalize(obj);
 }
 
 static void
-purple_request_field_class_init(PurpleRequestFieldClass *klass) {
+purple_request_field_datasheet_init(G_GNUC_UNUSED PurpleRequestFieldDatasheet *field) {
+}
+
+static void
+purple_request_field_datasheet_class_init(PurpleRequestFieldDatasheetClass *klass) {
 	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
 
-	obj_class->finalize = purple_request_field_finalize;
-	obj_class->get_property = purple_request_field_get_property;
-	obj_class->set_property = purple_request_field_set_property;
+	obj_class->finalize = purple_request_field_datasheet_finalize;
+	obj_class->get_property = purple_request_field_datasheet_get_property;
+	obj_class->set_property = purple_request_field_datasheet_set_property;
 
 	/**
-	 * PurpleRequestField:id:
-	 *
-	 * The ID of the field.
-	 *
-	 * Since: 3.0.0
-	 */
-	properties[PROP_ID] = g_param_spec_string(
-		"id", "id",
-		"The ID of the field.",
-		NULL,
-		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
-	/**
-	 * PurpleRequestField:label:
+	 * PurpleRequestFieldDatasheet:sheet:
 	 *
-	 * The label of the field.
-	 *
-	 * Since: 3.0.0
-	 */
-	properties[PROP_LABEL] = g_param_spec_string(
-		"label", "label",
-		"The label of the field.",
-		NULL,
-		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	/**
-	 * PurpleRequestField:visible:
-	 *
-	 * Whether the field should be visible.
+	 * The datasheet of the field.
 	 *
 	 * Since: 3.0.0
 	 */
-	properties[PROP_VISIBLE] = g_param_spec_boolean(
-		"visible", "visible",
-		"Whether the field should be visible.",
-		TRUE,
-		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	/**
-	 * PurpleRequestField:sensitive:
-	 *
-	 * Whether the field should be sensitive.
-	 *
-	 * Since: 3.0.0
-	 */
-	properties[PROP_SENSITIVE] = g_param_spec_boolean(
-		"sensitive", "sensitive",
-		"Whether the field should be sensitive.",
-		TRUE,
-		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	/**
-	 * PurpleRequestField:type-hint:
-	 *
-	 * The type hint of the field.
-	 *
-	 * Since: 3.0.0
-	 */
-	properties[PROP_TYPE_HINT] = g_param_spec_string(
-		"type-hint", "type-hint",
-		"The type hint of the field.",
-		NULL,
-		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	/**
-	 * PurpleRequestField:tooltip:
-	 *
-	 * The tooltip of the field.
-	 *
-	 * Since: 3.0.0
-	 */
-	properties[PROP_TOOLTIP] = g_param_spec_string(
-		"tooltip", "tooltip",
-		"The tooltip of the field.",
-		NULL,
-		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	/**
-	 * PurpleRequestField:required:
-	 *
-	 * Whether the field is required to complete the request.
-	 *
-	 * Since: 3.0.0
-	 */
-	properties[PROP_REQUIRED] = g_param_spec_boolean(
-		"required", "required",
-		"Whether the field is required to complete the request.",
-		FALSE,
-		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-	/**
-	 * PurpleRequestField:is-validatable:
-	 *
-	 * Whether the field can be validated by the requestor.
-	 *
-	 * Since: 3.0.0
-	 */
-	properties[PROP_IS_VALIDATABLE] = g_param_spec_boolean(
-		"is-validatable", "is-validatable",
-		"Whether the field can be validated by the requestor.",
-		FALSE,
-		G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+	properties[PROP_SHEET] = g_param_spec_pointer(
+		"sheet", "sheet",
+		"The datasheet of the field.",
+		G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
 
 	g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
 }
@@ -325,333 +132,22 @@ purple_request_field_class_init(PurpleRe
  * Public API
  *****************************************************************************/
 PurpleRequestField *
-purple_request_field_new(const char *id, const char *text,
-                         PurpleRequestFieldType type)
-{
-	PurpleRequestField *field;
-
-	g_return_val_if_fail(id != NULL, NULL);
-	g_return_val_if_fail(type != PURPLE_REQUEST_FIELD_NONE, NULL);
-
-	field = g_object_new(PURPLE_TYPE_REQUEST_FIELD,
-	                     "id", id,
-	                     "label", text,
-	                     NULL);
-	purple_request_field_set_field_type(field, type);
-
-	return field;
-}
-
-void
-_purple_request_field_set_group(PurpleRequestField *field,
-                                PurpleRequestGroup *group)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field));
-
-	priv = purple_request_field_get_instance_private(field);
-
-	priv->group = group;
-}
-
-void
-purple_request_field_set_label(PurpleRequestField *field, const char *label)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field));
-
-	priv = purple_request_field_get_instance_private(field);
-
-	g_free(priv->label);
-	priv->label = g_strdup(label);
-
-	g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_LABEL]);
-}
-
-void
-purple_request_field_set_visible(PurpleRequestField *field, gboolean visible)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field));
-
-	priv = purple_request_field_get_instance_private(field);
-
-	priv->visible = visible;
-
-	g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_VISIBLE]);
-}
-
-void
-purple_request_field_set_type_hint(PurpleRequestField *field,
-								 const char *type_hint)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field));
-
-	priv = purple_request_field_get_instance_private(field);
-
-	g_free(priv->type_hint);
-	priv->type_hint = g_strdup(type_hint);
-
-	g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_TYPE_HINT]);
-}
-
-void
-purple_request_field_set_tooltip(PurpleRequestField *field, const char *tooltip)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field));
-
-	priv = purple_request_field_get_instance_private(field);
-
-	g_free(priv->tooltip);
-	priv->tooltip = g_strdup(tooltip);
-
-	g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_TOOLTIP]);
-}
-
-void
-purple_request_field_set_required(PurpleRequestField *field, gboolean required)
+purple_request_field_datasheet_new(const char *id, const char *text,
+                                   PurpleRequestDatasheet *sheet)
 {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field));
-
-	priv = purple_request_field_get_instance_private(field);
-
-	if(priv->required == required) {
-		return;
-	}
-
-	priv->required = required;
-
-	if(PURPLE_IS_REQUEST_GROUP(priv->group)) {
-		_purple_request_group_set_field_required(priv->group, field,
-		                                         required);
-	}
-
-	g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_REQUIRED]);
-}
-
-PurpleRequestFieldType
-purple_request_field_get_field_type(PurpleRequestField *field) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field),
-	                     PURPLE_REQUEST_FIELD_NONE);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->type;
-}
-
-PurpleRequestGroup *
-purple_request_field_get_group(PurpleRequestField *field) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->group;
-}
-
-const char *
-purple_request_field_get_id(PurpleRequestField *field) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->id;
-}
-
-const char *
-purple_request_field_get_label(PurpleRequestField *field) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->label;
-}
-
-gboolean
-purple_request_field_is_visible(PurpleRequestField *field) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->visible;
-}
-
-const char *
-purple_request_field_get_type_hint(PurpleRequestField *field) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->type_hint;
-}
-
-const char *
-purple_request_field_get_tooltip(PurpleRequestField *field) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->tooltip;
-}
-
-gboolean
-purple_request_field_is_required(PurpleRequestField *field) {
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->required;
-}
-
-gboolean
-purple_request_field_is_filled(PurpleRequestField *field) {
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE);
-
-	if(PURPLE_IS_REQUEST_FIELD_STRING(field)) {
-		PurpleRequestFieldString *sfield = PURPLE_REQUEST_FIELD_STRING(field);
-		return !purple_strempty(purple_request_field_string_get_value(sfield));
-	}
-
-	return TRUE;
-}
-
-void
-purple_request_field_set_validator(PurpleRequestField *field,
-	PurpleRequestFieldValidator validator, void *user_data)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field));
-
-	priv = purple_request_field_get_instance_private(field);
-
-	priv->validator = validator;
-	priv->validator_data = validator ? user_data : NULL;
-
-	if(PURPLE_IS_REQUEST_GROUP(priv->group)) {
-		_purple_request_group_set_field_validator(priv->group, field,
-		                                          validator != NULL);
-	}
-
-	g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_IS_VALIDATABLE]);
-}
-
-gboolean
-purple_request_field_is_validatable(PurpleRequestField *field)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->validator != NULL;
-}
-
-gboolean
-purple_request_field_is_valid(PurpleRequestField *field, gchar **errmsg)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-	gboolean valid;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	if(!priv->validator) {
-		return TRUE;
-	}
-
-	if (!purple_request_field_is_required(field) &&
-		!purple_request_field_is_filled(field))
-		return TRUE;
-
-	valid = priv->validator(field, errmsg, priv->validator_data);
-
-	if (valid && errmsg)
-		*errmsg = NULL;
-
-	return valid;
-}
-
-void
-purple_request_field_set_sensitive(PurpleRequestField *field,
-	gboolean sensitive)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field));
-
-	priv = purple_request_field_get_instance_private(field);
-
-	priv->sensitive = sensitive;
-
-	g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_SENSITIVE]);
-}
-
-gboolean
-purple_request_field_is_sensitive(PurpleRequestField *field)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE);
-
-	priv = purple_request_field_get_instance_private(field);
-
-	return priv->sensitive;
-}
-
-PurpleRequestField *
-purple_request_field_datasheet_new(const char *id,
-	const gchar *text, PurpleRequestDatasheet *sheet)
-{
-	PurpleRequestField *field;
-	PurpleRequestFieldPrivate *priv = NULL;
-
 	g_return_val_if_fail(id != NULL, NULL);
 	g_return_val_if_fail(sheet != NULL, NULL);
 
-	field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_DATASHEET);
-	priv = purple_request_field_get_instance_private(field);
-
-	priv->u.datasheet.sheet = sheet;
-
-	return field;
+	return g_object_new(PURPLE_TYPE_REQUEST_FIELD_DATASHEET,
+	                    "id", id,
+	                    "label", text,
+	                    "sheet", sheet,
+	                    NULL);
 }
 
 PurpleRequestDatasheet *
-purple_request_field_datasheet_get_sheet(PurpleRequestField *field)
-{
-	PurpleRequestFieldPrivate *priv = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL);
+purple_request_field_datasheet_get_sheet(PurpleRequestFieldDatasheet *field) {
+	g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_DATASHEET(field), NULL);
 
-	priv = purple_request_field_get_instance_private(field);
-	g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_DATASHEET, NULL);
-
-	return priv->u.datasheet.sheet;
+	return field->sheet;
 }
diff --git a/pidgin/gtkrequest.c b/pidgin/gtkrequest.c
--- a/pidgin/gtkrequest.c
+++ b/pidgin/gtkrequest.c
@@ -1772,6 +1772,7 @@ datasheet_action_clicked(GtkButton *btn,
 static GtkWidget *
 create_datasheet_field(PurpleRequestField *field, GtkSizeGroup *buttons_sg)
 {
+	PurpleRequestFieldDatasheet *dfield = PURPLE_REQUEST_FIELD_DATASHEET(field);
 	PurpleRequestDatasheet *sheet;
 	guint i, col_count;
 	GType *col_types;
@@ -1785,7 +1786,7 @@ create_datasheet_field(PurpleRequestFiel
 	GtkWidget *buttons_box;
 	const GList *it;
 
-	sheet = purple_request_field_datasheet_get_sheet(field);
+	sheet = purple_request_field_datasheet_get_sheet(dfield);
 	main_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
 
 	col_count = purple_request_datasheet_get_column_count(sheet);
@@ -2044,12 +2045,10 @@ pidgin_request_fields(const char *title,
 		for (fl = field_list; fl != NULL; fl = fl->next)
 		{
 			PurpleRequestField *field = PURPLE_REQUEST_FIELD(fl->data);
-			PurpleRequestFieldType type;
-
-			type = purple_request_field_get_field_type(field);
-
-			if (type == PURPLE_REQUEST_FIELD_DATASHEET)
+
+			if(PURPLE_IS_REQUEST_FIELD_DATASHEET(field)) {
 				contains_resizable = TRUE;
+			}
 
 			if(PURPLE_IS_REQUEST_FIELD_LABEL(field)) {
 				rows++;
@@ -2089,7 +2088,6 @@ pidgin_request_fields(const char *title,
 			{
 				size_t col_offset = 0;
 				PurpleRequestField *field = PURPLE_REQUEST_FIELD(fl->data);
-				PurpleRequestFieldType type;
 				GtkWidget *widget = NULL;
 				gchar *field_label;
 
@@ -2099,7 +2097,6 @@ pidgin_request_fields(const char *title,
 					continue;
 				}
 
-				type = purple_request_field_get_field_type(field);
 				field_label = pidgin_request_escape(cpar,
 					purple_request_field_get_label(field));
 
@@ -2160,10 +2157,11 @@ pidgin_request_fields(const char *title,
 						widget = create_image_field(field);
 					} else if(PURPLE_IS_REQUEST_FIELD_ACCOUNT(field)) {
 						widget = create_account_field(field);
-					} else if (type == PURPLE_REQUEST_FIELD_DATASHEET)
+					} else if(PURPLE_IS_REQUEST_FIELD_DATASHEET(field)) {
 						widget = create_datasheet_field(field, datasheet_buttons_sg);
-					else
+					} else {
 						continue;
+					}
 				}
 
 				gtk_widget_set_sensitive(widget,
