pidgin/pidginaccountsdisabledmenu.c

Tue, 01 Apr 2025 00:12:31 -0500

author
Elliott Sales de Andrade <quantum.analyst@gmail.com>
date
Tue, 01 Apr 2025 00:12:31 -0500
changeset 43220
583158d1e6c2
parent 43062
9d134b69b834
child 43222
e0cc9323ffed
permissions
-rw-r--r--

Convert PidginAccountsDisabledMenu to the list model

This isn't exactly what PIDGIN-18067 requested, but should be a reasonable version of it.

Testing Done:
Started Pidgin with all accounts enabled, and the menu showed the placeholder "No disabled accounts". Disabled an account, and that was replaced by the disabled account. Enabled the account again, and the placeholder text returned.

Also, started Pidgin with an account disabled, and it was in the menu without the placeholder.

Bugs closed: PIDGIN-18067

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

/*
 * 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"

struct _PidginAccountsDisabledMenu {
	GMenuModel parent;

	GListModel *accounts;
};

G_DEFINE_FINAL_TYPE(PidginAccountsDisabledMenu, pidgin_accounts_disabled_menu,
                    G_TYPE_MENU_MODEL)

/******************************************************************************
 * Callbacks
 *****************************************************************************/
static void
pidgin_accounts_disabled_menu_items_changed_cb(GListModel *model,
                                               guint position,
                                               guint removed,
                                               guint added,
                                               gpointer data)
{
	PidginAccountsDisabledMenu *menu = data;
	guint n_items = g_list_model_get_n_items(model);

	if(n_items == 0) {
		/* If every account is enabled, this model will be empty, but we add an
		 * item saying "no disabled accounts".
		 */
		added = 1;
	} else if(n_items == (added - removed) && position == 0) {
		/* In this case, there were no accounts in the model *before*. This
		 * means we need to remove the "no disabled accounts" item that we put
		 * in place when all accounts are enabled.
		 */
		removed = 1;
	}

	g_menu_model_items_changed(G_MENU_MODEL(menu), position, removed, added);
}

/******************************************************************************
 * GMenuModel Implementation
 *****************************************************************************/
static gboolean
pidgin_accounts_disabled_menu_is_mutable(G_GNUC_UNUSED GMenuModel *model) {
	return TRUE;
}

static gboolean
pidgin_accounts_disabled_menu_get_n_items(GMenuModel *model) {
	PidginAccountsDisabledMenu *menu = NULL;

	menu = PIDGIN_ACCOUNTS_DISABLED_MENU(model);

	/* If every account is enabled, we add an item saying "no disabled
	 * accounts", so there's always at least 1.
	 */
	return MAX(1, g_list_model_get_n_items(menu->accounts));
}

static void
pidgin_accounts_disabled_menu_get_item_attributes(GMenuModel *model,
                                                  gint index,
                                                  GHashTable **attributes)
{
	PidginAccountsDisabledMenu *menu = NULL;
	PurpleAccount *account = NULL;
	PurpleProtocol *protocol = NULL;
	GVariant *value = NULL;
	const char *account_name = NULL;
	const char *protocol_name = N_("Unknown");

	menu = PIDGIN_ACCOUNTS_DISABLED_MENU(model);

	/* Create our hash table of attributes to return. */
	*attributes = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
	                                    (GDestroyNotify)g_variant_unref);

	/* If we don't have any disabled accounts, just return a single item,
	 * stating as much.
	 */
	if(g_list_model_get_n_items(menu->accounts) == 0) {
		value = g_variant_new_string(_("No disabled accounts"));
		g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_LABEL,
		                    g_variant_ref_sink(value));

		value = g_variant_new_string("disabled");
		g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_ACTION,
		                    g_variant_ref_sink(value));

		return;
	}

	account = g_list_model_get_item(menu->accounts, index);
	if(account == NULL) {
		return;
	}

	account_name = purple_account_get_username(account);
	protocol = purple_account_get_protocol(account);
	if(PURPLE_IS_PROTOCOL(protocol)) {
		protocol_name = purple_protocol_get_name(protocol);

		value = g_variant_new_printf("%s", purple_protocol_get_icon_name(protocol));
		g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_ICON,
		                    g_variant_ref_sink(value));
	}

	/* translators: This format string is intended to contain the account
	 * name followed by the protocol name to uniquely identify a specific
	 * account.
	 */
	value = g_variant_new_printf(_("%s (%s)"), account_name, _(protocol_name));
	g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_LABEL,
	                    g_variant_ref_sink(value));

	value = g_variant_new_string("app.enable-account");
	g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_ACTION,
	                    g_variant_ref_sink(value));

	value = g_variant_new_printf("%s", purple_account_get_id(account));
	g_hash_table_insert(*attributes, G_MENU_ATTRIBUTE_TARGET,
	                    g_variant_ref_sink(value));

	g_clear_object(&account);
}

static void
pidgin_accounts_disabled_menu_get_item_links(G_GNUC_UNUSED GMenuModel *model,
                                             G_GNUC_UNUSED gint index,
                                             GHashTable **links)
{
	*links = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
	                               g_object_unref);
}

/******************************************************************************
 * GObject Implementation
 *****************************************************************************/
static void
pidgin_accounts_disabled_menu_constructed(GObject *obj) {
	PidginAccountsDisabledMenu *menu = PIDGIN_ACCOUNTS_DISABLED_MENU(obj);
	guint count = 0;

	G_OBJECT_CLASS(pidgin_accounts_disabled_menu_parent_class)->constructed(obj);

	count = g_list_model_get_n_items(menu->accounts);
	g_menu_model_items_changed(G_MENU_MODEL(obj), 0, 0, count);
}

static void
pidgin_accounts_disabled_menu_init(PidginAccountsDisabledMenu *menu) {
	PurpleAccountManager *manager = purple_account_manager_get_default();

	menu->accounts = purple_account_manager_get_disabled_model(manager);
	g_signal_connect_object(menu->accounts, "items-changed",
	                        G_CALLBACK(pidgin_accounts_disabled_menu_items_changed_cb),
	                        menu, G_CONNECT_DEFAULT);
}

static void
pidgin_accounts_disabled_menu_class_init(PidginAccountsDisabledMenuClass *klass) {
	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
	GMenuModelClass *model_class = G_MENU_MODEL_CLASS(klass);

	obj_class->constructed = pidgin_accounts_disabled_menu_constructed;

	model_class->is_mutable = pidgin_accounts_disabled_menu_is_mutable;
	model_class->get_n_items = pidgin_accounts_disabled_menu_get_n_items;
	model_class->get_item_attributes = pidgin_accounts_disabled_menu_get_item_attributes;
	model_class->get_item_links = pidgin_accounts_disabled_menu_get_item_links;
}

/******************************************************************************
 * Public API
 *****************************************************************************/
GMenuModel *
pidgin_accounts_disabled_menu_new(void) {
	return g_object_new(PIDGIN_TYPE_ACCOUNTS_DISABLED_MENU, NULL);
}

mercurial