pidgin/pidginmooddialog.c

Mon, 22 Aug 2022 21:40:04 -0500

author
Elliott Sales de Andrade <quantum.analyst@gmail.com>
date
Mon, 22 Aug 2022 21:40:04 -0500
branch
gtk4
changeset 41567
517ac516af27
parent 41454
7cc69bde919d
child 41851
64d7e69bff25
permissions
-rw-r--r--

Inline pidgin_make_scrollable

We need to change it for GTK4, and there are few enough that it can be inlined. Eventually, that code might be a `.ui` anyway.

Testing Done:
Compile only.

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

/*
 * pidgin
 *
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 */

#include "pidgin/pidginmooddialog.h"

#include <glib/gi18n-lib.h>

#include "config.h"

/*< private >
 * pidgin_mood_update_status:
 * @account: The #PurpleAccount instance.
 * @mood: The id of the new mood.
 * @text: The new status text.
 *
 * Updates the current status for @account with the given @mood and @text.
 */
static void
update_status_with_mood(PurpleAccount *account, const gchar *mood,
                        const gchar *text)
{
	if (mood && *mood) {
		if (text) {
			purple_account_set_status(account, "mood", TRUE,
			                          PURPLE_MOOD_NAME, mood,
				    				  PURPLE_MOOD_COMMENT, text,
			                          NULL);
		} else {
			purple_account_set_status(account, "mood", TRUE,
			                          PURPLE_MOOD_NAME, mood,
			                          NULL);
		}
	} else {
		purple_account_set_status(account, "mood", FALSE, NULL);
	}
}

/*< private
 * pidgin_mood_edit_cb:
 * @connection: The #PurpleConnection instance.
 * @fields: The #PurpleRequestFields
 *
 * This a callback function for when the request dialog has been accepted.
 */
static void
pidgin_mood_dialog_edit_cb(PurpleConnection *connection,
                           PurpleRequestFields *fields)
{
	PurpleRequestField *mood_field = NULL;
	GList *l = NULL;
	const gchar *mood = NULL;

	mood_field = purple_request_fields_get_field(fields, "mood");
	l = purple_request_field_list_get_selected(mood_field);

	if(l == NULL) {
		return;
	}

	mood = purple_request_field_list_get_data(mood_field, l->data);

	if(connection != NULL) {
		PurpleAccount *account = purple_connection_get_account(connection);
		PurpleConnectionFlags flags;
		const gchar *text = NULL;

		flags = purple_connection_get_flags(connection);
		if (flags & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES) {
			PurpleRequestField *text_field = NULL;

			text_field = purple_request_fields_get_field(fields, "text");
			text = purple_request_field_string_get_value(text_field);
		} else {
			text = NULL;
		}

		update_status_with_mood(account, mood, text);
	} else {
		PurpleAccountManager *manager = purple_account_manager_get_default();
		GList *accounts = purple_account_manager_get_all(manager);

		for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
			PurpleAccount *account = (PurpleAccount *) accounts->data;

			connection = purple_account_get_connection(account);
			if(PURPLE_IS_CONNECTION(connection)) {
				PurpleConnectionFlags flags;

				flags = purple_connection_get_flags(connection);
				if(flags & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS) {
					update_status_with_mood(account, mood, NULL);
				}
			}
		}
	}
}

/*< private >
 * pidgin_mood_get_global_moods:
 *
 * Returns an array of all global moods.
 *
 * This function should be in libpurple, and it needs a lot of cleanup.  It
 * should probably also be returning a GList of moods as that's easier to deal
 * with.
 *
 * Also, there is non-deterministic behavior here that the order of the
 * returned moods depends purely on the order that the accounts where connected
 * in.  This is probably okay, but we should look at fixing that somehow.
 *
 * Returns: (transfer full): A list of all global moods.
 */
static PurpleMood *
pidgin_mood_get_global_moods(void) {
	PurpleAccountManager *manager = NULL;
	GHashTable *global_moods = NULL;
	GHashTable *mood_counts = NULL;
	GList *accounts = NULL;
	PurpleMood *result = NULL;
	GList *out_moods = NULL;
	int i = 0;
	int num_accounts = 0;

	global_moods = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
	mood_counts = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);

	manager = purple_account_manager_get_default();
	accounts = purple_account_manager_get_enabled(manager);
	for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
		PurpleAccount *account = (PurpleAccount *) accounts->data;
		if (purple_account_is_connected(account)) {
			PurpleConnection *gc = purple_account_get_connection(account);

			if (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOODS) {
				PurpleProtocol *protocol = purple_connection_get_protocol(gc);
				PurpleMood *mood = NULL;

				for (mood = purple_protocol_client_get_moods(PURPLE_PROTOCOL_CLIENT(protocol), account) ;
				    mood->mood != NULL ; mood++) {
					int mood_count =
							GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood));

					if (!g_hash_table_contains(global_moods, mood->mood)) {
						g_hash_table_insert(global_moods, (gpointer)mood->mood, mood);
					}
					g_hash_table_insert(mood_counts, (gpointer)mood->mood,
					    GINT_TO_POINTER(mood_count + 1));
				}

				num_accounts++;
			}
		}
	}

	result = g_new0(PurpleMood, g_hash_table_size(global_moods) + 1);

	out_moods = g_hash_table_get_values(global_moods);
	while (out_moods) {
		PurpleMood *mood = (PurpleMood *) out_moods->data;
		int in_num_accounts =
			GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood));

		if (in_num_accounts == num_accounts) {
			/* mood is present in all accounts supporting moods */
			result[i].mood = mood->mood;
			result[i].description = mood->description;
			i++;
		}
		out_moods = g_list_delete_link(out_moods, out_moods);
	}

	g_hash_table_destroy(global_moods);
	g_hash_table_destroy(mood_counts);

	return result;
}

