Port account manager to AdwNavigationView

Thu, 21 Nov 2024 21:41:35 -0600

author
Elliott Sales de Andrade <quantum.analyst@gmail.com>
date
Thu, 21 Nov 2024 21:41:35 -0600
changeset 43073
b97e5e85b97d
parent 43072
a59a119b74f5
child 43074
0ff905ef6259

Port account manager to AdwNavigationView

This handles all the forward/back stuff for us (with the `GtkButton`, Escape key, `Alt`-`←`, or mouse back button.)

The editor is currently a page that's re-used. I'm not sure if it's better to use a page per account, but this works just fine.

The overview/placeholder page remains about the same, except the Add button is in an action bar.

The account editor is also about the same, except for the movement of the Back button to the header, and the Save button to the action bar. I also added a Remove button on the opposite end. I'm not sure, but debating whether we should remove the Remove buttons from the overview page since they take up space for something you probably won't do that often.

Testing Done:
Opened empty config, added a Bonjour/IRCv3 account, toggled a few options, went back and forth to overview, and removed the account from both pages.

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

pidgin/pidginaccountmanager.c file | annotate | diff | comparison | revisions
pidgin/pidginaccountmanager.h file | annotate | diff | comparison | revisions
pidgin/resources/Accounts/manager.ui file | annotate | diff | comparison | revisions
--- a/pidgin/pidginaccountmanager.c	Thu Nov 21 00:35:20 2024 -0600
+++ b/pidgin/pidginaccountmanager.c	Thu Nov 21 21:41:35 2024 -0600
@@ -31,13 +31,20 @@
 #include "pidginaccountmanagerrow.h"
 
 struct _PidginAccountManager {
-	GtkDialog parent;
+	AdwWindow parent;
+
+	AdwNavigationView *view;
 
-	GtkListBox *list_box;
-	GtkWidget *add;
+	struct {
+		GtkListBox *list_box;
+		GtkActionBar *action_bar;
+	} overview;
 
-	GtkWidget *stack;
-	GtkWidget *editor;
+	struct {
+		PidginAccountEditor *editor;
+		GtkButton *add;
+		GtkWidget *remove;
+	} 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
@@ -46,12 +53,8 @@
 	gboolean edit_only;
 };
 
-enum {
-	RESPONSE_ADD,
-};
-
 G_DEFINE_FINAL_TYPE(PidginAccountManager, pidgin_account_manager,
-                    GTK_TYPE_DIALOG)
+                    ADW_TYPE_WINDOW)
 
 /******************************************************************************
  * Helpers
@@ -76,10 +79,20 @@
 
 	manager->edit_only = edit_only;
 
-	pidgin_account_editor_set_account(PIDGIN_ACCOUNT_EDITOR(manager->editor),
-	                                  account);
+	pidgin_account_editor_set_account(manager->editor.editor, account);
+
+	/* Scroll the editor back to the top of the scrolled window. */
+	adw_preferences_page_scroll_to_top(ADW_PREFERENCES_PAGE(manager->editor.editor));
 
-	gtk_stack_set_visible_child_name(GTK_STACK(manager->stack), "editor-page");
+	if(PURPLE_IS_ACCOUNT(account)) {
+		gtk_button_set_label(manager->editor.add, _("_Save"));
+		gtk_widget_set_visible(manager->editor.remove, TRUE);
+	} else {
+		gtk_button_set_label(manager->editor.add, _("_Add"));
+		gtk_widget_set_visible(manager->editor.remove, FALSE);
+	}
+
+	adw_navigation_view_push_by_tag(manager->view, "editor");
 }
 
 /******************************************************************************
@@ -105,27 +118,9 @@
 	PidginAccountManager *manager = data;
 
 	/* If there are no accounts, the placeholder is shown, which includes an
-	 * Add button. So hide the one in the button box if that's the case. */
-	gtk_widget_set_visible(manager->add, g_list_model_get_n_items(list) != 0);
-}
-
-static void
-pidgin_account_manager_response_cb(GtkDialog *dialog, gint response_id,
-                                   G_GNUC_UNUSED gpointer data)
-{
-	PidginAccountManager *manager = PIDGIN_ACCOUNT_MANAGER(dialog);
-
-	switch(response_id) {
-		case RESPONSE_ADD:
-			pidgin_account_manager_real_edit_account(manager, NULL, FALSE);
-			break;
-		case GTK_RESPONSE_CLOSE:
-		case GTK_RESPONSE_DELETE_EVENT:
-			gtk_window_destroy(GTK_WINDOW(dialog));
-			break;
-		default:
-			g_warning("not sure how you got here...");
-	}
+	 * Add button. So hide the button box if that's the case. */
+	gtk_action_bar_set_revealed(manager->overview.action_bar,
+	                            g_list_model_get_n_items(list) != 0);
 }
 
 static void
@@ -144,17 +139,65 @@
 }
 
 static void
