pidgin/pidgin

41b9c5be8965
Parents a90f1381c9a8
Children 2bcdf415a79d
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/
--- a/pidgin/pidginaccounteditor.c Thu Mar 16 22:19:39 2023 -0500
+++ b/pidgin/pidginaccounteditor.c Thu Mar 16 22:36:19 2023 -0500
@@ -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 @@
enum {
PROP_0,
PROP_ACCOUNT,
+ PROP_VALID,
N_PROPERTIES,
};
static GParamSpec *properties[N_PROPERTIES] = {NULL, };
@@ -86,6 +89,17 @@
* 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_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 @@
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 @@
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 @@
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 @@
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 @@
/******************************************************************************
* 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 @@
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 @@
"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 @@
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);
+ }
+ }
+}
--- a/pidgin/pidginaccounteditor.h Thu Mar 16 22:19:39 2023 -0500
+++ b/pidgin/pidginaccounteditor.h Thu Mar 16 22:36:19 2023 -0500
@@ -29,6 +29,8 @@
#include <gtk/gtk.h>
+#include <adwaita.h>
+
#include <purple.h>
/**
@@ -43,7 +45,7 @@
#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 @@
*/
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 */
--- a/pidgin/pidginaccountmanager.c Thu Mar 16 22:19:39 2023 -0500
+++ b/pidgin/pidginaccountmanager.c Thu Mar 16 22:36:19 2023 -0500
@@ -36,6 +36,15 @@
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 @@
}
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 @@
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 @@
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 @@
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_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 @@
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);
+}
--- a/pidgin/pidginaccountmanager.h Thu Mar 16 22:19:39 2023 -0500
+++ b/pidgin/pidginaccountmanager.h Thu Mar 16 22:36:19 2023 -0500
@@ -54,6 +54,28 @@
*/
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 */
--- a/pidgin/pidginapplication.c Thu Mar 16 22:19:39 2023 -0500
+++ b/pidgin/pidginapplication.c Thu Mar 16 22:36:19 2023 -0500
@@ -95,6 +95,26 @@
*****************************************************************************/
/*
+ * 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 @@
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 @@
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));
}
}
--- a/pidgin/resources/Accounts/editor.ui Thu Mar 16 22:19:39 2023 -0500
+++ b/pidgin/resources/Accounts/editor.ui Thu Mar 16 22:36:19 2023 -0500
@@ -26,195 +26,181 @@
<!-- 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>
+ <object class="GtkListBox" id="user_splits">
+ <property name="focusable">0</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>
- <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>
- </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="title" translatable="1">_Username</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>
+ <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="AdwPreferencesGroup">
- <property name="title" translatable="1">User Options</property>
+ <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="AdwEntryRow" id="alias">
+ <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="GtkListBox">
+ <property name="focusable">0</property>
+ <child>
+ <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>
- </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"/>
+ <property name="input-purpose">number</property>
</object>
</child>
<child>
- <object class="AdwPreferencesRow" id="proxy_options">
+ <object class="AdwEntryRow" id="proxy_username">
<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">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>
@@ -223,25 +209,5 @@
</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>
--- a/pidgin/resources/Accounts/manager.ui Thu Mar 16 22:19:39 2023 -0500
+++ b/pidgin/resources/Accounts/manager.ui Thu Mar 16 22:36:19 2023 -0500
@@ -32,64 +32,122 @@
<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 @@
</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>