/*< private >
 * pidgin_mood_get_global_status:
 *
 * Get the currently selected mood name for all mood support accounts.  If no
 * mood is set, or accounts have different moods then %NULL is returned.
 *
 * Returns: The currently selected mood name or %NULL if a mood is not set, or
 *          accounts are using different moods.
 */
static const gchar *
pidgin_mood_get_global_status(void) {
	PurpleAccountManager *manager = NULL;
	GList *accounts = NULL;
	const gchar *found_mood = NULL;

	manager = purple_account_manager_get_default();
	accounts = purple_account_manager_get_enabled(manager);
	for (; accounts ; accounts = g_list_delete_link(accounts, accounts)) {
		PurpleAccount *account = (PurpleAccount *) accounts->data;

		if (purple_account_is_connected(account) &&
		    (purple_connection_get_flags(purple_account_get_connection(account)) &
		     PURPLE_CONNECTION_FLAG_SUPPORT_MOODS)) {
			PurplePresence *presence = purple_account_get_presence(account);
			PurpleStatus *status = purple_presence_get_status(presence, "mood");
			const gchar *curr_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);

			if (found_mood != NULL && !purple_strequal(curr_mood, found_mood)) {
				/* found a different mood */
				found_mood = NULL;
				break;
			} else {
				found_mood = curr_mood;
			}
		}
	}

	return found_mood;
}

/******************************************************************************
 * Public API
 *****************************************************************************/
void
pidgin_mood_dialog_show(PurpleAccount *account) {
	const gchar *current_mood;
	PurpleRequestFields *fields;
	PurpleRequestFieldGroup *g;
	PurpleRequestField *f;
	PurpleConnection *gc = NULL;
	PurpleProtocol *protocol = NULL;
	PurpleMood *mood = NULL;
	PurpleMood *global_moods = NULL;

	if (account) {
		PurplePresence *presence = purple_account_get_presence(account);
		PurpleStatus *status = purple_presence_get_status(presence, "mood");
		gc = purple_account_get_connection(account);
		g_return_if_fail(purple_connection_get_protocol(gc) != NULL);
		protocol = purple_connection_get_protocol(gc);
		current_mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
	} else {
		current_mood = pidgin_mood_get_global_status();
	}

	fields = purple_request_fields_new();
	g = purple_request_field_group_new(NULL);
	f = purple_request_field_list_new("mood", _("Please select your mood from the list"));

	purple_request_field_list_add_icon(f, _("None"), NULL, "");
	if (current_mood == NULL)
		purple_request_field_list_add_selected(f, _("None"));

	/* TODO: rlaager wants this sorted. */
	/* TODO: darkrain wants it sorted post-translation */
	if (account && PURPLE_IS_PROTOCOL_CLIENT(protocol)) {
		mood = purple_protocol_client_get_moods(PURPLE_PROTOCOL_CLIENT(protocol), account);
	}

	if(mood == NULL) {
		mood = global_moods = pidgin_mood_get_global_moods();
	}

	for ( ; mood != NULL && mood->mood != NULL ; mood++) {
		char *path;

		if (mood->description == NULL) {
			continue;
		}

		path = pidgin_mood_get_icon_path(mood->mood);
		purple_request_field_list_add_icon(f, _(mood->description),
				path, (gpointer)mood->mood);
		g_free(path);

		if (current_mood && purple_strequal(current_mood, mood->mood))
			purple_request_field_list_add_selected(f, _(mood->description));
	}
	purple_request_field_group_add_field(g, f);

	purple_request_fields_add_group(fields, g);

	/* if the connection allows setting a mood message */
	if (gc && (purple_connection_get_flags(gc) & PURPLE_CONNECTION_FLAG_SUPPORT_MOOD_MESSAGES)) {
		g = purple_request_field_group_new(NULL);
		f = purple_request_field_string_new("text",
		    _("Message (optional)"), NULL, FALSE);
		purple_request_field_group_add_field(g, f);
		purple_request_fields_add_group(fields, g);
	}

	purple_request_fields(gc, _("Edit User Mood"), _("Edit User Mood"),
	                      NULL, fields,
	                      _("OK"), G_CALLBACK(pidgin_mood_dialog_edit_cb),
	                      _("Cancel"), NULL,
	                      purple_request_cpar_from_connection(gc), gc);

	g_free(global_moods);
}

gchar *
pidgin_mood_get_icon_path(const gchar *mood) {
	gchar *path;

	if(purple_strequal(mood, "busy")) {
		path = g_build_filename(PURPLE_DATADIR, "pidgin", "icons",
			"hicolor", "16x16", "status", "user-busy.png", NULL);
	} else if(purple_strequal(mood, "hiptop")) {
		path = g_build_filename(PURPLE_DATADIR, "pidgin", "icons",
			"hicolor", "16x16", "emblems", "emblem-hiptop.png",
			NULL);
	} else {
		gchar *filename = g_strdup_printf("%s.png", mood);
		path = g_build_filename(PURPLE_DATADIR, "pixmaps", "pidgin",
			"emotes", "small", filename, NULL);
		g_free(filename);
	}

	return path;
}

mercurial