Create a menu controller that will keep a GMenu in sync with the disabled accounts in libpurple

Mon, 14 Mar 2022 01:18:18 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Mon, 14 Mar 2022 01:18:18 -0500
changeset 41298
6d816e02fd76
parent 41297
4960320545ef
child 41299
4a8bdbae8d8b

Create a menu controller that will keep a GMenu in sync with the disabled accounts in libpurple

Testing Done:
Used the account manager to disable and account, then disabled it from the menu and verified that the item was removed.

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

libpurple/purpleaccountmanager.c file | annotate | diff | comparison | revisions
libpurple/purpleaccountmanager.h file | annotate | diff | comparison | revisions
pidgin/meson.build file | annotate | diff | comparison | revisions
pidgin/pidginaccountsdisabledmenu.c file | annotate | diff | comparison | revisions
pidgin/pidginaccountsdisabledmenu.h file | annotate | diff | comparison | revisions
pidgin/pidginapplication.c file | annotate | diff | comparison | revisions
pidgin/resources/gtk/menus.ui file | annotate | diff | comparison | revisions
po/POTFILES.in file | annotate | diff | comparison | revisions
--- a/libpurple/purpleaccountmanager.c	Sun Mar 13 23:59:40 2022 -0500
+++ b/libpurple/purpleaccountmanager.c	Mon Mar 14 01:18:18 2022 -0500
@@ -251,6 +251,26 @@
 }
 
 PurpleAccount *
