# HG changeset patch
# Node ID 3590de5ec7c4
# Parent  d8a78f5c982d
diff --git a/pidgin/pidginaccounteditor.c b/pidgin/pidginaccounteditor.c
--- a/pidgin/pidginaccounteditor.c
+++ b/pidgin/pidginaccounteditor.c
@@ -22,17 +22,50 @@
 
 #include <glib/gi18n-lib.h>
 
+#include <adwaita.h>
+
 #include "pidginaccounteditor.h"
 
-#include "pidginproxyoptions.h"
+#include "pidginprotocolchooser.h"
 
 struct _PidginAccountEditor {
 	GtkDialog parent;
 
 	PurpleAccount *account;
 
-	GtkWidget *notebook;
+	GtkCssProvider *css_provider;
+
+	/* Login Options */
+	GtkWidget *login_options;
+	GtkWidget *protocol;
+	GtkWidget *username;
+
+	GList *user_split_entries;
+	GList *user_split_rows;
+
+	/* User Options */
+	GtkWidget *alias;
+
+	GtkFileChooserNative *avatar_dialog;
+	GdkPixbuf *avatar_pixbuf;
+	GtkWidget *avatar_row;
+	GtkWidget *use_custom_avatar;
+	GtkWidget *avatar;
+
+	/* Advanced Options */
+	GtkWidget *advanced_group;
+	GtkWidget *advanced_toggle;
+
+	GList *advanced_entries;
+	GList *advanced_rows;
+
+	/* Proxy Options */
+	GtkWidget *proxy_type;
 	GtkWidget *proxy_options;
+	GtkWidget *proxy_host;
+	GtkWidget *proxy_port;
+	GtkWidget *proxy_username;
+	GtkWidget *proxy_password;
 };
 
 enum {
@@ -46,45 +79,764 @@
  * Helpers
  *****************************************************************************/
 static void
+pidgin_account_editor_add_user_split(gpointer data, gpointer user_data) {
+	PurpleAccountUserSplit *split = data;
+	PidginAccountEditor *editor = user_data;
+	GtkWidget *entry = NULL;
+
+	if(!purple_account_user_split_is_constant(split)) {
+		GtkStyleContext *context = NULL;
+		GtkWidget *row = NULL;
+
+		row = adw_action_row_new();
+		editor->user_split_rows = g_list_append(editor->user_split_rows, row);
+		adw_preferences_group_add(ADW_PREFERENCES_GROUP(editor->login_options),
+		                          row);
+
+		adw_preferences_row_set_title(ADW_PREFERENCES_ROW(row),
+		                              purple_account_user_split_get_text(split));
+
+		entry = gtk_entry_new();
+		gtk_widget_set_hexpand(entry, TRUE);
+		gtk_widget_set_valign(entry, GTK_ALIGN_CENTER);
+		adw_action_row_add_suffix(ADW_ACTION_ROW(row), entry);
+		adw_action_row_set_activatable_widget(ADW_ACTION_ROW(row), entry);
+
+		context = gtk_widget_get_style_context(entry);
+		gtk_style_context_add_provider(context,
+		                               GTK_STYLE_PROVIDER(editor->css_provider),
+		                               GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+	}
+
+	editor->user_split_entries = g_list_append(editor->user_split_entries,
+	                                           entry);
+}
+
+static gboolean
+pidgin_account_editor_update_login_options(PidginAccountEditor *editor,
+                                           PurpleProtocol *protocol)
+{
+	GList *user_splits = NULL;
+	GList *split_item = NULL;
+	GList *entry_item = NULL;
+	gchar *username = NULL;
+
+	/* Clear out the old user splits from our list and their container. */
+	g_clear_pointer(&editor->user_split_entries, g_list_free);
+	while(editor->user_split_rows != NULL) {
+		adw_preferences_group_remove(ADW_PREFERENCES_GROUP(editor->login_options),
+		                             editor->user_split_rows->data);
+
+		editor->user_split_rows = g_list_delete_link(editor->user_split_rows,
+		                                             editor->user_split_rows);
+	}
+
+	/* Add the user splits for the protocol. */
+	user_splits = purple_protocol_get_user_splits(protocol);
+	if(user_splits != NULL) {
+		g_list_foreach(user_splits, pidgin_account_editor_add_user_split, editor);
+	}
+
+	/* If we have an account, populate its values. */
+	if(PURPLE_IS_ACCOUNT(editor->account)) {
+		/* The username will be split apart below and eventually set as the text
+		 * in the username entry.
+		 */
+		username = g_strdup(purple_account_get_username(editor->account));
+	}
+
+	/* Filling out the user splits is a pain. If we have an account, we created
+	 * a copy of the username above. We then iterate the user splits backwards
+	 * so we can insert a null terminator at the start of each split we find in
+	 * the username.
+	 */
+	split_item = g_list_last(user_splits);
+	entry_item = g_list_last(editor->user_split_entries);
+	while(split_item != NULL && entry_item != NULL) {
+		GtkWidget *entry = entry_item->data;
+		PurpleAccountUserSplit *split = split_item->data;
+		gchar *ptr = NULL;
+		const gchar *value = NULL;
+
+		if(username != NULL) {
+			gchar sep = purple_account_user_split_get_separator(split);
+
+			if(purple_account_user_split_get_reverse(split)) {
+				ptr = strrchr(username, sep);
+			} else {
+				ptr = strchr(username, sep);
+			}
+
+			if(ptr != NULL) {
+				/* Insert a null terminator in place of the separator. */
+				*ptr = '\0';
+
+				/* Set the value to the first byte after the separator. */
+				value = ptr + 1;
+			}
+		}
+
+		if(value == NULL) {
+			value = purple_account_user_split_get_default_value(split);
+		}
+
+		if(value != NULL && entry != NULL) {
+			gtk_editable_set_text(GTK_EDITABLE(entry), value);
+		}
+
+		split_item = split_item->prev;
+		entry_item = entry_item->prev;
+	}
+
+	/* Free the user splits. */
+	g_list_free_full(user_splits,
+	                 (GDestroyNotify)purple_account_user_split_destroy);
+
+	/* Set the username entry to the remaining text in username and free our
+	 * copy of said username.
+	 */
+	if(username != NULL) {
+		gtk_editable_set_text(GTK_EDITABLE(editor->username), username);
+		g_free(username);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void
+pidgin_account_editor_update_user_options(PidginAccountEditor *editor,
+                                          PurpleProtocol *protocol)
+{
+	PurpleBuddyIconSpec *icon_spec = NULL;
+	PurpleImage *image = NULL;
+	gboolean show_avatar_opts = TRUE;
+	const gchar *svalue = "";
+	gboolean use_global = TRUE;
+
+	/* Check if the protocol supports avatars. */
+	icon_spec = purple_protocol_get_icon_spec(protocol);
+	show_avatar_opts = (icon_spec != NULL && icon_spec->format != NULL);
+	purple_buddy_icon_spec_free(icon_spec);
+
+	gtk_widget_set_visible(editor->avatar_row, show_avatar_opts);
+
+	/* Determine our values. */
+	if(editor->account != NULL) {
+		svalue = purple_account_get_private_alias(editor->account);
+		image = purple_buddy_icons_find_account_icon(editor->account);
+		use_global = purple_account_get_bool(editor->account,
+		                                     "use-global-buddyicon", TRUE);
+	}
+
+	gtk_editable_set_text(GTK_EDITABLE(editor->alias), svalue);
+	gtk_switch_set_active(GTK_SWITCH(editor->use_custom_avatar), !use_global);
+
+	g_clear_object(&editor->avatar_pixbuf);
+	if(PURPLE_IS_IMAGE(image)) {
+		editor->avatar_pixbuf = purple_gdk_pixbuf_from_image(image);
+		gtk_image_set_from_pixbuf(GTK_IMAGE(editor->avatar),
+		                          editor->avatar_pixbuf);
+	} else {
+		gtk_image_set_from_icon_name(GTK_IMAGE(editor->avatar),
+		                             "select-avatar");
+	}
+}
+
+static gboolean
+pidgin_account_editor_advanced_option_use_default(PidginAccountEditor *editor) {
+	PurpleProtocol *protocol = NULL;
+
+	/* If this is the new dialog, use the default value. */
+	if(!PURPLE_IS_ACCOUNT(editor->account)) {
+		return TRUE;
+	}
+
+	/* If we have an existing account, check if the protocol has changed. */
+	protocol = pidgin_protocol_chooser_get_protocol(PIDGIN_PROTOCOL_CHOOSER(editor->protocol));
+	if(protocol != purple_account_get_protocol(editor->account)) {
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static GtkWidget *
+pidgin_account_editor_add_advanced_boolean(PidginAccountEditor *editor,
+                                           PurpleAccountOption *option)
+{
+	GtkWidget *row = NULL;
+	GtkWidget *toggle = NULL;
+	gboolean value = FALSE;
+	gchar *title = NULL;
+
+	if(pidgin_account_editor_advanced_option_use_default(editor)) {
+		value = purple_account_option_get_default_bool(option);
+	} else {
+		const gchar *setting = purple_account_option_get_setting(option);
+		gboolean def_value = purple_account_option_get_default_bool(option);
+
+		value = purple_account_get_bool(editor->account, setting, def_value);
+	}
+
+	/* Create the row and set it's title with a mnemonic. */
+	row = adw_action_row_new();
+	g_object_bind_property(editor->advanced_toggle, "active", row, "visible",
+	                       G_BINDING_SYNC_CREATE);
+	adw_preferences_row_set_use_underline(ADW_PREFERENCES_ROW(row), TRUE);
+	title = g_strdup_printf("_%s", purple_account_option_get_text(option));
+	adw_preferences_row_set_title(ADW_PREFERENCES_ROW(row), title);
+	g_free(title);
+
+	adw_preferences_group_add(ADW_PREFERENCES_GROUP(editor->advanced_group),
+	                          row);
+
+	/* Add the row to the editor's list of advanced rows. */
+	editor->advanced_rows = g_list_append(editor->advanced_rows, row);
+
+	/* Create the input widget. */
+	toggle = gtk_switch_new();
+	gtk_switch_set_active(GTK_SWITCH(toggle), value);
+	gtk_widget_set_valign(toggle, GTK_ALIGN_CENTER);
+	adw_action_row_add_suffix(ADW_ACTION_ROW(row), toggle);
+	adw_action_row_set_activatable_widget(ADW_ACTION_ROW(row), toggle);
+
+	return toggle;
+}
+
+static GtkWidget *
+pidgin_account_editor_add_advanced_int(PidginAccountEditor *editor,
+                                       PurpleAccountOption *option)
+{
+	GtkWidget *row = NULL;
+	GtkWidget *entry = NULL;
+	gint value = FALSE;
+	gchar *title = NULL;
+	gchar *svalue = NULL;
+
+	if(pidgin_account_editor_advanced_option_use_default(editor)) {
+		value = purple_account_option_get_default_int(option);
+	} else {
+		const gchar *setting = purple_account_option_get_setting(option);
+		gint def_value = purple_account_option_get_default_int(option);
+
+		value = purple_account_get_int(editor->account, setting, def_value);
+	}
+
+	/* Create the row and set it's title with a mnemonic. */
+	row = adw_action_row_new();
+	g_object_bind_property(editor->advanced_toggle, "active", row, "visible",
+	                       G_BINDING_SYNC_CREATE);
+	adw_preferences_row_set_use_underline(ADW_PREFERENCES_ROW(row), TRUE);
+	title = g_strdup_printf("_%s", purple_account_option_get_text(option));
+	adw_preferences_row_set_title(ADW_PREFERENCES_ROW(row), title);
+	g_free(title);
+
+	adw_preferences_group_add(ADW_PREFERENCES_GROUP(editor->advanced_group),
+	                          row);
+
+	/* Add the row to the editor's list of advanced rows. */
+	editor->advanced_rows = g_list_append(editor->advanced_rows, row);
+
+	/* Create the input widget. */
+	entry = gtk_entry_new();
+	svalue = g_strdup_printf("%d", value);
+	gtk_editable_set_text(GTK_EDITABLE(entry), svalue);
+	g_free(svalue);
+
+	gtk_widget_set_hexpand(entry, TRUE);
+	gtk_widget_set_valign(entry, GTK_ALIGN_CENTER);
+	adw_action_row_add_suffix(ADW_ACTION_ROW(row), entry);
+	adw_action_row_set_activatable_widget(ADW_ACTION_ROW(row), entry);
+
+	return entry;
+}
+
+static GtkWidget *
+pidgin_account_editor_add_advanced_string(PidginAccountEditor *editor,
+                                          PurpleAccountOption *option)
+{
+	GtkWidget *row = NULL;
+	GtkWidget *entry = NULL;
+	gchar *title = NULL;
+	const gchar *value = FALSE;
+
+	if(pidgin_account_editor_advanced_option_use_default(editor)) {
+		value = purple_account_option_get_default_string(option);
+	} else {
+		const gchar *setting = purple_account_option_get_setting(option);
+		const gchar *def_value = NULL;
+
+		def_value = purple_account_option_get_default_string(option);
+
+		value = purple_account_get_string(editor->account, setting, def_value);
+	}
+
+	/* Create the row and set its title with a mnemonic. */
+	row = adw_action_row_new();
+	g_object_bind_property(editor->advanced_toggle, "active", row, "visible",
+	                       G_BINDING_SYNC_CREATE);
+	adw_preferences_row_set_use_underline(ADW_PREFERENCES_ROW(row), TRUE);
+	title = g_strdup_printf("_%s", purple_account_option_get_text(option));
+	adw_preferences_row_set_title(ADW_PREFERENCES_ROW(row), title);
+	g_free(title);
+
+	adw_preferences_group_add(ADW_PREFERENCES_GROUP(editor->advanced_group),
+	                          row);
+
+	/* Add the row to the editor's list of advanced rows. */
+	editor->advanced_rows = g_list_append(editor->advanced_rows, row);
+
+	/* Create the input widget. */
+	if(purple_account_option_string_get_masked(option)) {
+		entry = gtk_password_entry_new();
+	} else {
+		entry = gtk_entry_new();
+	}
+
+	if(value != NULL) {
+		gtk_editable_set_text(GTK_EDITABLE(entry), value);
+	}
+	gtk_widget_set_hexpand(entry, TRUE);
+	gtk_widget_set_valign(entry, GTK_ALIGN_CENTER);
+	adw_action_row_add_suffix(ADW_ACTION_ROW(row), entry);
+	adw_action_row_set_activatable_widget(ADW_ACTION_ROW(row), entry);
+
+	return entry;
+}
+
+static GtkWidget *
+pidgin_account_editor_add_advanced_list(PidginAccountEditor *editor,
+                                        PurpleAccountOption *option)
+{
+	GtkWidget *row = NULL;
+	GtkStringList *model = NULL;
+	GList *data = NULL;
+	GList *items = NULL;
+	gchar *title = NULL;
+	const gchar *value = FALSE;
+	guint index = 0;
+	guint position = 0;
+
+	if(pidgin_account_editor_advanced_option_use_default(editor)) {
+		value = purple_account_option_get_default_list_value(option);
+	} else {
+		const gchar *setting = purple_account_option_get_setting(option);
+		const gchar *def_value = NULL;
+
+		def_value = purple_account_option_get_default_list_value(option);
+
+		value = purple_account_get_string(editor->account, setting, def_value);
+	}
+
+	/* Create the row and set its title with a mnemonic. */
+	row = adw_combo_row_new();
+	g_object_bind_property(editor->advanced_toggle, "active", row, "visible",
+	                       G_BINDING_SYNC_CREATE);
+	adw_preferences_row_set_use_underline(ADW_PREFERENCES_ROW(row), TRUE);
+	adw_combo_row_set_use_subtitle(ADW_COMBO_ROW(row), TRUE);
+	title = g_strdup_printf("_%s", purple_account_option_get_text(option));
+	adw_preferences_row_set_title(ADW_PREFERENCES_ROW(row), title);
+	g_free(title);
+
+	adw_preferences_group_add(ADW_PREFERENCES_GROUP(editor->advanced_group),
+	                          row);
+
+	/* Add the row to the editor's list of advanced rows. */
+	editor->advanced_rows = g_list_append(editor->advanced_rows, row);
+
+	/* Create the model and data for the expression. */
+	items = purple_account_option_get_list(option);
+	model = gtk_string_list_new(NULL);
+
+	for(GList *l = items; l != NULL; l = l->next) {
+		PurpleKeyValuePair *kvp = l->data;
+
+		if(kvp != NULL) {
+			if(purple_strequal(kvp->value, value)) {
+				position = index;
+			}
+
+			data = g_list_append(data, kvp->value);
+			gtk_string_list_append(model, kvp->key);
+		}
+
+		index++;
+	}
+
+	adw_combo_row_set_model(ADW_COMBO_ROW(row), G_LIST_MODEL(model));
+	adw_combo_row_set_selected(ADW_COMBO_ROW(row), position);
+	g_object_set_data_full(G_OBJECT(row), "keys", data,
+	                       (GDestroyNotify)g_list_free);
+
+	return row;
+}
+
+static void
+pidgin_account_editor_add_advanced_option(gpointer data, gpointer user_data) {
+	PidginAccountEditor *editor = user_data;
+	PurpleAccountOption *option = data;
+	PurplePrefType type;
+	GtkWidget *widget = NULL;
+
+	type = purple_account_option_get_pref_type(option);
+	switch(type) {
+		case PURPLE_PREF_BOOLEAN:
+			widget = pidgin_account_editor_add_advanced_boolean(editor, option);
+			break;
+		case PURPLE_PREF_INT:
+			widget = pidgin_account_editor_add_advanced_int(editor, option);
+			break;
+		case PURPLE_PREF_STRING:
+			widget = pidgin_account_editor_add_advanced_string(editor, option);
+			break;
+		case PURPLE_PREF_STRING_LIST:
+			widget = pidgin_account_editor_add_advanced_list(editor, option);
+			break;
+		default:
+			purple_debug_error("PidginAccountEditor",
+			                   "Invalid Account Option pref type (%d)\n", type);
+			break;
+	}
+
+	if(GTK_IS_WIDGET(widget)) {
+		const gchar *setting = purple_account_option_get_setting(option);
+
+		g_object_set_data(G_OBJECT(widget), "type", GINT_TO_POINTER(type));
+		g_object_set_data(G_OBJECT(widget), "setting", (gpointer)setting);
+
+		editor->advanced_entries = g_list_append(editor->advanced_entries,
+		                                         widget);
+	}
+}
+
+static void
+pidgin_account_editor_update_advanced_options(PidginAccountEditor *editor,
+                                              PurpleProtocol *protocol)
+{
+	GList *options = NULL;
+
+	g_clear_pointer(&editor->advanced_entries, g_list_free);
+	while(editor->advanced_rows != NULL) {
+		adw_preferences_group_remove(ADW_PREFERENCES_GROUP(editor->advanced_group),
+		                             GTK_WIDGET(editor->advanced_rows->data));
+
+		editor->advanced_rows = g_list_delete_link(editor->advanced_rows,
+		                                           editor->advanced_rows);
+	}
+
+	if(!PURPLE_IS_PROTOCOL(protocol)) {
+		gtk_widget_set_visible(editor->advanced_group, FALSE);
+
+		return;
+	}
+
+	options = purple_protocol_get_account_options(protocol);
+	if(options == NULL) {
+		gtk_widget_set_visible(editor->advanced_group, FALSE);
+
+		return;
+	}
+
+	g_list_foreach(options, pidgin_account_editor_add_advanced_option, editor);
+
+	gtk_widget_set_visible(editor->advanced_group, TRUE);
+}
+
+static void
+pidgin_account_editor_update_proxy_options(PidginAccountEditor *editor) {
+	PurpleProxyInfo *info = NULL;
+	GListModel *model = NULL;
+	const gchar *svalue = NULL;
+	gint ivalue = 0;
+	guint position = 0;
+
+	if(!PURPLE_IS_ACCOUNT(editor->account)) {
+		return;
+	}
+
+	info = purple_account_get_proxy_info(editor->account);
+
+	switch(purple_proxy_info_get_proxy_type(info)) {
+		case PURPLE_PROXY_TYPE_USE_GLOBAL:
+			svalue = "global";
+			break;
+		case PURPLE_PROXY_TYPE_NONE:
+			svalue = "none";
+			break;
+		case PURPLE_PROXY_TYPE_SOCKS4:
+			svalue = "socks4";
+			break;
+		case PURPLE_PROXY_TYPE_SOCKS5:
+			svalue = "socks5";
+			break;
+		case PURPLE_PROXY_TYPE_TOR:
+			svalue = "tor";
+			break;
+		case PURPLE_PROXY_TYPE_HTTP:
+			svalue = "http";
+			break;
+		case PURPLE_PROXY_TYPE_USE_ENVVAR:
+			svalue = "envvar";
+			break;
+	}
+
+	model = adw_combo_row_get_model(ADW_COMBO_ROW(editor->proxy_type));
+	for(guint i = 0; i < g_list_model_get_n_items(model); i++) {
+		GtkStringObject *obj = g_list_model_get_item(model, i);
+		if(purple_strequal(svalue, gtk_string_object_get_string(obj))) {
+			position = i;
+			break;
+		}
+	}
+	adw_combo_row_set_selected(ADW_COMBO_ROW(editor->proxy_type), position);
+
+	svalue = purple_proxy_info_get_hostname(info);
+	if(svalue == NULL) {
+		svalue = "";
+	}
+	gtk_editable_set_text(GTK_EDITABLE(editor->proxy_host), svalue);
+
+	ivalue = purple_proxy_info_get_port(info);
+	gtk_spin_button_set_value(GTK_SPIN_BUTTON(editor->proxy_port),
+	                          (gdouble)ivalue);
+
+	svalue = purple_proxy_info_get_username(info);
+	if(svalue == NULL) {
+		svalue = "";
+	}
+	gtk_editable_set_text(GTK_EDITABLE(editor->proxy_username), svalue);
+
+	svalue = purple_proxy_info_get_password(info);
+	if(svalue == NULL) {
+		svalue = "";
+	}
+	gtk_editable_set_text(GTK_EDITABLE(editor->proxy_password), svalue);
+}
+
+static void
+pidgin_account_editor_update(PidginAccountEditor *editor) {
+	PurpleProtocol *protocol = NULL;
+	gboolean sensitive = FALSE;
+
+	if(PURPLE_IS_ACCOUNT(editor->account)) {
+		PurpleConnection *connection = NULL;
+
+		connection = purple_account_get_connection(editor->account);
+		if(PURPLE_IS_CONNECTION(connection)) {
+			gtk_widget_set_sensitive(editor->protocol, FALSE);
+		}
+	}
+
+	protocol = pidgin_protocol_chooser_get_protocol(PIDGIN_PROTOCOL_CHOOSER(editor->protocol));
+
+	sensitive = pidgin_account_editor_update_login_options(editor, protocol);
+	pidgin_account_editor_update_user_options(editor, protocol);
+	pidgin_account_editor_update_advanced_options(editor, protocol);
+	pidgin_account_editor_update_proxy_options(editor);
+
+	gtk_dialog_set_response_sensitive(GTK_DIALOG(editor), GTK_RESPONSE_APPLY,
+	                                  sensitive);
+}
+
+static void
 pidgin_account_editor_set_account(PidginAccountEditor *editor,
                                   PurpleAccount *account)
 {
 	if(g_set_object(&editor->account, account)) {
-		PurpleProxyInfo *proxy_info = NULL;
+		g_object_notify_by_pspec(G_OBJECT(editor), properties[PROP_ACCOUNT]);
+	}
+
+	pidgin_account_editor_update(editor);
+}
+
+static gboolean
+pidgin_account_editor_save_login_options(PidginAccountEditor *editor) {
+	PurpleProtocol *protocol = NULL;
+	GList *split_item = NULL, *entry_item = NULL;
+	GString *username = NULL;
+	const gchar *protocol_id = NULL;
+	gboolean new_account = FALSE;
+
+	protocol = pidgin_protocol_chooser_get_protocol(PIDGIN_PROTOCOL_CHOOSER(editor->protocol));
+	protocol_id = purple_protocol_get_id(protocol);
+
+	username = g_string_new(gtk_editable_get_text(GTK_EDITABLE(editor->username)));
 
-		if(PURPLE_IS_ACCOUNT(account)) {
-			proxy_info = purple_account_get_proxy_info(account);
+	split_item = purple_protocol_get_user_splits(protocol);
+	entry_item = editor->user_split_entries;
+	while(split_item != NULL && entry_item != NULL) {
+		PurpleAccountUserSplit *split = split_item->data;
+		GtkEntry *entry = entry_item->data;
+		const gchar *value = "";
+		gchar sep = '\0';
+
+		sep = purple_account_user_split_get_separator(split);
+		g_string_append_c(username, sep);
+
+
+		if(GTK_IS_ENTRY(entry)) {
+			value = gtk_editable_get_text(GTK_EDITABLE(entry));
+		}
+
+		if(value == NULL || *value == '\0') {
+			value = purple_account_user_split_get_default_value(split);
 		}
 
-		pidgin_proxy_options_set_info(PIDGIN_PROXY_OPTIONS(editor->proxy_options),
-		                              proxy_info);
+		g_string_append(username, value);
+
+		split_item = split_item->next;
+		entry_item = entry_item->next;
+	}
+
+	if(!PURPLE_IS_ACCOUNT(editor->account)) {
+		editor->account = purple_account_new(username->str, protocol_id);
+		new_account = TRUE;
+	} else {
+		purple_account_set_username(editor->account, username->str);
+		purple_account_set_protocol_id(editor->account, protocol_id);
+	}
+
+	g_string_free(username, TRUE);
+
+	return new_account;
+}
 
-		g_object_notify_by_pspec(G_OBJECT(editor), properties[PROP_ACCOUNT]);
+static void
+pidgin_account_editor_save_user_options(PidginAccountEditor *editor) {
+	const gchar *svalue = NULL;
+	gboolean bvalue = FALSE;
+
+	/* Set the alias. */
+	svalue = gtk_editable_get_text(GTK_EDITABLE(editor->alias));
+	if(*svalue == '\0') {
+		svalue = NULL;
+	}
+	purple_account_set_private_alias(editor->account, svalue);
+
+	/* Set whether or not to use the global avatar. */
+	bvalue = gtk_switch_get_active(GTK_SWITCH(editor->use_custom_avatar));
+	purple_account_set_bool(editor->account, "use-global-buddyicon", !bvalue);
+
+	if(bvalue) {
+		if(GDK_IS_PIXBUF(editor->avatar_pixbuf)) {
+			# warning implement this when buddy icons do not suck so bad.
+		} else {
+			purple_buddy_icons_set_account_icon(editor->account, NULL, 0);
+		}
+	} else {
+		# warning set the global buddy icon when buddy icons do not suck so bad.
 	}
 }
 
 static void
+pidgin_account_editor_save_advanced_options(PidginAccountEditor *editor) {
+	for(GList *l = editor->advanced_entries; l != NULL; l = l->next) {
+		GtkWidget *widget = l->data;
+		PurplePrefType type;
+		GList *keys = NULL;
+		const gchar *setting = NULL;
+		const gchar *svalue = NULL;
+		gboolean bvalue = FALSE;
+		gint ivalue = 0;
+		guint selected = 0;
+
+		type = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "type"));
+		setting = g_object_get_data(G_OBJECT(widget), "setting");
+
+		switch(type) {
+			case PURPLE_PREF_STRING:
+				svalue = gtk_editable_get_text(GTK_EDITABLE(widget));
+				purple_account_set_string(editor->account, setting, svalue);
+				break;
+			case PURPLE_PREF_INT:
+				ivalue = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
+				purple_account_set_int(editor->account, setting, ivalue);
+				break;
+			case PURPLE_PREF_BOOLEAN:
+				bvalue = gtk_switch_get_active(GTK_SWITCH(widget));
+				purple_account_set_bool(editor->account, setting, bvalue);
+				break;
+			case PURPLE_PREF_STRING_LIST:
+				keys = g_object_get_data(G_OBJECT(widget), "keys");
+				selected = adw_combo_row_get_selected(ADW_COMBO_ROW(widget));
+				svalue = g_list_nth_data(keys, selected);
+				purple_account_set_string(editor->account, setting, svalue);
+				break;
+			default:
+				break;
+		}
+	}
+}
+
+static void
+pidgin_account_editor_save_proxy(PidginAccountEditor *editor,
+                                 gboolean new_account)
+{
+	PurpleProxyInfo *info = NULL;
+	PurpleProxyType type = PURPLE_PROXY_TYPE_NONE;
+	GObject *item = NULL;
+	const gchar *svalue = NULL;
+	gint ivalue = 0;
+
+	/* Build the ProxyInfo object */
+	if(new_account) {
+		info = purple_proxy_info_new();
+		purple_account_set_proxy_info(editor->account, info);
+	} else {
+		info = purple_account_get_proxy_info(editor->account);
+	}
+
+	item = adw_combo_row_get_selected_item(ADW_COMBO_ROW(editor->proxy_type));
+	svalue = gtk_string_object_get_string(GTK_STRING_OBJECT(item));
+	if(purple_strequal(svalue, "global")) {
+		type = PURPLE_PROXY_TYPE_USE_GLOBAL;
+	} else if(purple_strequal(svalue, "none")) {
+		type = PURPLE_PROXY_TYPE_NONE;
+	} else if(purple_strequal(svalue, "socks4")) {
+		type = PURPLE_PROXY_TYPE_SOCKS4;
+	} else if(purple_strequal(svalue, "socks5")) {
+		type = PURPLE_PROXY_TYPE_SOCKS5;
+	} else if(purple_strequal(svalue, "tor")) {
+		type = PURPLE_PROXY_TYPE_TOR;
+	} else if(purple_strequal(svalue, "http")) {
+		type = PURPLE_PROXY_TYPE_HTTP;
+	} else if(purple_strequal(svalue, "envvar")) {
+		type = PURPLE_PROXY_TYPE_USE_ENVVAR;
+	}
+	purple_proxy_info_set_proxy_type(info, type);
+
+	svalue = gtk_editable_get_text(GTK_EDITABLE(editor->proxy_host));
+	purple_proxy_info_set_hostname(info, svalue);
+
+	ivalue = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editor->proxy_port));
+	purple_proxy_info_set_port(info, ivalue);
+
+	svalue = gtk_editable_get_text(GTK_EDITABLE(editor->proxy_username));
+	purple_proxy_info_set_username(info, svalue);
+
+	svalue = gtk_editable_get_text(GTK_EDITABLE(editor->proxy_password));
+	purple_proxy_info_set_password(info, svalue);
+}
+
+static void
 pidgin_account_editor_save_account(PidginAccountEditor *editor) {
-	PurpleAccountManager *manager = NULL;
-	PurpleProxyInfo *info = NULL;
 	gboolean new_account = FALSE;
 
-	manager = purple_account_manager_get_default();
-
-	if(!PURPLE_IS_ACCOUNT(editor->account)) {
-		editor->account = purple_account_new("undefined", "undefined");
-		new_account = TRUE;
-	}
-
-	info = pidgin_proxy_options_get_info(PIDGIN_PROXY_OPTIONS(editor->proxy_options));
-	purple_account_set_proxy_info(editor->account, info);
+	new_account = pidgin_account_editor_save_login_options(editor);
+	pidgin_account_editor_save_user_options(editor);
+	pidgin_account_editor_save_advanced_options(editor);
+	pidgin_account_editor_save_proxy(editor, new_account);
 
 	/* If this is a new account, add it to the account manager and bring it
 	 * online.
 	 */
 	if(new_account) {
+		PurpleAccountManager *manager = NULL;
 		const PurpleSavedStatus *saved_status;
 
+		manager = purple_account_manager_get_default();
+
 		purple_account_manager_add(manager, editor->account);
 
 		saved_status = purple_savedstatus_get_current();
@@ -110,6 +862,139 @@
 	gtk_window_destroy(GTK_WINDOW(dialog));
 }
 
+static void
+pidgin_account_editor_protocol_changed_cb(G_GNUC_UNUSED GObject *obj,
+                                          G_GNUC_UNUSED GParamSpec *pspec,
+                                          gpointer data)
+{
+	pidgin_account_editor_update(data);
+}
+
+static void
+pidgin_account_editor_username_changed_cb(GtkEditable *self, gpointer data) {
+	PidginAccountEditor *editor = data;
+	const gchar *text = gtk_editable_get_text(self);
+	gboolean sensitive = FALSE;
+
+	if(text != NULL && *text != '\0') {
+		sensitive = TRUE;
+	}
+
+	gtk_dialog_set_response_sensitive(GTK_DIALOG(editor), GTK_RESPONSE_APPLY,
+	                                  sensitive);
+}
+
+static void
+pidgin_account_editor_avatar_response_cb(GtkNativeDialog *self,
+                                         gint response_id, gpointer data)
+{
+	PidginAccountEditor *editor = data;
+
+	if(response_id == GTK_RESPONSE_ACCEPT) {
+		GError *error = NULL;
+		GFile *file = NULL;
+		gchar *filename = NULL;
+
+		file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(self));
+		filename = g_file_get_path(file);
+
+		g_clear_object(&editor->avatar_pixbuf);
+		editor->avatar_pixbuf = gdk_pixbuf_new_from_file(filename, &error);
+		if(error != NULL) {
+			g_warning("Failed to create pixbuf from file %s: %s", filename,
+			          error->message);
+			g_clear_error(&error);
+		} else {
+			gtk_image_set_from_pixbuf(GTK_IMAGE(editor->avatar),
+			                          editor->avatar_pixbuf);
+		}
+
+		g_free(filename);
+		g_object_unref(file);
+	}
+
+	g_clear_object(&editor->avatar_dialog);
+}
+
+static void
+pidgin_account_editor_avatar_set_clicked_cb(G_GNUC_UNUSED GtkButton *self,
+                                            gpointer data)
+{
+	PidginAccountEditor *editor = data;
+
+	editor->avatar_dialog = gtk_file_chooser_native_new(_("Buddy Icon"),
+	                                                    GTK_WINDOW(editor),
+	                                                    GTK_FILE_CHOOSER_ACTION_OPEN,
+	                                                    _("_Open"),
+	                                                    _("_Cancel"));
+	gtk_native_dialog_set_transient_for(GTK_NATIVE_DIALOG(editor->avatar_dialog),
+	                                    GTK_WINDOW(editor));
+
+	g_signal_connect(G_OBJECT(editor->avatar_dialog), "response",
+					 G_CALLBACK(pidgin_account_editor_avatar_response_cb),
+					 editor);
+
+	gtk_native_dialog_show(GTK_NATIVE_DIALOG(editor->avatar_dialog));
+}
+
+static void
+pidgin_account_editor_avatar_remove_clicked_cb(G_GNUC_UNUSED GtkButton *self,
+                                               gpointer data)
+{
+	PidginAccountEditor *editor = data;
+
+	gtk_image_set_from_icon_name(GTK_IMAGE(editor->avatar), "select-avatar");
+}
+
+static gchar *
+pidgin_account_editor_proxy_type_expression_cb(GObject *self,
+                                               G_GNUC_UNUSED gpointer data)
+{
+	const gchar *text = "";
+	const gchar *value = NULL;
+
+	value = gtk_string_object_get_string(GTK_STRING_OBJECT(self));
+	if(purple_strequal(value, "global")) {
+		text = _("Use Global Proxy Settings");
+	} else if(purple_strequal(value, "none")) {
+		text = _("No proxy");
+	} else if(purple_strequal(value, "socks4")) {
+		text = _("SOCKS 4");
+	} else if(purple_strequal(value, "socks5")) {
+		text = _("SOCKS 5");
+	} else if(purple_strequal(value, "tor")) {
+		text = _("Tor/Privacy (SOCKS 5)");
+	} else if(purple_strequal(value, "http")) {
+		text = _("HTTP");
+	} else if(purple_strequal(value, "envvar")) {
+		text = _("Use Environmental Settings");
+	}
+
+	return g_strdup(text);
+}
+
+static void
+pidgin_account_editor_proxy_type_changed_cb(G_GNUC_UNUSED GObject *obj,
+                                            G_GNUC_UNUSED GParamSpec *pspec,
+                                            gpointer data)
+{
+	PidginAccountEditor *editor = data;
+	GObject *selected = NULL;
+	gboolean show_options = TRUE;
+	const gchar *value = NULL;
+
+	selected = adw_combo_row_get_selected_item(ADW_COMBO_ROW(editor->proxy_type));
+	value = gtk_string_object_get_string(GTK_STRING_OBJECT(selected));
+
+	if(purple_strequal(value, "global") || purple_strequal(value, "none") ||
+	   purple_strequal(value, "envvar"))
+	{
+		show_options = FALSE;
+	}
+
+	gtk_widget_set_visible(editor->proxy_options, show_options);
+}
+
 /******************************************************************************
  * GObject Implementation
  *****************************************************************************/
@@ -154,15 +1039,44 @@
 	PidginAccountEditor *editor = PIDGIN_ACCOUNT_EDITOR(obj);
 
 	g_clear_object(&editor->account);
+	g_clear_object(&editor->css_provider);
+	g_clear_object(&editor->avatar_dialog);
+	g_clear_object(&editor->avatar_pixbuf);
 
 	G_OBJECT_CLASS(pidgin_account_editor_parent_class)->dispose(obj);
 }
 
 static void
-pidgin_account_editor_init(PidginAccountEditor *account_editor) {
-	GtkWidget *widget = GTK_WIDGET(account_editor);
+pidgin_account_editor_init(PidginAccountEditor *editor) {
+	GtkStyleContext *context = NULL;
+	GtkWidget *widget = GTK_WIDGET(editor);
 
 	gtk_widget_init_template(widget);
+
+	editor->css_provider = gtk_css_provider_new();
+	gtk_css_provider_load_from_resource(editor->css_provider,
+	                                    "/im/pidgin/Pidgin3/Accounts/entry.css");
+
+	context = gtk_widget_get_style_context(editor->username);
+	gtk_style_context_add_provider(context,
+	                               GTK_STYLE_PROVIDER(editor->css_provider),
+	                               GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+	pidgin_account_editor_proxy_type_changed_cb(NULL, NULL, editor);
+}
+
+static void
+pidgin_account_editor_constructed(GObject *obj) {
+	PidginAccountEditor *editor = PIDGIN_ACCOUNT_EDITOR(obj);
+
+	G_OBJECT_CLASS(pidgin_account_editor_parent_class)->constructed(obj);
+
+	if(PURPLE_IS_ACCOUNT(editor->account)) {
+		pidgin_protocol_chooser_set_protocol(PIDGIN_PROTOCOL_CHOOSER(editor->protocol),
+		                                     purple_account_get_protocol(editor->account));
+	}
+
+	pidgin_account_editor_update(editor);
 }
 
 static void
@@ -172,6 +1086,7 @@
 
 	obj_class->get_property = pidgin_account_editor_get_property;
 	obj_class->set_property = pidgin_account_editor_set_property;
+	obj_class->constructed = pidgin_account_editor_constructed;
 	obj_class->dispose = pidgin_account_editor_dispose;
 
 	/**
@@ -192,13 +1107,62 @@
 	gtk_widget_class_set_template_from_resource(widget_class,
 	                                            "/im/pidgin/Pidgin3/Accounts/editor.ui");
 
+	/* Dialog */
+	gtk_widget_class_bind_template_callback(widget_class,
+	                                        pidgin_account_editor_response_cb);
+
+	/* Login Options */
 	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
-	                                     notebook);
+	                                     login_options);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     protocol);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     username);
+
+	gtk_widget_class_bind_template_callback(widget_class,
+	                                        pidgin_account_editor_protocol_changed_cb);
+	gtk_widget_class_bind_template_callback(widget_class,
+	                                        pidgin_account_editor_username_changed_cb);
+
+	/* User Options */
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     alias);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     avatar_row);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     use_custom_avatar);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     avatar);
+
+	gtk_widget_class_bind_template_callback(widget_class,
+	                                        pidgin_account_editor_avatar_set_clicked_cb);
+	gtk_widget_class_bind_template_callback(widget_class,
+	                                        pidgin_account_editor_avatar_remove_clicked_cb);
+
+	/* Advanced Options */
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     advanced_group);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     advanced_toggle);
+
+	/* Proxy Options */
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     proxy_type);
 	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
 	                                     proxy_options);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     proxy_host);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     proxy_port);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     proxy_username);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountEditor,
