libpurple/roomlist.c

Fri, 12 Aug 2022 03:44:34 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Fri, 12 Aug 2022 03:44:34 -0500
branch
gtk4
changeset 41560
2579a5138f0c
parent 41351
a2cd8d6d9483
child 41685
ca22b00972d4
permissions
-rw-r--r--

A bunch of random fixes for the the gtk4 branch

Testing Done:
Compiled

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

/* purple
 *
 * Purple 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 "internal.h"

#include "account.h"
#include "connection.h"
#include "debug.h"
#include "purpleprotocolfactory.h"
#include "roomlist.h"
#include "server.h"

/* This must be after roomlist.h otherwise you'll get an include cycle. */
#include "purpleprotocolroomlist.h"

/*
 * Private data for a room list.
 */
typedef struct {
	PurpleAccount *account;  /* The account this list belongs to. */
	GList *rooms;            /* The list of rooms.                */
	gboolean in_progress;    /* The listing is in progress.       */
} PurpleRoomlistPrivate;

/* Room list property enums */
enum
{
	PROP_0,
	PROP_ACCOUNT,
	PROP_IN_PROGRESS,
	PROP_LAST
};

static GParamSpec *properties[PROP_LAST];
static PurpleRoomlistUiOps *ops = NULL;

G_DEFINE_TYPE_WITH_PRIVATE(PurpleRoomlist, purple_roomlist, G_TYPE_OBJECT);

/**************************************************************************/
/* Room List API                                                          */
/**************************************************************************/

void purple_roomlist_show_with_account(PurpleAccount *account)
{
	if (ops && ops->show_with_account)
		ops->show_with_account(account);
}

PurpleAccount *purple_roomlist_get_account(PurpleRoomlist *list)
{
	PurpleRoomlistPrivate *priv = NULL;

	g_return_val_if_fail(PURPLE_IS_ROOMLIST(list), NULL);

	priv = purple_roomlist_get_instance_private(list);
	return priv->account;
}

void purple_roomlist_set_in_progress(PurpleRoomlist *list, gboolean in_progress)
{
	PurpleRoomlistPrivate *priv = NULL;

	g_return_if_fail(PURPLE_IS_ROOMLIST(list));

	priv = purple_roomlist_get_instance_private(list);
	priv->in_progress = in_progress;

	g_object_notify_by_pspec(G_OBJECT(list), properties[PROP_IN_PROGRESS]);
}

gboolean purple_roomlist_get_in_progress(PurpleRoomlist *list)
{
	PurpleRoomlistPrivate *priv = NULL;

	g_return_val_if_fail(PURPLE_IS_ROOMLIST(list), FALSE);

	priv = purple_roomlist_get_instance_private(list);
	return priv->in_progress;
}

void purple_roomlist_room_add(PurpleRoomlist *list, PurpleRoomlistRoom *room)
{
	PurpleRoomlistPrivate *priv = NULL;

	g_return_if_fail(PURPLE_IS_ROOMLIST(list));
	g_return_if_fail(room != NULL);

	priv = purple_roomlist_get_instance_private(list);
	priv->rooms = g_list_append(priv->rooms, room);

	if (ops && ops->add_room)
		ops->add_room(list, room);
}

PurpleRoomlist *purple_roomlist_get_list(PurpleConnection *gc)
{
	PurpleProtocol *protocol = NULL;

	g_return_val_if_fail(PURPLE_IS_CONNECTION(gc), NULL);
	g_return_val_if_fail(PURPLE_CONNECTION_IS_CONNECTED(gc), NULL);

	protocol = purple_connection_get_protocol(gc);

	if(PURPLE_IS_PROTOCOL_ROOMLIST(protocol)) {
		return purple_protocol_roomlist_get_list(PURPLE_PROTOCOL_ROOMLIST(protocol),
		                                         gc);
	}

	return NULL;
}

void purple_roomlist_cancel_get_list(PurpleRoomlist *list)
{
	PurpleRoomlistPrivate *priv = NULL;
	PurpleProtocol *protocol = NULL;
	PurpleConnection *gc;

	g_return_if_fail(PURPLE_IS_ROOMLIST(list));

	priv = purple_roomlist_get_instance_private(list);

	gc = purple_account_get_connection(priv->account);
	g_return_if_fail(PURPLE_IS_CONNECTION(gc));

	if(gc)
		protocol = purple_connection_get_protocol(gc);

	if(PURPLE_IS_PROTOCOL_ROOMLIST(protocol)) {
		purple_protocol_roomlist_cancel(PURPLE_PROTOCOL_ROOMLIST(protocol), list);
	}
}