+purple_account_manager_find_by_id(PurpleAccountManager *manager,
+                                  const gchar *id)
+{
+	GList *l = NULL;
+
+	g_return_val_if_fail(PURPLE_IS_ACCOUNT_MANAGER(manager), NULL);
+	g_return_val_if_fail(id != NULL, NULL);
+
+	for(l = manager->accounts; l != NULL; l = l->next) {
+		PurpleAccount *account = PURPLE_ACCOUNT(l->data);
+
+		if(purple_strequal(purple_account_get_id(account), id)) {
+			return account;
+		}
+	}
+
+	return NULL;
+}
+
+PurpleAccount *
 purple_account_manager_find(PurpleAccountManager *manager,
                             const gchar *username, const gchar *protocol_id)
 {
--- a/libpurple/purpleaccountmanager.h	Sun Mar 13 23:59:40 2022 -0500
+++ b/libpurple/purpleaccountmanager.h	Mon Mar 14 01:18:18 2022 -0500
@@ -126,6 +126,19 @@
 GList *purple_account_manager_get_active(PurpleAccountManager *manager);
 
 /**
+ * purple_account_manager_find_by_id:
+ * @manager: The account manager instance.
+ * @id: The id of the account.
+ *
+ * Looks up an account based on its id property.
+ *
+ * Returns: (transfer none): The account if found, otherwise %NULL.
+ *
+ * Since: 3.0.0
+ */
+PurpleAccount *purple_account_manager_find_by_id(PurpleAccountManager *manager, const gchar *id);
+
+/**
  * purple_account_manager_find:
  * @manager: The account manager instance.
  * @username: The username of the account.
--- a/pidgin/meson.build	Sun Mar 13 23:59:40 2022 -0500
+++ b/pidgin/meson.build	Mon Mar 14 01:18:18 2022 -0500
@@ -23,6 +23,7 @@
 	'pidginaccountchooser.c',
 	'pidginaccountfilterconnected.c',
 	'pidginaccountfilterprotocol.c',
+	'pidginaccountsdisabledmenu.c',
 	'pidginaccountsmenu.c',
 	'pidginaccountstore.c',
 	'pidginactiongroup.c',
@@ -85,6 +86,7 @@
 	'pidginaccountchooser.h',
 	'pidginaccountfilterconnected.h',
 	'pidginaccountfilterprotocol.h',
+	'pidginaccountsdisabledmenu.h',
 	'pidginaccountsmenu.h',
 	'pidginaccountstore.h',
 	'pidginactiongroup.h',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginaccountsdisabledmenu.c	Mon Mar 14 01:18:18 2022 -0500
@@ -0,0 +1,126 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <glib/gi18n.h>
+
+#include "pidginaccountsdisabledmenu.h"
+
+#include "pidgincore.h"
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+pidgin_accounts_disabled_menu_refresh_helper(PurpleAccount *account,
+                                             gpointer data)
+{
+	GMenu *menu = data;
+
+	if(!purple_account_get_enabled(account, PIDGIN_UI)) {
+		gchar *label = NULL, *action = NULL;
+		const gchar *account_name = purple_account_get_username(account);
+		const gchar *protocol_name = purple_account_get_protocol_name(account);
+
+		/* translators: This format string is intended to contain the account
+		 * name followed by the protocol name to uniquely identify a specific
+		 * account.
+		 */
+		label = g_strdup_printf(_("%s (%s)"), account_name, protocol_name);
+		action = g_strdup_printf("app.enable-account::%s",
+		                         purple_account_get_id(account));
+
+		g_menu_append(menu, label, action);
+
+		g_free(label);
+		g_free(action);
+	}
+}
+
+static void
+pidgin_accounts_disabled_menu_refresh(GMenu *menu) {
+	PurpleAccountManager *manager = NULL;
+
+	g_menu_remove_all(menu);
+
+	manager = purple_account_manager_get_default();
+	purple_account_manager_foreach(manager,
+	                               pidgin_accounts_disabled_menu_refresh_helper,
+	                               menu);
+
+	if(g_menu_model_get_n_items(G_MENU_MODEL(menu)) == 0) {
+		g_menu_append(menu, _("No disabled accounts"), "disabled");
+	}
+}
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
+static void
+pidgin_accounts_disabled_menu_enabled_cb(G_GNUC_UNUSED PurpleAccount *account,
+                                         gpointer data)
+{
+	pidgin_accounts_disabled_menu_refresh(data);
+}
+
+static void
+pidgin_accounts_disabled_menu_disabled_cb(G_GNUC_UNUSED PurpleAccount *account,
+                                          gpointer data)
+{
+	pidgin_accounts_disabled_menu_refresh(data);
+}
+
+static void
+pidgin_accounts_disabled_menu_weak_notify_cb(G_GNUC_UNUSED gpointer data,
+                                             GObject *obj)
+{
+	purple_signals_disconnect_by_handle(obj);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+GMenu *
+pidgin_accounts_disabled_menu_new(void) {
+	GMenu *menu = NULL;
+	gpointer handle = NULL;
+
+	/* Create the menu and set our instance as data on it so it'll be freed
+	 * when the menu is destroyed.
+	 */
+	menu = g_menu_new();
+	g_object_weak_ref(G_OBJECT(menu),
+	                  pidgin_accounts_disabled_menu_weak_notify_cb, NULL);
+
+	/* Populate ourselves with any accounts that are already disabled. */
+	pidgin_accounts_disabled_menu_refresh(menu);
+
+	/* Wire up the purple signals we care about. */
+	handle = purple_accounts_get_handle();
+	purple_signal_connect(handle, "account-enabled", menu,
+	                      G_CALLBACK(pidgin_accounts_disabled_menu_enabled_cb),
+	                      menu);
+	purple_signal_connect(handle, "account-disabled", menu,
+	                      G_CALLBACK(pidgin_accounts_disabled_menu_disabled_cb),
+	                      menu);
+
+	return menu;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/pidginaccountsdisabledmenu.h	Mon Mar 14 01:18:18 2022 -0500
@@ -0,0 +1,51 @@
+/*
+ * Pidgin - Internet Messenger
+ * Copyright (C) Pidgin Developers <devel@pidgin.im>
+ *
+ * Pidgin is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined(PIDGIN_GLOBAL_HEADER_INSIDE) && !defined(PIDGIN_COMPILATION)
+# error "only <pidgin.h> may be included directly"
+#endif
+
+#ifndef PIDGIN_ACCOUNTS_DISABLED_MENU_H
+#define PIDGIN_ACCOUNTS_DISABLED_MENU_H
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <purple.h>
+
+G_BEGIN_DECLS
+
+/**
+ * pidgin_accounts_disabled_menu_new:
+ *
+ * Creates a [class@Gio.Menu] that will automatically update itself to include
+ * accounts that are disabled in libpurple.
+ *
+ * Returns: (transfer full): The new menu instance.
+ *
+ * Since: 3.0.0
+ */
+GMenu *pidgin_accounts_disabled_menu_new(void);
+
+G_END_DECLS
+
+#endif /* PIDGIN_ACCOUNTS_DISABLED_MENU_H */
\ No newline at end of file
--- a/pidgin/pidginapplication.c	Sun Mar 13 23:59:40 2022 -0500
+++ b/pidgin/pidginapplication.c	Mon Mar 14 01:18:18 2022 -0500
@@ -43,6 +43,7 @@
 #include "gtksavedstatuses.h"
 #include "gtkxfer.h"
 #include "pidginabout.h"
+#include "pidginaccountsdisabledmenu.h"
 #include "pidginconversationwindow.h"
 #include "pidgincore.h"
 #include "pidgindebug.h"
@@ -125,6 +126,18 @@
 	purple_plugins_refresh();
 }
 
+static void
+pidgin_application_populate_dynamic_menus(PidginApplication *application) {
+	GMenu *target = NULL;
+	GMenuModel *source = NULL;
+
+	/* Link the AccountsDisabledMenu into its proper location. */
+	target = gtk_application_get_menu_by_id(GTK_APPLICATION(application),
+	                                        "disabled-accounts");
+	source = pidgin_accounts_disabled_menu_new();
+	g_menu_append_section(target, NULL, source);
+}
+
 /******************************************************************************
  * Actions
  *****************************************************************************/
@@ -245,6 +258,26 @@
 }
 
 static void
