diff options
author | Gary Kramlich <grim@reaperworld.com> | 2022-05-02 21:57:35 -0500 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2022-05-02 21:57:35 -0500 |
commit | 5846c056422c18ab516c60b44eb399c877ffc824 (patch) | |
tree | 24a21fa95b14044766af8cf633f0132fd31e0252 /libpurple/roomlist.c | |
parent | becd2ccaa215780aec0aed16b00b18b89c15102d (diff) | |
download | pidgin-5846c056422c18ab516c60b44eb399c877ffc824.tar.gz |
Rework the way roomlists work so we can more easily port them to GTK4
Testing Done:
Joined rooms on XMPP via the buttons, double clicking, and the context menu.
Reviewed at https://reviews.imfreedom.org/r/1293/
Diffstat (limited to 'libpurple/roomlist.c')
-rw-r--r-- | libpurple/roomlist.c | 346 |
1 files changed, 25 insertions, 321 deletions
diff --git a/libpurple/roomlist.c b/libpurple/roomlist.c index 4697f26d78..2bcea641a7 100644 --- a/libpurple/roomlist.c +++ b/libpurple/roomlist.c @@ -36,38 +36,15 @@ */ typedef struct { PurpleAccount *account; /* The account this list belongs to. */ - GList *fields; /* The fields. */ GList *rooms; /* The list of rooms. */ gboolean in_progress; /* The listing is in progress. */ } PurpleRoomlistPrivate; -/* - * Represents a room. - */ -struct _PurpleRoomlistRoom { - PurpleRoomlistRoomType type; /* The type of room. */ - gchar *name; /* The name of the room. */ - GList *fields; /* Other fields. */ - PurpleRoomlistRoom *parent; /* The parent room, or NULL. */ - gboolean expanded_once; /* A flag the UI uses to avoid multiple expand protocol cbs. */ -}; - -/* - * A field a room might have. - */ -struct _PurpleRoomlistField { - PurpleRoomlistFieldType type; /* The type of field. */ - gchar *label; /* The i18n user displayed name of the field. */ - gchar *name; /* The internal name of the field. */ - gboolean hidden; /* Hidden? */ -}; - /* Room list property enums */ enum { PROP_0, PROP_ACCOUNT, - PROP_FIELDS, PROP_IN_PROGRESS, PROP_LAST }; @@ -77,10 +54,6 @@ static PurpleRoomlistUiOps *ops = NULL; G_DEFINE_TYPE_WITH_PRIVATE(PurpleRoomlist, purple_roomlist, G_TYPE_OBJECT); -static void purple_roomlist_room_free(PurpleRoomlistRoom *r); -static void purple_roomlist_field_free(PurpleRoomlistField *f); -static void purple_roomlist_room_destroy(PurpleRoomlist *list, PurpleRoomlistRoom *r); - /**************************************************************************/ /* Room List API */ /**************************************************************************/ @@ -101,21 +74,6 @@ PurpleAccount *purple_roomlist_get_account(PurpleRoomlist *list) return priv->account; } -void purple_roomlist_set_fields(PurpleRoomlist *list, GList *fields) -{ - PurpleRoomlistPrivate *priv = NULL; - - g_return_if_fail(PURPLE_IS_ROOMLIST(list)); - - priv = purple_roomlist_get_instance_private(list); - priv->fields = fields; - - if (ops && ops->set_fields) - ops->set_fields(list, fields); - - g_object_notify_by_pspec(G_OBJECT(list), properties[PROP_FIELDS]); -} - void purple_roomlist_set_in_progress(PurpleRoomlist *list, gboolean in_progress) { PurpleRoomlistPrivate *priv = NULL; @@ -190,39 +148,40 @@ void purple_roomlist_cancel_get_list(PurpleRoomlist *list) } } -void purple_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category) -{ +void +purple_roomlist_join_room(PurpleRoomlist *roomlist, PurpleRoomlistRoom *room) { PurpleRoomlistPrivate *priv = NULL; - PurpleProtocol *protocol = NULL; - PurpleConnection *gc; + 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(category != NULL); - g_return_if_fail(category->type & PURPLE_ROOMLIST_ROOMTYPE_CATEGORY); - - priv = purple_roomlist_get_instance_private(list); + g_return_if_fail(PURPLE_IS_ROOMLIST(roomlist)); + g_return_if_fail(PURPLE_IS_ROOMLIST_ROOM(room)); - gc = purple_account_get_connection(priv->account); - g_return_if_fail(PURPLE_IS_CONNECTION(gc)); + priv = purple_roomlist_get_instance_private(roomlist); - if(gc) { - protocol = purple_connection_get_protocol(gc); + connection = purple_account_get_connection(priv->account); + if(connection == NULL) { + return; } - if(PURPLE_IS_PROTOCOL_ROOMLIST(protocol)) { - purple_protocol_roomlist_expand_category(PURPLE_PROTOCOL_ROOMLIST(protocol), - list, category); + 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); } -} -GList * purple_roomlist_get_fields(PurpleRoomlist *list) -{ - PurpleRoomlistPrivate *priv = NULL; + name = purple_roomlist_room_get_name(room); + g_hash_table_replace(adjusted, "name", (gpointer)name); - g_return_val_if_fail(PURPLE_IS_ROOMLIST(list), NULL); + purple_serv_join_chat(connection, adjusted); - priv = purple_roomlist_get_instance_private(list); - return priv->fields; + g_hash_table_destroy(adjusted); } /**************************************************************************/ @@ -242,9 +201,6 @@ purple_roomlist_set_property(GObject *obj, guint param_id, const GValue *value, case PROP_ACCOUNT: priv->account = g_value_get_object(value); break; - case PROP_FIELDS: - purple_roomlist_set_fields(list, g_value_get_pointer(value)); - break; case PROP_IN_PROGRESS: purple_roomlist_set_in_progress(list, g_value_get_boolean(value)); break; @@ -265,9 +221,6 @@ purple_roomlist_get_property(GObject *obj, guint param_id, GValue *value, case PROP_ACCOUNT: g_value_set_object(value, purple_roomlist_get_account(list)); break; - case PROP_FIELDS: - g_value_set_pointer(value, purple_roomlist_get_fields(list)); - break; case PROP_IN_PROGRESS: g_value_set_boolean(value, purple_roomlist_get_in_progress(list)); break; @@ -301,17 +254,10 @@ purple_roomlist_finalize(GObject *object) PurpleRoomlist *list = PURPLE_ROOMLIST(object); PurpleRoomlistPrivate *priv = purple_roomlist_get_instance_private(list); - GList *l; purple_debug_misc("roomlist", "destroying list %p\n", list); - for (l = priv->rooms; l; l = l->next) { - PurpleRoomlistRoom *r = l->data; - purple_roomlist_room_destroy(list, r); - } - g_list_free(priv->rooms); - - g_list_free_full(priv->fields, (GDestroyNotify)purple_roomlist_field_free); + g_list_free_full(priv->rooms, g_object_unref); G_OBJECT_CLASS(purple_roomlist_parent_class)->finalize(object); } @@ -335,10 +281,6 @@ purple_roomlist_class_init(PurpleRoomlistClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - properties[PROP_FIELDS] = g_param_spec_pointer("fields", "Fields", - "The list of fields for a roomlist.", - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - properties[PROP_IN_PROGRESS] = g_param_spec_boolean("in-progress", "In progress", "Whether the room list is being fetched.", FALSE, @@ -356,244 +298,6 @@ PurpleRoomlist *purple_roomlist_new(PurpleAccount *account) } /**************************************************************************/ -/* Room API */ -/**************************************************************************/ - -PurpleRoomlistRoom *purple_roomlist_room_new(PurpleRoomlistRoomType type, const gchar *name, - PurpleRoomlistRoom *parent) -{ - PurpleRoomlistRoom *room; - - g_return_val_if_fail(name != NULL, NULL); - - room = g_new0(PurpleRoomlistRoom, 1); - room->type = type; - room->name = g_strdup(name); - room->parent = parent; - - return room; -} - -void purple_roomlist_room_add_field(PurpleRoomlist *list, PurpleRoomlistRoom *room, gconstpointer field) -{ - PurpleRoomlistPrivate *priv = NULL; - PurpleRoomlistField *f; - - g_return_if_fail(PURPLE_IS_ROOMLIST(list)); - g_return_if_fail(room != NULL); - - priv = purple_roomlist_get_instance_private(list); - g_return_if_fail(priv->fields != NULL); - - /* If this is the first call for this room, grab the first field in - * the Roomlist's fields. Otherwise, grab the field that is one - * more than the number of fields already present for the room. - * (This works because g_list_nth_data() is zero-indexed and - * g_list_length() is one-indexed.) */ - if (!room->fields) - f = priv->fields->data; - else - f = g_list_nth_data(priv->fields, g_list_length(room->fields)); - - g_return_if_fail(f != NULL); - - switch(f->type) { - case PURPLE_ROOMLIST_FIELD_STRING: - room->fields = g_list_append(room->fields, g_strdup(field)); - break; - case PURPLE_ROOMLIST_FIELD_BOOL: - case PURPLE_ROOMLIST_FIELD_INT: - room->fields = g_list_append(room->fields, GINT_TO_POINTER(field)); - break; - } - - g_object_notify_by_pspec(G_OBJECT(list), properties[PROP_FIELDS]); -} - -void purple_roomlist_room_join(PurpleRoomlist *list, PurpleRoomlistRoom *room) -{ - PurpleRoomlistPrivate *priv = NULL; - GHashTable *components; - GList *l, *j; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_IS_ROOMLIST(list)); - g_return_if_fail(room != NULL); - - priv = purple_roomlist_get_instance_private(list); - - gc = purple_account_get_connection(priv->account); - if (!gc) - return; - - components = g_hash_table_new(g_str_hash, g_str_equal); - - g_hash_table_replace(components, "name", room->name); - for (l = priv->fields, j = room->fields; l && j; l = l->next, j = j->next) { - PurpleRoomlistField *f = l->data; - - g_hash_table_replace(components, f->name, j->data); - } - - purple_serv_join_chat(gc, components); - - g_hash_table_destroy(components); -} - -PurpleRoomlistRoomType purple_roomlist_room_get_room_type(PurpleRoomlistRoom *room) -{ - return room->type; -} - -const char * purple_roomlist_room_get_name(PurpleRoomlistRoom *room) -{ - return room->name; -} - -PurpleRoomlistRoom * purple_roomlist_room_get_parent(PurpleRoomlistRoom *room) -{ - return room->parent; -} - -gboolean purple_roomlist_room_get_expanded_once(PurpleRoomlistRoom *room) -{ - g_return_val_if_fail(room != NULL, FALSE); - - return room->expanded_once; -} - -void purple_roomlist_room_set_expanded_once(PurpleRoomlistRoom *room, gboolean expanded_once) -{ - g_return_if_fail(room != NULL); - - room->expanded_once = expanded_once; -} - -GList *purple_roomlist_room_get_fields(PurpleRoomlistRoom *room) -{ - return room->fields; -} - -static void purple_roomlist_room_destroy(PurpleRoomlist *list, PurpleRoomlistRoom *r) -{ - PurpleRoomlistPrivate *priv = - purple_roomlist_get_instance_private(list); - GList *l, *j; - - for (l = priv->fields, j = r->fields; l && j; l = l->next, j = j->next) { - PurpleRoomlistField *f = l->data; - if (f->type == PURPLE_ROOMLIST_FIELD_STRING) - g_free(j->data); - } - - purple_roomlist_room_free(r); -} - -/**************************************************************************/ -/* Room GBoxed code */ -/**************************************************************************/ - -static PurpleRoomlistRoom *purple_roomlist_room_copy(PurpleRoomlistRoom *r) -{ - g_return_val_if_fail(r != NULL, NULL); - - return purple_roomlist_room_new(r->type, r->name, r->parent); -} - -static void purple_roomlist_room_free(PurpleRoomlistRoom *r) -{ - g_return_if_fail(r != NULL); - - g_list_free(r->fields); - g_free(r->name); - g_free(r); -} - -GType purple_roomlist_room_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - type = g_boxed_type_register_static("PurpleRoomlistRoom", - (GBoxedCopyFunc)purple_roomlist_room_copy, - (GBoxedFreeFunc)purple_roomlist_room_free); - } - - return type; -} - -/**************************************************************************/ -/* Room Field API */ -/**************************************************************************/ - -PurpleRoomlistField *purple_roomlist_field_new(PurpleRoomlistFieldType type, - const gchar *label, const gchar *name, - gboolean hidden) -{ - PurpleRoomlistField *f; - - g_return_val_if_fail(label != NULL, NULL); - g_return_val_if_fail(name != NULL, NULL); - - f = g_new0(PurpleRoomlistField, 1); - - f->type = type; - f->label = g_strdup(label); - f->name = g_strdup(name); - f->hidden = hidden; - - return f; -} - -PurpleRoomlistFieldType purple_roomlist_field_get_field_type(PurpleRoomlistField *field) -{ - return field->type; -} - -const char * purple_roomlist_field_get_label(PurpleRoomlistField *field) -{ - return field->label; -} - -gboolean purple_roomlist_field_get_hidden(PurpleRoomlistField *field) -{ - return field->hidden; -} - -/**************************************************************************/ -/* Room Field GBoxed code */ -/**************************************************************************/ - -static PurpleRoomlistField *purple_roomlist_field_copy(PurpleRoomlistField *f) -{ - g_return_val_if_fail(f != NULL, NULL); - - return purple_roomlist_field_new(f->type, f->label, f->name, f->hidden); -} - -static void purple_roomlist_field_free(PurpleRoomlistField *f) -{ - g_return_if_fail(f != NULL); - - g_free(f->label); - g_free(f->name); - g_free(f); -} - -GType purple_roomlist_field_get_type(void) -{ - static GType type = 0; - - if (type == 0) { - type = g_boxed_type_register_static("PurpleRoomlistField", - (GBoxedCopyFunc)purple_roomlist_field_copy, - (GBoxedFreeFunc)purple_roomlist_field_free); - } - - return type; -} - -/**************************************************************************/ /* UI Registration Functions */ /**************************************************************************/ |