-pidgin_account_manager_back_clicked_cb(G_GNUC_UNUSED GtkButton *self,
-                                       gpointer data)
+pidgin_account_manager_remove_account_cb(G_GNUC_UNUSED AdwMessageDialog *self,
+                                         char *response, gpointer data)
+{
+	PidginAccountManager *account_manager = data;
+	PurpleAccount *account = NULL;
+	PurpleNotificationManager *notification_manager = NULL;
+
+	if(!purple_strequal(response, "remove")) {
+		return;
+	}
+
+	account = pidgin_account_editor_get_account(account_manager->editor.editor);
+
+	/* Remove all notifications including connection errors for the account. */
+	notification_manager = purple_notification_manager_get_default();
+	purple_notification_manager_remove_with_account(notification_manager,
+	                                                account, TRUE);
+
+	/* Delete the account. */
+	purple_accounts_delete(account);
+
+	pidgin_account_manager_show_overview(account_manager);
+}
+
+static void
+pidgin_account_manager_remove_clicked_cb(G_GNUC_UNUSED GtkButton *self,
+                                         gpointer data)
 {
 	PidginAccountManager *manager = data;
+	PurpleAccount *account = NULL;
+	PurpleProtocol *protocol = NULL;
+	AdwAlertDialog *dialog = NULL;
+	const char *name = NULL;
+	const char *protocol_name = _("Unknown");
 
-#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
+	account = pidgin_account_editor_get_account(manager->editor.editor);
+	name = purple_account_get_username(account);
+	protocol = purple_account_get_protocol(account);
+	if(PURPLE_IS_PROTOCOL(protocol)) {
+		protocol_name = purple_protocol_get_name(protocol);
+	}
 
-	pidgin_account_manager_show_overview(manager);
+	dialog = ADW_ALERT_DIALOG(adw_alert_dialog_new(_("Remove account?"), NULL));
+	adw_alert_dialog_format_body(
+		dialog,
+		_("Do you want to remove the %s (%s) account from Pidgin?"),
+		name, protocol_name);
+	adw_alert_dialog_add_responses(dialog, "cancel", _("Cancel"),
+	                               "remove", _("Remove"), NULL);
+	adw_alert_dialog_set_response_appearance(dialog, "remove",
+	                                         ADW_RESPONSE_DESTRUCTIVE);
+	adw_alert_dialog_set_default_response(dialog, "cancel");
+	adw_alert_dialog_set_close_response(dialog, "cancel");
+
+	g_signal_connect(dialog, "response",
+	                 G_CALLBACK(pidgin_account_manager_remove_account_cb),
+	                 manager);
+
+	adw_dialog_present(ADW_DIALOG(dialog), GTK_WIDGET(manager));
 }
 
 static void
@@ -163,7 +206,7 @@
 {
 	PidginAccountManager *manager = data;
 
-	pidgin_account_editor_save(PIDGIN_ACCOUNT_EDITOR(manager->editor));
+	pidgin_account_editor_save(manager->editor.editor);
 
 	if(manager->edit_only) {
 		gtk_window_destroy(GTK_WINDOW(manager));
@@ -182,7 +225,7 @@
 	gtk_widget_init_template(GTK_WIDGET(manager));
 
 	purple_manager = purple_account_manager_get_default_as_model();
-	gtk_list_box_bind_model(manager->list_box, purple_manager,
+	gtk_list_box_bind_model(manager->overview.list_box, purple_manager,
 	                        pidgin_account_manager_create_widget, NULL, NULL);
 	g_signal_connect_object(purple_manager, "items-changed",
 	                        G_CALLBACK(pidgin_account_manager_refresh_add_cb),
@@ -200,22 +243,26 @@
 	);
 
 	gtk_widget_class_bind_template_child(widget_class, PidginAccountManager,
-	                                     list_box);
+	                                     view);
+
 	gtk_widget_class_bind_template_child(widget_class, PidginAccountManager,
-	                                     add);
+	                                     overview.list_box);
 	gtk_widget_class_bind_template_child(widget_class, PidginAccountManager,
-	                                     stack);
+	                                     overview.action_bar);
+
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountManager,
+	                                     editor.editor);
 	gtk_widget_class_bind_template_child(widget_class, PidginAccountManager,
-	                                     editor);
+	                                     editor.add);
+	gtk_widget_class_bind_template_child(widget_class, PidginAccountManager,
+	                                     editor.remove);
 
 	gtk_widget_class_bind_template_callback(widget_class,
-	                                        pidgin_account_manager_response_cb);
-	gtk_widget_class_bind_template_callback(widget_class,
 	                                        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);
+	                                        pidgin_account_manager_remove_clicked_cb);
 	gtk_widget_class_bind_template_callback(widget_class,
 	                                        pidgin_account_manager_save_clicked_cb);
 }
@@ -232,10 +279,9 @@
 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");
+	adw_navigation_view_pop_to_tag(manager->view, "overview");
 
-	pidgin_account_editor_set_account(PIDGIN_ACCOUNT_EDITOR(manager->editor),
-	                                  NULL);
+	pidgin_account_editor_set_account(manager->editor.editor, NULL);
 }
 
 void