+pidgin_application_enable_account(GSimpleAction *simple, GVariant *parameter,
+                                  gpointer data)
+{
+	PurpleAccount *account = NULL;
+	PurpleAccountManager *manager = NULL;
+	const gchar *id = NULL;
+
+	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)) {
+		if(!purple_account_get_enabled(account, PIDGIN_UI)) {
+			purple_account_set_enabled(account, PIDGIN_UI, TRUE);
+		}
+	}
+}
+
+static void
 pidgin_application_file_transfers(GSimpleAction *simple, GVariant *parameter,
                                   gpointer data)
 {
@@ -352,6 +385,10 @@
 		.name = "debug",
 		.activate = pidgin_application_debug,
 	}, {
+		.name = "enable-account",
+		.activate = pidgin_application_enable_account,
+		.parameter_type = "s",
+	}, {
 		.name = "file-transfers",
 		.activate = pidgin_application_file_transfers,
 	}, {
@@ -630,6 +667,9 @@
 		g_list_free(active_accounts);
 	}
 
+	/* Populate our dynamic menus. */
+	pidgin_application_populate_dynamic_menus(PIDGIN_APPLICATION(application));
+
 	/* GTK clears the notification for us when opening the first window, but we
 	 * may have launched with only a status icon, so clear it just in case.
 	 */
--- a/pidgin/resources/gtk/menus.ui	Sun Mar 13 23:59:40 2022 -0500
+++ b/pidgin/resources/gtk/menus.ui	Mon Mar 14 01:18:18 2022 -0500
@@ -184,9 +184,7 @@
         <submenu>
           <attribute name="label" translatable="yes">_Enable Account</attribute>
 
-          <section>
-            <attribute name="id">disabled-accounts</attribute>
-          </section>
+          <section id="disabled-accounts"/>
         </submenu>
       </section>
       <section>
--- a/po/POTFILES.in	Sun Mar 13 23:59:40 2022 -0500
+++ b/po/POTFILES.in	Mon Mar 14 01:18:18 2022 -0500
@@ -336,6 +336,7 @@
 pidgin/pidginaccountchooser.c
 pidgin/pidginaccountfilterconnected.c
 pidgin/pidginaccountfilterprotocol.c
+pidgin/pidginaccountsdisabledmenu.c
 pidgin/pidginaccountsmenu.c
 pidgin/pidginaccountstore.c
 pidgin/pidginactiongroup.c

mercurial