void
purple_roomlist_join_room(PurpleRoomlist *list, PurpleRoomlistRoom *room) {
	PurpleRoomlistPrivate *priv = NULL;
	PurpleConnection *connection = NULL;
	GHashTable *components = NULL, *adjusted = NULL;
	GHashTableIter iter;
	const gchar *name = NULL;
	gpointer key, value;

	g_return_if_fail(PURPLE_IS_ROOMLIST(list));
	g_return_if_fail(PURPLE_IS_ROOMLIST_ROOM(room));

	priv = purple_roomlist_get_instance_private(list);

	connection = purple_account_get_connection(priv->account);
	if(connection == NULL) {
		return;
	}

	components = purple_roomlist_room_get_components(room);

	/* Make a copy of the components as we make sure the name is included. */
	adjusted = g_hash_table_new(g_str_hash, g_str_equal);
	g_hash_table_iter_init(&iter, components);
	while(g_hash_table_iter_next(&iter, &key, &value)) {
		g_hash_table_insert(adjusted, key, value);
	}

	name = purple_roomlist_room_get_name(room);
	g_hash_table_replace(adjusted, "name", (gpointer)name);

	purple_serv_join_chat(connection, adjusted);

	g_hash_table_destroy(adjusted);
}

/**************************************************************************/
/* Room List GObject code                                                 */
/**************************************************************************/

/* Set method for GObject properties */
static void
purple_roomlist_set_property(GObject *obj, guint param_id, const GValue *value,
		GParamSpec *pspec)
{
	PurpleRoomlist *list = PURPLE_ROOMLIST(obj);
	PurpleRoomlistPrivate *priv =
			purple_roomlist_get_instance_private(list);

	switch (param_id) {
		case PROP_ACCOUNT:
			priv->account = g_value_get_object(value);
			break;
		case PROP_IN_PROGRESS:
			purple_roomlist_set_in_progress(list, g_value_get_boolean(value));
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
			break;
	}
}

/* Get method for GObject properties */
static void
purple_roomlist_get_property(GObject *obj, guint param_id, GValue *value,
		GParamSpec *pspec)
{
	PurpleRoomlist *list = PURPLE_ROOMLIST(obj);

	switch (param_id) {
		case PROP_ACCOUNT:
			g_value_set_object(value, purple_roomlist_get_account(list));
			break;
		case PROP_IN_PROGRESS:
			g_value_set_boolean(value, purple_roomlist_get_in_progress(list));
			break;
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
			break;
	}
}

static void
purple_roomlist_init(PurpleRoomlist *list)
{
}

/* Called when done constructing */
static void
purple_roomlist_constructed(GObject *object)
{
	PurpleRoomlist *list = PURPLE_ROOMLIST(object);

	G_OBJECT_CLASS(purple_roomlist_parent_class)->constructed(object);

	if (ops && ops->create)
		ops->create(list);
}

/* GObject finalize function */
static void
purple_roomlist_finalize(GObject *object)
{
	PurpleRoomlist *list = PURPLE_ROOMLIST(object);
	PurpleRoomlistPrivate *priv =
			purple_roomlist_get_instance_private(list);

	purple_debug_misc("roomlist", "destroying list %p\n", list);

	g_list_free_full(priv->rooms, g_object_unref);

	G_OBJECT_CLASS(purple_roomlist_parent_class)->finalize(object);
}

/* Class initializer function */
static void
purple_roomlist_class_init(PurpleRoomlistClass *klass)
{
	GObjectClass *obj_class = G_OBJECT_CLASS(klass);

	obj_class->finalize = purple_roomlist_finalize;
	obj_class->constructed = purple_roomlist_constructed;

	/* Setup properties */
	obj_class->get_property = purple_roomlist_get_property;
	obj_class->set_property = purple_roomlist_set_property;

	properties[PROP_ACCOUNT] = g_param_spec_object("account", "Account",
				"The account for the room list.",
				PURPLE_TYPE_ACCOUNT,
				G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
				G_PARAM_STATIC_STRINGS);

	properties[PROP_IN_PROGRESS] = g_param_spec_boolean("in-progress",
				"In progress",
				"Whether the room list is being fetched.", FALSE,
				G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);

	g_object_class_install_properties(obj_class, PROP_LAST, properties);
}

PurpleRoomlist *purple_roomlist_new(PurpleAccount *account)
{
	return g_object_new(PURPLE_TYPE_ROOMLIST,
		"account", account,
		NULL
	);
}

/**************************************************************************/
/* UI Registration Functions                                              */
/**************************************************************************/

void purple_roomlist_set_ui_ops(PurpleRoomlistUiOps *ui_ops)
{
	ops = ui_ops;
}

PurpleRoomlistUiOps *purple_roomlist_get_ui_ops(void)
{
	return ops;
}

/**************************************************************************
 * UI Ops GBoxed code
 **************************************************************************/

static PurpleRoomlistUiOps *
purple_roomlist_ui_ops_copy(PurpleRoomlistUiOps *ops)
{
	PurpleRoomlistUiOps *ops_new;

	g_return_val_if_fail(ops != NULL, NULL);

	ops_new = g_new(PurpleRoomlistUiOps, 1);
	*ops_new = *ops;

	return ops_new;
}

GType
purple_roomlist_ui_ops_get_type(void)
{
	static GType type = 0;

	if (type == 0) {
		type = g_boxed_type_register_static("PurpleRoomlistUiOps",
				(GBoxedCopyFunc)purple_roomlist_ui_ops_copy,
				(GBoxedFreeFunc)g_free);
	}

	return type;
}

mercurial