+	                                     proxy_password);
 
 	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_account_editor_response_cb);
+	                                        pidgin_account_editor_proxy_type_expression_cb);
+	gtk_widget_class_bind_template_callback(widget_class,
+	                                        pidgin_account_editor_proxy_type_changed_cb);
 }
 
 /******************************************************************************
diff --git a/pidgin/resources/Accounts/editor.ui b/pidgin/resources/Accounts/editor.ui
--- a/pidgin/resources/Accounts/editor.ui
+++ b/pidgin/resources/Accounts/editor.ui
@@ -19,42 +19,237 @@
 
 -->
 <interface>
+  <requires lib="Adw" version="1.0"/>
   <requires lib="gtk" version="4.0"/>
   <requires lib="pidgin" version="3.0"/>
   <!-- interface-license-type gplv2 -->
   <!-- interface-name Pidgin -->
   <!-- interface-description Internet Messenger -->
   <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
+  <object class="GtkAdjustment" id="proxy_port_adjustment">
+    <property name="upper">65535</property>
+    <property name="step-increment">1</property>
+    <property name="page-increment">10</property>
+  </object>
   <template class="PidginAccountEditor" parent="GtkDialog">
+    <property name="resizable">0</property>
+    <property name="default-height">600</property>
+    <property name="default-width">400</property>
+    <property name="title" translatable="1">Edit Account</property>
     <signal name="response" handler="pidgin_account_editor_response_cb" swapped="no"/>
     <child internal-child="content_area">
       <object class="GtkBox">
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
+        <property name="vexpand">1</property>
         <child>
-          <object class="GtkNotebook" id="notebook">
-            <property name="focusable">1</property>
-            <child>
-              <object class="GtkNotebookPage">
-                <property name="position">0</property>
-                <property name="child">
-                  <object class="PidginProxyOptions" id="proxy_options">
-                    <property name="margin-start">12</property>
-                    <property name="margin-end">12</property>
-                    <property name="margin-top">12</property>
-                    <property name="margin-bottom">12</property>
-                    <property name="orientation">vertical</property>
-                    <property name="spacing">6</property>
+          <object class="GtkScrolledWindow">
+            <property name="vexpand">1</property>
+            <property name="hexpand">1</property>
+            <property name="child">
+              <object class="AdwPreferencesPage">
+                <property name="vexpand">1</property>
+                <property name="hexpand">1</property>
+                <child>
+                  <object class="AdwPreferencesGroup" id="login_options">
+                    <property name="title" translatable="1">Login Options</property>
+                    <child>
+                      <object class="AdwActionRow">
+                        <property name="activatable-widget">protocol</property>
+                        <property name="title" translatable="1">Pro_tocol</property>
+                        <property name="use-underline">1</property>
+                        <child>
+                          <object class="PidginProtocolChooser" id="protocol">
+                            <property name="hexpand">1</property>
+                            <property name="valign">center</property>
+                            <signal name="notify::protocol" handler="pidgin_account_editor_protocol_changed_cb" object="PidginAccountEditor" swapped="no"/>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="AdwActionRow">
+                        <property name="activatable-widget">username</property>
+                        <property name="title" translatable="1">_Username</property>
+                        <property name="use-underline">1</property>
+                        <child>
+                          <object class="GtkEntry" id="username">
+                            <property name="hexpand">1</property>
+                            <property name="valign">center</property>
+                            <property name="truncate-multiline">1</property>
+                            <signal name="changed" handler="pidgin_account_editor_username_changed_cb" object="PidginAccountEditor" swapped="no"/>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="AdwPreferencesGroup">
+                    <property name="title" translatable="1">User Options</property>
+                    <child>
+                      <object class="AdwActionRow">
+                        <property name="activatable-widget">alias</property>
+                        <property name="title" translatable="1">_Local alias</property>
+                        <property name="use-underline">1</property>
+                        <child>
+                          <object class="GtkEntry" id="alias">
+                            <property name="truncate-multiline">1</property>
+                            <property name="hexpand">1</property>
+                            <property name="valign">center</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="AdwActionRow" id="avatar_row">
+                        <property name="activatable-widget">avatar</property>
+                        <property name="title" translatable="1">Use custom _avatar</property>
+                        <property name="use-underline">1</property>
+                        <property name="visible">0</property>
+                        <child type="prefix">
+                          <object class="GtkSwitch" id="use_custom_avatar">
+                            <property name="valign">center</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkButton">
+                            <property name="css-classes">flat</property>
+                            <property name="valign">center</property>
+                            <binding name="sensitive">
+                              <lookup name="active">use_custom_avatar</lookup>
+                            </binding>
+                            <child>
+                              <object class="GtkImage" id="avatar">
+                                <property name="icon-name">select-avatar</property>
+                                <property name="icon-size">large</property>
+                              </object>
+                            </child>
+                            <signal name="clicked" handler="pidgin_account_editor_avatar_set_clicked_cb" object="PidginAccountEditor" swapped="no"/>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="remove">
+                            <property name="label" translatable="1">_Remove</property>
+                            <property name="use-underline">1</property>
+                            <property name="valign">center</property>
+                            <binding name="sensitive">
+                              <lookup name="active">use_custom_avatar</lookup>
+                            </binding>
+                            <signal name="clicked" handler="pidgin_account_editor_avatar_remove_clicked_cb" object="PidginAccountEditor" swapped="no"/>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
                   </object>
-                </property>
-                <property name="tab">
-                  <object class="GtkLabel">
-                    <property name="label" translatable="1">_Proxy</property>
-                    <property name="use-underline">1</property>
+                </child>
+                <child>
+                  <object class="AdwPreferencesGroup" id="advanced_group">
+                    <property name="title" translatable="1">Advanced Options</property>
+                    <property name="description" translatable="1">Additional options for this account.</property>
+                    <property name="visible">0</property>
+                    <child type="header-suffix">
+                      <object class="GtkSwitch" id="advanced_toggle">
+                        <property name="active">0</property>
+                        <property name="valign">center</property>
+                      </object>
+                    </child>
                   </object>
-                </property>
+                </child>
+                <child>
+                  <object class="AdwPreferencesGroup">
+                    <property name="title" translatable="1">Proxy</property>
+                    <child>
+                      <object class="AdwComboRow" id="proxy_type">
+                        <property name="title" translatable="1">Proxy t_ype</property>
+                        <property name="use-underline">1</property>
+                        <property name="use-subtitle">1</property>
+                        <property name="model">
+                          <object class="GtkStringList">
+                            <items>
+                              <item>global</item>
+                              <item>none</item>
+                              <item>socks4</item>
+                              <item>socks5</item>
+                              <item>tor</item>
+                              <item>http</item>
+                              <item>envvar</item>
+                            </items>
+                          </object>
+                        </property>
+                        <property name="expression">
+                          <closure type="gchararray" function="pidgin_account_editor_proxy_type_expression_cb"/>
+                        </property>
+                        <signal name="notify::selected" handler="pidgin_account_editor_proxy_type_changed_cb" object="PidginAccountEditor" swapped="no"/>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="AdwPreferencesRow" id="proxy_options">
+                        <property name="visible">0</property>
+                        <child>
+                          <object class="GtkListBox">
+                            <child>
+                              <object class="AdwActionRow">
+                                <property name="activatable-widget">proxy_host</property>
+                                <property name="title" translatable="1">_Host</property>
+                                <property name="use-underline">1</property>
+                                <child>
+                                  <object class="GtkEntry" id="proxy_host">
+                                    <property name="hexpand">1</property>
+                                    <property name="valign">center</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="AdwActionRow">
+                                <property name="activatable-widget">proxy_port</property>
+                                <property name="title" translatable="1">P_ort</property>
+                                <property name="use-underline">1</property>
+                                <child>
+                                  <object class="GtkSpinButton" id="proxy_port">
+                                    <property name="text" translatable="1">0</property>
+                                    <property name="adjustment">proxy_port_adjustment</property>
+                                    <property name="numeric">1</property>
+                                    <property name="hexpand">1</property>
+                                    <property name="valign">center</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="AdwActionRow">
+                                <property name="activatable-widget">proxy_username</property>
+                                <property name="title" translatable="1">User_name</property>
+                                <property name="use-underline">1</property>
+                                <child>
+                                  <object class="GtkEntry" id="proxy_username">
+                                    <property name="hexpand">1</property>
+                                    <property name="valign">center</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="AdwActionRow">
+                                <property name="activatable-widget">proxy_password</property>
+                                <property name="title" translatable="1">Pa_ssword</property>
+                                <property name="use-underline">1</property>
+                                <child>
+                                  <object class="GtkPasswordEntry" id="proxy_password">
+                                    <property name="hexpand">1</property>
+                                    <property name="show-peek-icon">1</property>
+                                    <property name="valign">center</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
               </object>
-            </child>
+            </property>
           </object>
         </child>
       </object>
@@ -62,7 +257,6 @@
     <child type="action">
       <object class="GtkButton" id="button1">
         <property name="label" translatable="1">_Cancel</property>
-        <property name="focusable">1</property>
         <property name="receives-default">1</property>
         <property name="use-underline">1</property>
       </object>
@@ -70,8 +264,8 @@
     <child type="action">
       <object class="GtkButton" id="button2">
         <property name="label" translatable="1">_Save</property>
-        <property name="focusable">1</property>
         <property name="receives-default">1</property>
+        <property name="sensitive">0</property>
         <property name="use-underline">1</property>
       </object>
     </child>