--- a/pidgin/pidginaccountmanager.h	Thu Nov 21 00:35:20 2024 -0600
+++ b/pidgin/pidginaccountmanager.h	Thu Nov 21 21:41:35 2024 -0600
@@ -29,6 +29,8 @@
 
 #include <gtk/gtk.h>
 
+#include <adwaita.h>
+
 #include "pidginversion.h"
 
 G_BEGIN_DECLS
@@ -45,7 +47,7 @@
 
 PIDGIN_AVAILABLE_IN_3_0
 G_DECLARE_FINAL_TYPE(PidginAccountManager, pidgin_account_manager, PIDGIN,
-                     ACCOUNT_MANAGER, GtkDialog)
+                     ACCOUNT_MANAGER, AdwWindow)
 
 /**
  * pidgin_account_manager_new:
--- a/pidgin/resources/Accounts/manager.ui	Thu Nov 21 00:35:20 2024 -0600
+++ b/pidgin/resources/Accounts/manager.ui	Thu Nov 21 21:41:35 2024 -0600
@@ -24,24 +24,23 @@
   <!-- interface-name Pidgin -->
   <!-- interface-description Internet Messenger -->
   <!-- interface-copyright Pidgin Developers <devel@pidgin.im> -->
-  <template class="PidginAccountManager" parent="GtkDialog">
-    <property name="title" translatable="1">Accounts</property>
-    <property name="default-width">640</property>
-    <property name="default-height">480</property>
-    <signal name="response" handler="pidgin_account_manager_response_cb" swapped="no"/>
-    <child internal-child="content_area">
-      <object class="GtkBox">
+  <template class="PidginAccountManager" parent="AdwWindow">
+    <property name="width-request">640</property>
+    <property name="height-request">480</property>
+    <property name="content">
+      <object class="AdwNavigationView" id="view">
         <child>
-          <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="AdwNavigationPage">
+            <property name="tag">overview</property>
+            <property name="title" translatable="1">Accounts</property>
+            <property name="child">
+              <object class="AdwToolbarView">
+                <child type="top">
+                  <object class="AdwHeaderBar"/>
+                </child>
+                <property name="content">
                   <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>
@@ -50,7 +49,7 @@
                         <property name="margin-top">24</property>
                         <property name="orientation">horizontal</property>
                         <child>
-                          <object class="GtkListBox" id="list_box">
+                          <object class="GtkListBox" id="overview.list_box">
                             <property name="css-classes">boxed-list
 rich-list</property>
                             <property name="selection-mode">none</property>
@@ -83,74 +82,67 @@
                     </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="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"/>
+                <child type="bottom">
+                  <object class="GtkActionBar" id="overview.action_bar">
+                    <child type="end">
+                      <object class="GtkButton">
+                        <property name="css-classes">suggested-action</property>
+                        <property name="focusable">1</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>
-                        </child>
-                        <child>
-                          <object class="GtkButton">
-                            <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>
+                        </property>
                       </object>
                     </child>
-                    <child>
-                      <object class="PidginAccountEditor" id="editor"/>
+                  </object>
+                </child>
+              </object>
+            </property>
+          </object>
+        </child>
+        <child>
+          <object class="AdwNavigationPage" id="editor_page">
+            <property name="tag">editor</property>
+            <property name="title" translatable="1">Editor</property>
+            <property name="child">
+              <object class="AdwToolbarView">
+                <child type="top">
+                  <object class="AdwHeaderBar"/>
+                </child>
+                <property name="content">
+                  <object class="PidginAccountEditor" id="editor.editor"/>
+                </property>
+                <child type="bottom">
+                  <object class="GtkActionBar">
+                    <child type="start">
+                      <object class="GtkButton" id="editor.remove">
+                        <property name="css-classes">destructive-action</property>
+                        <property name="label" translatable="1">_Remove</property>
+                        <property name="use-underline">1</property>
+                        <signal name="clicked" handler="pidgin_account_manager_remove_clicked_cb"/>
+                      </object>
+                    </child><child type="end">
+                      <object class="GtkButton" id="editor.add">
+                        <property name="css-classes">suggested-action</property>
+                        <property name="label" translatable="1">_Add</property>
+                        <property name="use-underline">1</property>
+                        <binding name="sensitive">
+                          <lookup name="valid">editor.editor</lookup>
+                        </binding>
+                        <signal name="clicked" handler="pidgin_account_manager_save_clicked_cb"/>
+                      </object>
                     </child>
                   </object>
-                </property>
+                </child>
               </object>
-            </child>
+            </property>
           </object>
         </child>
       </object>
-    </child>
-    <child type="action">
-      <object class="GtkButton" id="add">
-        <property name="css-classes">suggested-action</property>
-        <property name="focusable">1</property>
-        <property name="receives-default">1</property>
-        <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>
-    <action-widgets>
-      <action-widget response="0">add</action-widget>
-    </action-widgets>
+    </property>
   </template>
 </interface>

mercurial