Mon, 14 Mar 2022 01:18:18 -0500
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/
--- 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