summaryrefslogtreecommitdiff
path: root/pidgin
diff options
context:
space:
mode:
authorGary Kramlich <grim@reaperworld.com>2023-03-16 22:36:19 -0500
committerGary Kramlich <grim@reaperworld.com>2023-03-16 22:36:19 -0500
commit05d170ef2463c58fa4e9d4bc8e66fb3913cc32c4 (patch)
tree359b019dc0b6be9bbff33b7f5d43063cc1882320 /pidgin
parent98ad76990a8f242c49c66995395a9814fc67445e (diff)
downloadpidgin-05d170ef2463c58fa4e9d4bc8e66fb3913cc32c4.tar.gz
Embed PidginAccountEditor into PidginAccountManager
The account manager now uses a stack to switch between a single editor instance and the list of accounts. The save button from the editor got moved next to the new back button, but we should probably prompt or throw up an info box when the user starts making changes or prompt before moving back. Also, the app.edit-account action now will lose any changes to an account that is currently being edited, which we should disallow from happening in the future as well. Testing Done: Opened the account manager and selected accounts and moved backed and saved accounts and made sure everything there worked. Opened the account editor from a connection error notification and verified that opened properly as well. Reviewed at https://reviews.imfreedom.org/r/2333/
Diffstat (limited to 'pidgin')
-rw-r--r--pidgin/pidginaccounteditor.c159
-rw-r--r--pidgin/pidginaccounteditor.h40
-rw-r--r--pidgin/pidginaccountmanager.c105
-rw-r--r--pidgin/pidginaccountmanager.h22
-rw-r--r--pidgin/pidginapplication.c42
-rw-r--r--pidgin/resources/Accounts/editor.ui328
-rw-r--r--pidgin/resources/Accounts/manager.ui155
7 files changed, 545 insertions, 306 deletions
diff --git a/pidgin/pidginaccounteditor.c b/pidgin/pidginaccounteditor.c
index 8824e10ff1..aaa87ee58b 100644
--- a/pidgin/pidginaccounteditor.c
+++ b/pidgin/pidginaccounteditor.c
@@ -29,10 +29,12 @@
#include "pidginprotocolchooser.h"
struct _PidginAccountEditor {
- GtkDialog parent;
+ AdwPreferencesPage parent;
PurpleAccount *account;
+ gboolean valid;
+
/* Login Options */
GtkWidget *login_options;
GtkWidget *protocol;
@@ -71,6 +73,7 @@ struct _PidginAccountEditor {
enum {
PROP_0,
PROP_ACCOUNT,
+ PROP_VALID,
N_PROPERTIES,
};
static GParamSpec *properties[N_PROPERTIES] = {NULL, };
@@ -86,6 +89,17 @@ static void pidgin_account_editor_connection_changed_cb(GObject *obj,
* Helpers
*****************************************************************************/
static void
+pidgin_account_editor_set_valid(PidginAccountEditor *editor, gboolean valid) {
+ g_return_if_fail(PIDGIN_IS_ACCOUNT_EDITOR(editor));
+
+ if(editor->valid != valid) {
+ editor->valid = valid;
+
+ g_object_notify_by_pspec(G_OBJECT(editor), properties[PROP_VALID]);
+ }
+}
+
+static void
pidgin_account_editor_add_user_split(gpointer data, gpointer user_data) {
PurpleAccountUserSplit *split = data;
PidginAccountEditor *editor = user_data;
@@ -652,8 +666,7 @@ pidgin_account_editor_update(PidginAccountEditor *editor) {
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);
+ pidgin_account_editor_set_valid(editor, sensitive);
}
static void
@@ -706,23 +719,6 @@ pidgin_account_editor_login_options_update_editable(PidginAccountEditor *editor)
gtk_widget_set_sensitive(editor->require_password, editable);
}
-static void
-pidgin_account_editor_set_account(PidginAccountEditor *editor,
- PurpleAccount *account)
-{
- if(g_set_object(&editor->account, account)) {
- if(PURPLE_IS_ACCOUNT(account)) {
- g_signal_connect_object(account, "notify::connection",
- G_CALLBACK(pidgin_account_editor_connection_changed_cb),
- editor, 0);
- }
-
- 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;
@@ -912,35 +908,6 @@ pidgin_account_editor_save_proxy(PidginAccountEditor *editor,
purple_proxy_info_set_password(info, svalue);
}
-static void
-pidgin_account_editor_save_account(PidginAccountEditor *editor) {
- gboolean new_account = FALSE;
-
- 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();
- if (saved_status != NULL) {
- purple_savedstatus_activate_for_account(saved_status,
- editor->account);
- purple_account_set_enabled(editor->account, TRUE);
- }
- }
-}
-
/******************************************************************************
* Callbacks
*****************************************************************************/
@@ -959,7 +926,7 @@ pidgin_account_editor_response_cb(GtkDialog *dialog, gint response_id,
G_GNUC_UNUSED gpointer data)
{
if(response_id == GTK_RESPONSE_APPLY) {
- pidgin_account_editor_save_account(PIDGIN_ACCOUNT_EDITOR(dialog));
+ pidgin_account_editor_save(PIDGIN_ACCOUNT_EDITOR(dialog));
}
gtk_window_destroy(GTK_WINDOW(dialog));
@@ -983,8 +950,7 @@ pidgin_account_editor_username_changed_cb(GtkEditable *self, gpointer data) {
sensitive = TRUE;
}
- gtk_dialog_set_response_sensitive(GTK_DIALOG(editor), GTK_RESPONSE_APPLY,
- sensitive);
+ pidgin_account_editor_set_valid(editor, sensitive);
}
static void
@@ -1103,7 +1069,8 @@ pidgin_account_editor_proxy_type_changed_cb(G_GNUC_UNUSED GObject *obj,
/******************************************************************************
* GObject Implementation
*****************************************************************************/
-G_DEFINE_TYPE(PidginAccountEditor, pidgin_account_editor, GTK_TYPE_DIALOG)
+G_DEFINE_TYPE(PidginAccountEditor, pidgin_account_editor,
+ ADW_TYPE_PREFERENCES_PAGE)
static void
pidgin_account_editor_get_property(GObject *obj, guint param_id, GValue *value,
@@ -1116,6 +1083,10 @@ pidgin_account_editor_get_property(GObject *obj, guint param_id, GValue *value,
g_value_set_object(value,
pidgin_account_editor_get_account(editor));
break;
+ case PROP_VALID:
+ g_value_set_boolean(value,
+ pidgin_account_editor_get_is_valid(editor));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
break;
@@ -1208,7 +1179,19 @@ pidgin_account_editor_class_init(PidginAccountEditorClass *klass) {
"account", "account",
"The account to modify",
PURPLE_TYPE_ACCOUNT,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PidginAccountEditor::valid:
+ *
+ * Whether or not the account settings are valid and it is okay to save the
+ * account.
+ */
+ properties[PROP_VALID] = g_param_spec_boolean(
+ "valid", "valid",
+ "Whether or not the account settings are valid",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
@@ -1293,3 +1276,71 @@ pidgin_account_editor_get_account(PidginAccountEditor *editor) {
return editor->account;
}
+
+void
+pidgin_account_editor_set_account(PidginAccountEditor *editor,
+ PurpleAccount *account)
+{
+ g_return_if_fail(PIDGIN_IS_ACCOUNT_EDITOR(editor));
+
+ /* Disconnect the notify handler from the previous account. */
+ if(PURPLE_IS_ACCOUNT(editor->account)) {
+ g_signal_handlers_disconnect_by_func(editor->account,
+ G_CALLBACK(pidgin_account_editor_connection_changed_cb),
+ editor);
+ }
+
+ if(g_set_object(&editor->account, account)) {
+ if(PURPLE_IS_ACCOUNT(account)) {
+ pidgin_protocol_chooser_set_protocol(PIDGIN_PROTOCOL_CHOOSER(editor->protocol),
+ purple_account_get_protocol(editor->account));
+
+ g_signal_connect_object(account, "notify::connection",
+ G_CALLBACK(pidgin_account_editor_connection_changed_cb),
+ editor, 0);
+ }
+
+ g_object_notify_by_pspec(G_OBJECT(editor), properties[PROP_ACCOUNT]);
+ }
+
+ pidgin_account_editor_update(editor);
+}
+
+gboolean
+pidgin_account_editor_get_is_valid(PidginAccountEditor *editor) {
+ g_return_val_if_fail(PIDGIN_IS_ACCOUNT_EDITOR(editor), FALSE);
+
+ return editor->valid;
+}
+
+void
+pidgin_account_editor_save(PidginAccountEditor *editor) {
+ gboolean new_account = FALSE;
+
+ g_return_if_fail(PIDGIN_IS_ACCOUNT_EDITOR(editor));
+ g_return_if_fail(editor->valid == TRUE);
+
+ 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();
+ if(saved_status != NULL) {
+ purple_savedstatus_activate_for_account(saved_status,
+ editor->account);
+ purple_account_set_enabled(editor->account, TRUE);
+ }
+ }
+}
diff --git a/pidgin/pidginaccounteditor.h b/pidgin/pidginaccounteditor.h
index f37ebabeb8..50bf55bc00 100644
--- a/pidgin/pidginaccounteditor.h
+++ b/pidgin/pidginaccounteditor.h
@@ -29,6 +29,8 @@
#include <gtk/gtk.h>
+#include <adwaita.h>
+
#include <purple.h>
/**
@@ -43,7 +45,7 @@ G_BEGIN_DECLS
#define PIDGIN_TYPE_ACCOUNT_EDITOR pidgin_account_editor_get_type()
G_DECLARE_FINAL_TYPE(PidginAccountEditor, pidgin_account_editor, PIDGIN,
- ACCOUNT_EDITOR, GtkDialog)
+ ACCOUNT_EDITOR, AdwPreferencesPage)
/**
* pidgin_account_editor_new:
@@ -70,6 +72,42 @@ GtkWidget *pidgin_account_editor_new(PurpleAccount *account);
*/
PurpleAccount *pidgin_account_editor_get_account(PidginAccountEditor *editor);
+/**
+ * pidgin_account_editor_set_account:
+ * @editor: The instance.
+ * @account: (nullable): The new account to edit.
+ *
+ * Sets the account that @editor is editing to @account. You can pass %NULL
+ * to remove the current account or edit a new account.
+ *
+ * Since: 3.0.0
+ */
+void pidgin_account_editor_set_account(PidginAccountEditor *editor, PurpleAccount *account);
+
+/**
+ * pidgin_account_editor_get_is_valid:
+ * @editor: The instance.
+ *
+ * Gets whether or not the settings for the account is valid and can be saved.
+ *
+ * Returns: %TRUE if the account being edited has valid values, otherwise
+ * %FALSE.
+ *
+ * Since: 3.0.0
+ */
+gboolean pidgin_account_editor_get_is_valid(PidginAccountEditor *editor);
+
+/**
+ * pidgin_account_editor_save:
+ * @editor: The instance.
+ *
+ * Save the account to disk. If this is a new account, it will be set to match
+ * the current global status which is "online" in most cases.
+ *
+ * Since: 3.0.0
+ */
+void pidgin_account_editor_save(PidginAccountEditor *editor);
+
G_END_DECLS
#endif /* PIDGIN_ACCOUNT_EDITOR_H */
diff --git a/pidgin/pidginaccountmanager.c b/pidgin/pidginaccountmanager.c
index 4162d8a617..ca036d875c 100644
--- a/pidgin/pidginaccountmanager.c
+++ b/pidgin/pidginaccountmanager.c
@@ -36,6 +36,15 @@ struct _PidginAccountManager {
GtkListBox *list_box;
GtkWidget *add;
+
+ GtkWidget *stack;
+ GtkWidget *editor;
+
+ /* This is used to not go back to the manager when an account was edited
+ * directly, via the `accounts->(account)->edit` menu or the
+ * `connection error` notification.
+ */
+ gboolean edit_only;
};
enum {
@@ -59,16 +68,32 @@ pidgin_account_manager_create_widget(gpointer item,
}
static void
-pidgin_account_manager_create_account(PidginAccountManager *manager) {
- GtkWidget *editor = pidgin_account_editor_new(NULL);
- gtk_window_set_transient_for(GTK_WINDOW(editor),
- GTK_WINDOW(manager));
- gtk_window_present_with_time(GTK_WINDOW(editor), GDK_CURRENT_TIME);
+pidgin_account_manager_real_edit_account(PidginAccountManager *manager,
+ PurpleAccount *account,
+ gboolean edit_only)
+{
+ g_return_if_fail(PIDGIN_IS_ACCOUNT_MANAGER(manager));
+
+ manager->edit_only = edit_only;
+
+ pidgin_account_editor_set_account(PIDGIN_ACCOUNT_EDITOR(manager->editor),
+ account);
+
+ gtk_stack_set_visible_child_name(GTK_STACK(manager->stack), "editor-page");
}
/******************************************************************************
* Callbacks
*****************************************************************************/
+/* This is used by the add button on the placeholder page. */
+static void
+pidgin_account_manager_create_account(G_GNUC_UNUSED GtkButton *self,
+ gpointer data)
+{
+ PidginAccountManager *manager = data;
+
+ pidgin_account_manager_real_edit_account(manager, NULL, FALSE);
+}
static void
pidgin_account_manager_refresh_add_cb(GListModel *list,
@@ -92,7 +117,7 @@ pidgin_account_manager_response_cb(GtkDialog *dialog, gint response_id,
switch(response_id) {
case RESPONSE_ADD:
- pidgin_account_manager_create_account(manager);
+ pidgin_account_manager_real_edit_account(manager, NULL, FALSE);
break;
case GTK_RESPONSE_CLOSE:
case GTK_RESPONSE_DELETE_EVENT:
@@ -106,14 +131,49 @@ pidgin_account_manager_response_cb(GtkDialog *dialog, gint response_id,
static void
pidgin_account_manager_row_activated_cb(G_GNUC_UNUSED GtkListBox *box,
GtkListBoxRow *row,
- G_GNUC_UNUSED gpointer data)
+ gpointer data)
{
- GtkWidget *editor = NULL;
PurpleAccount *account = NULL;
+ PidginAccountManager *manager = data;
account = pidgin_account_row_get_account(PIDGIN_ACCOUNT_ROW(row));
- editor = pidgin_account_editor_new(account);
- gtk_widget_show(editor);
+
+ pidgin_account_manager_real_edit_account(manager, account, FALSE);
+}
+
+static void
+pidgin_account_manager_back_clicked_cb(G_GNUC_UNUSED GtkButton *self,
+ gpointer data)
+{
+ PidginAccountManager *manager = data;
+
+#if ADW_CHECK_VERSION(1, 3, 0)
+ /* Scroll the editor back to the top of the scrolled window. */
+ adw_preferences_page_scroll_to_top(ADW_PREFERENCES_PAGE(manager->editor));
+#endif
+
+ /* Disconnect the account which will remove all of the account options as
+ * well.
+ */
+ pidgin_account_editor_set_account(PIDGIN_ACCOUNT_EDITOR(manager->editor),
+ NULL);
+
+ pidgin_account_manager_show_overview(manager);
+}
+
+static void
+pidgin_account_manager_save_clicked_cb(G_GNUC_UNUSED GtkButton *self,
+ gpointer data)
+{
+ PidginAccountManager *manager = data;
+
+ pidgin_account_editor_save(PIDGIN_ACCOUNT_EDITOR(manager->editor));
+
+ if(manager->edit_only) {
+ gtk_window_destroy(GTK_WINDOW(manager));
+ } else {
+ gtk_stack_set_visible_child_name(GTK_STACK(manager->stack), "overview");
+ }
}
/******************************************************************************
@@ -147,6 +207,10 @@ pidgin_account_manager_class_init(PidginAccountManagerClass *klass) {
list_box);
gtk_widget_class_bind_template_child(widget_class, PidginAccountManager,
add);
+ gtk_widget_class_bind_template_child(widget_class, PidginAccountManager,
+ stack);
+ gtk_widget_class_bind_template_child(widget_class, PidginAccountManager,
+ editor);
gtk_widget_class_bind_template_callback(widget_class,
pidgin_account_manager_response_cb);
@@ -154,6 +218,10 @@ pidgin_account_manager_class_init(PidginAccountManagerClass *klass) {
pidgin_account_manager_row_activated_cb);
gtk_widget_class_bind_template_callback(widget_class,
pidgin_account_manager_create_account);
+ gtk_widget_class_bind_template_callback(widget_class,
+ pidgin_account_manager_back_clicked_cb);
+ gtk_widget_class_bind_template_callback(widget_class,
+ pidgin_account_manager_save_clicked_cb);
}
/******************************************************************************
@@ -163,3 +231,20 @@ GtkWidget *
pidgin_account_manager_new(void) {
return g_object_new(PIDGIN_TYPE_ACCOUNT_MANAGER, NULL);
}
+
+void
+pidgin_account_manager_show_overview(PidginAccountManager *manager) {
+ g_return_if_fail(PIDGIN_IS_ACCOUNT_MANAGER(manager));
+
+ gtk_stack_set_visible_child_name(GTK_STACK(manager->stack), "overview");
+}
+
+void
+pidgin_account_manager_edit_account(PidginAccountManager *manager,
+ PurpleAccount *account)
+{
+ g_return_if_fail(PIDGIN_IS_ACCOUNT_MANAGER(manager));
+ g_return_if_fail(PURPLE_IS_ACCOUNT(account));
+
+ pidgin_account_manager_real_edit_account(manager, account, TRUE);
+}
diff --git a/pidgin/pidginaccountmanager.h b/pidgin/pidginaccountmanager.h
index 84fca9ea9e..6f757b65b6 100644
--- a/pidgin/pidginaccountmanager.h
+++ b/pidgin/pidginaccountmanager.h
@@ -54,6 +54,28 @@ G_DECLARE_FINAL_TYPE(PidginAccountManager, pidgin_account_manager, PIDGIN,
*/
GtkWidget *pidgin_account_manager_new(void);
+/**
+ * pidgin_account_managet_show_overview:
+ * @manager: The instance.
+ *
+ * Switches @manager to the overview page. This is useful as @manager might
+ * already be visible but editing an account.
+ *
+ * Since: 3.0.0
+ */
+void pidgin_account_manager_show_overview(PidginAccountManager *manager);
+
+/**
+ * pidgin_account_manager_edit_account:
+ * @manager: The instance.
+ * @account: The account to edit.
+ *
+ * Opens the account editor in @manager for the given account.
+ *
+ * Since: 3.0.0
+ */
+void pidgin_account_manager_edit_account(PidginAccountManager *manager, PurpleAccount *account);
+
G_END_DECLS
#endif /* PIDGIN_ACCOUNT_MANAGER_H */
diff --git a/pidgin/pidginapplication.c b/pidgin/pidginapplication.c
index 603f2e7e6e..177f67ae84 100644
--- a/pidgin/pidginapplication.c
+++ b/pidgin/pidginapplication.c
@@ -95,6 +95,26 @@ G_DEFINE_TYPE(PidginApplication, pidgin_application, GTK_TYPE_APPLICATION)
*****************************************************************************/
/*
+ * pidgin_application_get_account_manager:
+ *
+ * The Pidgin account manager can get opened from multiple actions, so this
+ * helper manages the singleton.
+ *
+ * Since: 3.0.0
+ */
+static GtkWidget *
+pidgin_application_get_account_manager(void) {
+ static GtkWidget *manager = NULL;
+
+ if(!PIDGIN_IS_ACCOUNT_MANAGER(manager)) {
+ manager = pidgin_account_manager_new();
+ g_object_add_weak_pointer(G_OBJECT(manager), (gpointer)&manager);
+ }
+
+ return manager;
+}
+
+/*
* pidgin_application_present_transient_window:
* @application: The application instance.
* @window: The [class@Gtk.Window] to present.
@@ -275,12 +295,9 @@ pidgin_application_accounts(G_GNUC_UNUSED GSimpleAction *simple,
G_GNUC_UNUSED GVariant *parameter, gpointer data)
{
PidginApplication *application = data;
- static GtkWidget *manager = NULL;
+ GtkWidget *manager = pidgin_application_get_account_manager();
- if(!GTK_IS_WIDGET(manager)) {
- manager = pidgin_account_manager_new();
- g_object_add_weak_pointer(G_OBJECT(manager), (gpointer)&manager);
- }
+ pidgin_account_manager_show_overview(PIDGIN_ACCOUNT_MANAGER(manager));
pidgin_application_present_transient_window(application,
GTK_WINDOW(manager));
@@ -377,16 +394,27 @@ pidgin_application_edit_account(G_GNUC_UNUSED GSimpleAction *simple,
PurpleAccountManager *manager = NULL;
const gchar *id = NULL;
+ if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
+ g_warning("parameter is of type %s, expected %s",
+ g_variant_get_type_string(parameter),
+ (char *)G_VARIANT_TYPE_STRING);
+
+ return;
+ }
+
id = g_variant_get_string(parameter, NULL);
manager = purple_account_manager_get_default();
account = purple_account_manager_find_by_id(manager, id);
if(PURPLE_IS_ACCOUNT(account)) {
- GtkWidget *editor = pidgin_account_editor_new(account);
+ GtkWidget *account_manager = pidgin_application_get_account_manager();
+
+ pidgin_account_manager_edit_account(PIDGIN_ACCOUNT_MANAGER(account_manager),
+ account);
pidgin_application_present_transient_window(application,
- GTK_WINDOW(editor));
+ GTK_WINDOW(account_manager));
}
}
diff --git a/pidgin/resources/Accounts/editor.ui b/pidgin/resources/Accounts/editor.ui
index 5b93fb81e1..f89d0c8f0b 100644
--- a/pidgin/resources/Accounts/editor.ui
+++ b/pidgin/resources/Accounts/editor.ui
@@ -26,195 +26,181 @@ along with this program; if not, see <https://www.gnu.org/licenses/>.
<!-- interface-name Pidgin -->
<!-- interface-description Internet Messenger -->
<!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
- <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="vexpand">1</property>
+ <template class="PidginAccountEditor" parent="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="AdwPreferencesPage">
- <property name="vexpand">1</property>
- <property name="hexpand">1</property>
+ <object class="PidginProtocolChooser" id="protocol">
+ <property name="title" translatable="1">Pro_tocol</property>
+ <property name="use-underline">1</property>
+ <signal name="notify::protocol" handler="pidgin_account_editor_protocol_changed_cb" object="PidginAccountEditor" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesRow">
+ <property name="focusable">0</property>
<child>
- <object class="AdwPreferencesGroup" id="login_options">
- <property name="title" translatable="1">Login Options</property>
- <child>
- <object class="PidginProtocolChooser" id="protocol">
- <property name="title" translatable="1">Pro_tocol</property>
- <property name="use-underline">1</property>
- <signal name="notify::protocol" handler="pidgin_account_editor_protocol_changed_cb" object="PidginAccountEditor" swapped="no"/>
- </object>
- </child>
+ <object class="GtkListBox" id="user_splits">
+ <property name="focusable">0</property>
<child>
- <object class="AdwPreferencesRow">
+ <object class="AdwEntryRow" id="username">
<property name="focusable">0</property>
- <child>
- <object class="GtkListBox" id="user_splits">
- <property name="focusable">0</property>
- <child>
- <object class="AdwEntryRow" id="username">
- <property name="focusable">0</property>
- <property name="title" translatable="1">_Username</property>
- <property name="use-underline">1</property>
- <signal name="changed" handler="pidgin_account_editor_username_changed_cb" object="PidginAccountEditor" swapped="no"/>
- </object>
- </child>
- </object>
- </child>
+ <property name="title" translatable="1">_Username</property>
+ <property name="use-underline">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="AdwActionRow" id="require_password_row">
+ <property name="activatable-widget">avatar</property>
+ <property name="focusable">0</property>
+ <property name="title" translatable="1">Require _password</property>
+ <property name="subtitle" translatable="1">This account has an optional password, setting this will make it required</property>
+ <property name="use-underline">1</property>
+ <property name="visible">0</property>
+ <child type="suffix">
+ <object class="GtkSwitch" id="require_password">
+ <property name="valign">center</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="AdwPreferencesGroup">
+ <property name="title" translatable="1">User Options</property>
+ <child>
+ <object class="AdwEntryRow" id="alias">
+ <property name="focusable">0</property>
+ <property name="title" translatable="1">_Local alias</property>
+ <property name="use-underline">1</property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwActionRow" id="avatar_row">
+ <property name="activatable-widget">avatar</property>
+ <property name="focusable">0</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="AdwActionRow" id="require_password_row">
- <property name="activatable-widget">avatar</property>
- <property name="focusable">0</property>
- <property name="title" translatable="1">Require _password</property>
- <property name="subtitle" translatable="1">This account has an optional password, setting this will make it required</property>
- <property name="use-underline">1</property>
- <property name="visible">0</property>
- <child type="suffix">
- <object class="GtkSwitch" id="require_password">
- <property name="valign">center</property>
- </object>
- </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>
+ </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>
+ </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="focusable">0</property>
+ <property name="visible">0</property>
<child>
- <object class="AdwPreferencesGroup">
- <property name="title" translatable="1">User Options</property>
+ <object class="GtkListBox">
+ <property name="focusable">0</property>
<child>
- <object class="AdwEntryRow" id="alias">
+ <object class="AdwEntryRow" id="proxy_host">
<property name="focusable">0</property>
- <property name="title" translatable="1">_Local alias</property>
+ <property name="title" translatable="1">_Host</property>
<property name="use-underline">1</property>
</object>
</child>
<child>
- <object class="AdwActionRow" id="avatar_row">
- <property name="activatable-widget">avatar</property>
+ <object class="AdwEntryRow" id="proxy_port">
<property name="focusable">0</property>
- <property name="title" translatable="1">Use custom _avatar</property>
+ <property name="title" translatable="1">P_ort</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>
+ <property name="input-purpose">number</property>
</object>
</child>
- </object>
- </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>
- </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>
+ <object class="AdwEntryRow" id="proxy_username">
+ <property name="focusable">0</property>
+ <property name="title" translatable="1">User_name</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">
+ <object class="AdwPasswordEntryRow" id="proxy_password">
<property name="focusable">0</property>
- <property name="visible">0</property>
- <child>
- <object class="GtkListBox">
- <property name="focusable">0</property>
- <child>
- <object class="AdwEntryRow" id="proxy_host">
- <property name="focusable">0</property>
- <property name="title" translatable="1">_Host</property>
- <property name="use-underline">1</property>
- </object>
- </child>
- <child>
- <object class="AdwEntryRow" id="proxy_port">
- <property name="focusable">0</property>
- <property name="title" translatable="1">P_ort</property>
- <property name="use-underline">1</property>
- <property name="input-purpose">number</property>
- </object>
- </child>
- <child>
- <object class="AdwEntryRow" id="proxy_username">
- <property name="focusable">0</property>
- <property name="title" translatable="1">User_name</property>
- <property name="use-underline">1</property>
- </object>
- </child>
- <child>
- <object class="AdwPasswordEntryRow" id="proxy_password">
- <property name="focusable">0</property>
- <property name="title" translatable="1">Pa_ssword</property>
- <property name="use-underline">1</property>
- </object>
- </child>
- </object>
- </child>
+ <property name="title" translatable="1">Pa_ssword</property>
+ <property name="use-underline">1</property>
</object>
</child>
</object>
@@ -223,25 +209,5 @@ along with this program; if not, see <https://www.gnu.org/licenses/>.
</child>
</object>
</child>
- <child type="action">
- <object class="GtkButton" id="button1">
- <property name="label" translatable="1">_Cancel</property>
- <property name="receives-default">1</property>
- <property name="use-underline">1</property>
- </object>
- </child>
- <child type="action">
- <object class="GtkButton" id="button2">
- <property name="css-classes">suggested-action</property>
- <property name="label" translatable="1">_Save</property>
- <property name="receives-default">1</property>
- <property name="sensitive">0</property>
- <property name="use-underline">1</property>
- </object>
- </child>
- <action-widgets>
- <action-widget response="cancel">button1</action-widget>
- <action-widget response="apply">button2</action-widget>
- </action-widgets>
</template>
</interface>
diff --git a/pidgin/resources/Accounts/manager.ui b/pidgin/resources/Accounts/manager.ui
index 001cdc449e..434a225692 100644
--- a/pidgin/resources/Accounts/manager.ui
+++ b/pidgin/resources/Accounts/manager.ui
@@ -32,64 +32,122 @@ along with this program; if not, see <https://www.gnu.org/licenses/>.
<child internal-child="content_area">
<object class="GtkBox">
<child>
- <object class="GtkScrolledWindow">
- <property name="vexpand">1</property>
- <property name="child">
- <object class="AdwClamp">
- <property name="margin-bottom">24</property>
- <property name="margin-end">24</property>
- <property name="margin-start">24</property>
- <property name="margin-top">24</property>
- <property name="orientation">horizontal</property>
- <child>
- <object class="GtkListBox" id="list_box">
- <property name="css-classes">boxed-list
-rich-list</property>
- <property name="selection-mode">none</property>
- <property name="show-separators">1</property>
- <signal name="row-activated" handler="pidgin_account_manager_row_activated_cb" swapped="no"/>
- <child type="placeholder">
- <object class="GtkBox">
- <property name="margin-bottom">48</property>
- <property name="margin-top">48</property>
- <property name="orientation">vertical</property>
- <property name="spacing">12</property>
- <property name="valign">center</property>
- <property name="vexpand">1</property>
+ <object class="GtkStack" id="stack">
+ <property name="transition-type">slide-left-right</property>
+ <property name="vhomogeneous">0</property>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">overview</property>
+ <property name="child">
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar_policy">never</property>
+ <property name="vexpand">1</property>
+ <property name="child">
+ <object class="AdwClamp">
+ <property name="margin-bottom">24</property>
+ <property name="margin-end">24</property>
+ <property name="margin-start">24</property>
+ <property name="margin-top">24</property>
+ <property name="orientation">horizontal</property>
<child>
- <object class="GtkImage">
- <property name="css-classes">dim-label</property>
- <property name="icon-name">view-list-symbolic</property>
- <property name="pixel-size">128</property>
+ <object class="GtkListBox" id="list_box">
+ <property name="css-classes">boxed-list
+ rich-list</property>
+ <property name="selection-mode">none</property>
+ <property name="show-separators">1</property>
+ <signal name="row-activated" handler="pidgin_account_manager_row_activated_cb" swapped="no"/>
+ <child type="placeholder">
+ <object class="GtkBox">
+ <property name="margin-bottom">48</property>
+ <property name="margin-top">48</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <property name="valign">center</property>
+ <property name="vexpand">1</property>
+ <child>
+ <object class="GtkImage">
+ <property name="css-classes">dim-label</property>
+ <property name="icon-name">view-list-symbolic</property>
+ <property name="pixel-size">128</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="css-classes">title-1</property>
+ <property name="label" translatable="1">No Accounts</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton">
+ <property name="css-classes">pill
+suggested-action</property>
+ <property name="halign">center</property>
+ <signal name="clicked" handler="pidgin_account_manager_create_account"/>
+ <property name="child">
+ <object class="AdwButtonContent">
+ <property name="icon-name">list-add-symbolic</property>
+ <property name="label" translatable="1">_Add…</property>
+ <property name="use-underline">1</property>
+ </object>
+ </property>
+ </object>
+ </child>
+ </object>
+ </child>
</object>
</child>
+ </object>
+ </property>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">editor-page</property>
+ <property name="child">
+ <object class="GtkBox">
+ <property name="margin-bottom">24</property>
+ <property name="margin-end">24</property>
+ <property name="margin-start">24</property>
+ <property name="margin-top">24</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkLabel">
- <property name="css-classes">title-1</property>
- <property name="label" translatable="1">No Accounts</property>
+ <object class="GtkButton">
+ <property name="css-classes">flat</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="tooltip-text" translatable="1">Back</property>
+ <signal name="clicked" handler="pidgin_account_manager_back_clicked_cb"/>
</object>
</child>
<child>
<object class="GtkButton">
- <property name="css-classes">pill
-suggested-action</property>
- <property name="halign">center</property>
- <signal name="clicked" handler="pidgin_account_manager_create_account" swapped="yes"/>
- <property name="child">
- <object class="AdwButtonContent">
- <property name="icon-name">list-add-symbolic</property>
- <property name="label" translatable="1">_Add…</property>
- <property name="use-underline">1</property>
- </object>
- </property>
+ <property name="css-classes">flat</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="icon-name">document-save-symbolic</property>
+ <property name="tooltip-text" translatable="1">Save</property>
+ <binding name="sensitive">
+ <lookup name="valid">editor</lookup>
+ </binding>
+ <signal name="clicked" handler="pidgin_account_manager_save_clicked_cb"/>
</object>
</child>
</object>
</child>
+ <child>
+ <object class="PidginAccountEditor" id="editor"/>
+ </child>
</object>
- </child>
+ </property>
</object>
- </property>
+ </child>
</object>
</child>
</object>
@@ -108,17 +166,8 @@ suggested-action</property>
</property>
</object>
</child>
- <child type="action">
- <object class="GtkButton" id="button2">
- <property name="label" translatable="1">_Close</property>
- <property name="focusable">1</property>
- <property name="receives-default">1</property>
- <property name="use-underline">1</property>
- </object>
- </child>
<action-widgets>
<action-widget response="0">add</action-widget>
- <action-widget response="close">button2</action-widget>
</action-widgets>
</template>
</interface>