diff options
author | Elliott Sales de Andrade <quantum.analyst@gmail.com> | 2023-03-10 17:17:53 -0600 |
---|---|---|
committer | Elliott Sales de Andrade <quantum.analyst@gmail.com> | 2023-03-10 17:17:53 -0600 |
commit | ccbb2c5906dbec65954745ae50fc6dcf32a66151 (patch) | |
tree | f93da8908f05e811b6612c63c086b414da32b936 /libpurple | |
parent | 376b58e87bd054fb09c73edcc31661110d7a2d97 (diff) | |
download | pidgin-ccbb2c5906dbec65954745ae50fc6dcf32a66151.tar.gz |
Convert PurpleRequestFieldList into a GObject
This also does an `hg cp`, though with all the renaming of the parameter names, maybe that wasn't as useful for tracking the diff.
Also could implement `GListModel`, but it takes arbitrary pointers too, so not right now.
Testing Done:
Compiled, and opened Request Fields from the Demo protocol.
Reviewed at https://reviews.imfreedom.org/r/2336/
Diffstat (limited to 'libpurple')
-rw-r--r-- | libpurple/meson.build | 2 | ||||
-rw-r--r-- | libpurple/protocols/demo/purpledemoprotocolactions.c | 29 | ||||
-rw-r--r-- | libpurple/protocols/facebook/util.c | 13 | ||||
-rw-r--r-- | libpurple/protocols/jabber/xdata.c | 16 | ||||
-rw-r--r-- | libpurple/purplerequestfield.c | 224 | ||||
-rw-r--r-- | libpurple/purplerequestfield.h | 135 | ||||
-rw-r--r-- | libpurple/request/purplerequestfieldlist.c | 281 | ||||
-rw-r--r-- | libpurple/request/purplerequestfieldlist.h | 177 |
8 files changed, 496 insertions, 381 deletions
diff --git a/libpurple/meson.build b/libpurple/meson.build index 591b450497..94991b8251 100644 --- a/libpurple/meson.build +++ b/libpurple/meson.build @@ -101,6 +101,7 @@ purple_coresources = [ 'request/purplerequestfieldbool.c', 'request/purplerequestfieldchoice.c', 'request/purplerequestfieldint.c', + 'request/purplerequestfieldlist.c', 'request/purplerequestfieldstring.c', 'request-datasheet.c', 'roomlist.c', @@ -229,6 +230,7 @@ purple_request_headers = [ 'request/purplerequestfieldbool.h', 'request/purplerequestfieldchoice.h', 'request/purplerequestfieldint.h', + 'request/purplerequestfieldlist.h', 'request/purplerequestfieldstring.h', ] diff --git a/libpurple/protocols/demo/purpledemoprotocolactions.c b/libpurple/protocols/demo/purpledemoprotocolactions.c index a3471eeb24..7ab29b5014 100644 --- a/libpurple/protocols/demo/purpledemoprotocolactions.c +++ b/libpurple/protocols/demo/purpledemoprotocolactions.c @@ -370,7 +370,7 @@ purple_demo_protocol_request_fields_ok_cb(G_GNUC_UNUSED gpointer data, PurpleRequestPage *page) { PurpleAccount *account = NULL; - PurpleRequestField *field = NULL; + PurpleRequestFieldList *field = NULL; GList *list = NULL; const char *tmp = NULL; GString *info = NULL; @@ -401,7 +401,8 @@ purple_demo_protocol_request_fields_ok_cb(G_GNUC_UNUSED gpointer data, tmp = (const char *)purple_request_page_get_choice(page, "choice"); g_string_append_printf(info, _("\tChoice: %s\n"), tmp); - field = purple_request_page_get_field(page, "list"); + field = PURPLE_REQUEST_FIELD_LIST(purple_request_page_get_field(page, + "list")); list = purple_request_field_list_get_selected(field); if(list != NULL) { tmp = (const char *)list->data; @@ -410,7 +411,8 @@ purple_demo_protocol_request_fields_ok_cb(G_GNUC_UNUSED gpointer data, } g_string_append_printf(info, _("\tList: %s\n"), tmp); - field = purple_request_page_get_field(page, "multilist"); + field = PURPLE_REQUEST_FIELD_LIST(purple_request_page_get_field(page, + "multilist")); list = purple_request_field_list_get_selected(field); g_string_append(info, _("\tMulti-list: [")); while(list != NULL) { @@ -456,6 +458,7 @@ purple_demo_protocol_request_fields_activate(G_GNUC_UNUSED GSimpleAction *action PurpleRequestGroup *group = NULL; PurpleRequestField *field = NULL; PurpleRequestFieldChoice *choice_field = NULL; + PurpleRequestFieldList *list_field = NULL; GBytes *icon = NULL; gconstpointer icon_data = NULL; gsize icon_len = 0; @@ -529,18 +532,20 @@ purple_demo_protocol_request_fields_activate(G_GNUC_UNUSED GSimpleAction *action purple_request_group_add_field(group, field); field = purple_request_field_list_new("list", _("A list")); - purple_request_field_list_add_icon(field, _("foo"), NULL, "foo"); - purple_request_field_list_add_icon(field, _("bar"), NULL, "bar"); - purple_request_field_list_add_icon(field, _("baz"), NULL, "baz"); - purple_request_field_list_add_icon(field, _("quux"), NULL, "quux"); + list_field = PURPLE_REQUEST_FIELD_LIST(field); + purple_request_field_list_add_icon(list_field, _("foo"), NULL, "foo"); + purple_request_field_list_add_icon(list_field, _("bar"), NULL, "bar"); + purple_request_field_list_add_icon(list_field, _("baz"), NULL, "baz"); + purple_request_field_list_add_icon(list_field, _("quux"), NULL, "quux"); purple_request_group_add_field(group, field); field = purple_request_field_list_new("multilist", _("A multi-select list")); - purple_request_field_list_set_multi_select(field, TRUE); - purple_request_field_list_add_icon(field, _("foo"), NULL, "foo"); - purple_request_field_list_add_icon(field, _("bar"), NULL, "bar"); - purple_request_field_list_add_icon(field, _("baz"), NULL, "baz"); - purple_request_field_list_add_icon(field, _("quux"), NULL, "quux"); + list_field = PURPLE_REQUEST_FIELD_LIST(field); + purple_request_field_list_set_multi_select(list_field, TRUE); + purple_request_field_list_add_icon(list_field, _("foo"), NULL, "foo"); + purple_request_field_list_add_icon(list_field, _("bar"), NULL, "bar"); + purple_request_field_list_add_icon(list_field, _("baz"), NULL, "baz"); + purple_request_field_list_add_icon(list_field, _("quux"), NULL, "quux"); purple_request_group_add_field(group, field); /* This group will contain specialized fields. */ diff --git a/libpurple/protocols/facebook/util.c b/libpurple/protocols/facebook/util.c index 9eb99271e1..4590e746dc 100644 --- a/libpurple/protocols/facebook/util.c +++ b/libpurple/protocols/facebook/util.c @@ -302,14 +302,15 @@ fb_util_request_buddy_ok(gpointer *request_data, PurpleRequestPage *page) { gpointer data = request_data[2]; GSList *ret = NULL; PurpleBuddy *bdy; - PurpleRequestField *field; + PurpleRequestFieldList *field; if (func == NULL) { g_free(request_data); return; } - field = purple_request_page_get_field(page, "buddy"); + field = PURPLE_REQUEST_FIELD_LIST(purple_request_page_get_field(page, + "buddy")); select = purple_request_field_list_get_selected(field); for (l = select; l != NULL; l = l->next) { @@ -380,6 +381,7 @@ fb_util_request_buddy(PurpleConnection *gc, const gchar *title, PurpleAccount *acct; PurpleRequestCommonParameters *cpar; PurpleRequestField *field; + PurpleRequestFieldList *list; PurpleRequestGroup *group; PurpleRequestPage *page; @@ -397,7 +399,8 @@ fb_util_request_buddy(PurpleConnection *gc, const gchar *title, purple_request_page_add_group(page, group); field = purple_request_field_list_new("buddy", NULL); - purple_request_field_list_set_multi_select(field, multi); + list = PURPLE_REQUEST_FIELD_LIST(field); + purple_request_field_list_set_multi_select(list, multi); purple_request_field_set_required(field, TRUE); purple_request_group_add_field(group, field); @@ -405,7 +408,7 @@ fb_util_request_buddy(PurpleConnection *gc, const gchar *title, name = purple_buddy_get_name(l->data); alias = purple_buddy_get_alias(l->data); str = g_strdup_printf("%s (%s)", alias, name); - purple_request_field_list_add_icon(field, str, NULL, l->data); + purple_request_field_list_add_icon(list, str, NULL, l->data); g_free(str); } @@ -416,7 +419,7 @@ fb_util_request_buddy(PurpleConnection *gc, const gchar *title, items = g_list_append(items, str); } - purple_request_field_list_set_selected(field, items); + purple_request_field_list_set_selected(list, items); g_slist_free(buddies); g_list_free_full(items, g_free); diff --git a/libpurple/protocols/jabber/xdata.c b/libpurple/protocols/jabber/xdata.c index 1cc3c78ed9..db1f1a536f 100644 --- a/libpurple/protocols/jabber/xdata.c +++ b/libpurple/protocols/jabber/xdata.c @@ -116,13 +116,14 @@ jabber_x_data_ok_cb(struct jabber_x_data_data *data, PurpleRequestPage *page) { case JABBER_X_DATA_LIST_SINGLE: case JABBER_X_DATA_LIST_MULTI: { - GList *selected = purple_request_field_list_get_selected(field); + PurpleRequestFieldList *lfield = PURPLE_REQUEST_FIELD_LIST(field); + GList *selected = purple_request_field_list_get_selected(lfield); char *value; fieldnode = purple_xmlnode_new_child(result, "field"); purple_xmlnode_set_attrib(fieldnode, "var", id); while(selected) { - value = purple_request_field_list_get_data(field, selected->data); + value = purple_request_field_list_get_data(lfield, selected->data); valuenode = purple_xmlnode_new_child(fieldnode, "value"); if(value) purple_xmlnode_insert_data(valuenode, value, -1); @@ -265,13 +266,15 @@ void *jabber_x_data_request_with_actions(JabberStream *js, PurpleXmlNode *packet g_string_free(str, TRUE); } else if(purple_strequal(type, "list-single") || purple_strequal(type, "list-multi")) { + PurpleRequestFieldList *list_field = NULL; PurpleXmlNode *optnode; GList *selected = NULL; field = purple_request_field_list_new(var, label); + list_field = PURPLE_REQUEST_FIELD_LIST(field); if(purple_strequal(type, "list-multi")) { - purple_request_field_list_set_multi_select(field, TRUE); + purple_request_field_list_set_multi_select(list_field, TRUE); g_hash_table_replace(data->fields, g_strdup(var), GINT_TO_POINTER(JABBER_X_DATA_LIST_MULTI)); } else { @@ -302,9 +305,10 @@ void *jabber_x_data_request_with_actions(JabberStream *js, PurpleXmlNode *packet data->values = g_slist_prepend(data->values, value); - purple_request_field_list_add_icon(field, lbl, NULL, value); - if(g_list_find_custom(selected, value, (GCompareFunc)strcmp)) - purple_request_field_list_add_selected(field, lbl); + purple_request_field_list_add_icon(list_field, lbl, NULL, value); + if(g_list_find_custom(selected, value, (GCompareFunc)strcmp)) { + purple_request_field_list_add_selected(list_field, lbl); + } } purple_request_group_add_field(group, field); diff --git a/libpurple/purplerequestfield.c b/libpurple/purplerequestfield.c index 43088f92a8..0037d59109 100644 --- a/libpurple/purplerequestfield.c +++ b/libpurple/purplerequestfield.c @@ -42,16 +42,6 @@ typedef struct { union { struct { - GList *items; - gboolean has_icons; - GHashTable *item_data; - GList *selected; - GHashTable *selected_table; - - gboolean multiple_selection; - } list; - - struct { unsigned int scale_x; unsigned int scale_y; char *buffer; @@ -206,13 +196,7 @@ purple_request_field_finalize(GObject *obj) { g_free(priv->type_hint); g_free(priv->tooltip); - if(priv->type == PURPLE_REQUEST_FIELD_LIST) { - g_list_free_full(priv->u.list.items, - (GDestroyNotify)purple_key_value_pair_free); - g_list_free_full(priv->u.list.selected, g_free); - g_hash_table_destroy(priv->u.list.item_data); - g_hash_table_destroy(priv->u.list.selected_table); - } else if(priv->type == PURPLE_REQUEST_FIELD_DATASHEET) { + if(priv->type == PURPLE_REQUEST_FIELD_DATASHEET) { purple_request_datasheet_free(priv->u.datasheet.sheet); } else if(priv->type == PURPLE_REQUEST_FIELD_IMAGE) { g_free(priv->u.image.buffer); @@ -651,212 +635,6 @@ purple_request_field_is_sensitive(PurpleRequestField *field) } PurpleRequestField * -purple_request_field_list_new(const char *id, const char *text) -{ - PurpleRequestField *field; - PurpleRequestFieldPrivate *priv = NULL; - - g_return_val_if_fail(id != NULL, NULL); - - field = purple_request_field_new(id, text, PURPLE_REQUEST_FIELD_LIST); - priv = purple_request_field_get_instance_private(field); - - priv->u.list.item_data = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - - priv->u.list.selected_table = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, NULL); - - return field; -} - -void -purple_request_field_list_set_multi_select(PurpleRequestField *field, - gboolean multi_select) -{ - PurpleRequestFieldPrivate *priv = NULL; - - g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field)); - - priv = purple_request_field_get_instance_private(field); - g_return_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST); - - priv->u.list.multiple_selection = multi_select; -} - -gboolean -purple_request_field_list_get_multi_select(PurpleRequestField *field) { - PurpleRequestFieldPrivate *priv = NULL; - - g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE); - - priv = purple_request_field_get_instance_private(field); - g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST, FALSE); - - return priv->u.list.multiple_selection; -} - -void * -purple_request_field_list_get_data(PurpleRequestField *field, const char *text) -{ - PurpleRequestFieldPrivate *priv = NULL; - - g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL); - g_return_val_if_fail(text != NULL, NULL); - - priv = purple_request_field_get_instance_private(field); - g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST, NULL); - - return g_hash_table_lookup(priv->u.list.item_data, text); -} - -void -purple_request_field_list_add_icon(PurpleRequestField *field, const char *item, const char* icon_path, - void *data) -{ - PurpleKeyValuePair *kvp; - PurpleRequestFieldPrivate *priv = NULL; - - g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field)); - g_return_if_fail(item != NULL); - g_return_if_fail(data != NULL); - - priv = purple_request_field_get_instance_private(field); - g_return_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST); - - priv->u.list.has_icons = priv->u.list.has_icons || (icon_path != NULL); - kvp = purple_key_value_pair_new_full(item, g_strdup(icon_path), g_free); - priv->u.list.items = g_list_append(priv->u.list.items, kvp); - g_hash_table_insert(priv->u.list.item_data, g_strdup(item), data); -} - -void -purple_request_field_list_add_selected(PurpleRequestField *field, const char *item) -{ - PurpleRequestFieldPrivate *priv = NULL; - - g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field)); - g_return_if_fail(item != NULL); - - priv = purple_request_field_get_instance_private(field); - g_return_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST); - - if(!purple_request_field_list_get_multi_select(field) && - priv->u.list.selected != NULL) - { - purple_debug_warning("request", - "More than one item added to non-multi-select " - "field %s\n", - purple_request_field_get_id(field)); - return; - } - - priv->u.list.selected = g_list_append(priv->u.list.selected, - g_strdup(item)); - - g_hash_table_add(priv->u.list.selected_table, g_strdup(item)); -} - -void -purple_request_field_list_clear_selected(PurpleRequestField *field) -{ - PurpleRequestFieldPrivate *priv = NULL; - - g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field)); - - priv = purple_request_field_get_instance_private(field); - g_return_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST); - - if(priv->u.list.selected != NULL) { - g_list_free_full(priv->u.list.selected, g_free); - priv->u.list.selected = NULL; - } - - g_hash_table_remove_all(priv->u.list.selected_table); -} - -void -purple_request_field_list_set_selected(PurpleRequestField *field, GList *items) -{ - PurpleRequestFieldPrivate *priv = NULL; - GList *l; - - g_return_if_fail(PURPLE_IS_REQUEST_FIELD(field)); - g_return_if_fail(items != NULL); - - priv = purple_request_field_get_instance_private(field); - g_return_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST); - - purple_request_field_list_clear_selected(field); - - if (!purple_request_field_list_get_multi_select(field) && items->next) { - purple_debug_warning("request", - "More than one item added to non-multi-select " - "field %s\n", - purple_request_field_get_id(field)); - return; - } - - for (l = items; l != NULL; l = l->next) { - char *selected = l->data; - priv->u.list.selected = g_list_append(priv->u.list.selected, - g_strdup(selected)); - g_hash_table_add(priv->u.list.selected_table, g_strdup(selected)); - } -} - -gboolean -purple_request_field_list_is_selected(PurpleRequestField *field, - const char *item) -{ - PurpleRequestFieldPrivate *priv = NULL; - - g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE); - g_return_val_if_fail(item != NULL, FALSE); - - priv = purple_request_field_get_instance_private(field); - g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST, FALSE); - - return g_hash_table_contains(priv->u.list.selected_table, item); -} - -GList * -purple_request_field_list_get_selected(PurpleRequestField *field) { - PurpleRequestFieldPrivate *priv = NULL; - - g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL); - - priv = purple_request_field_get_instance_private(field); - g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST, NULL); - - return priv->u.list.selected; -} - -GList * -purple_request_field_list_get_items(PurpleRequestField *field) { - PurpleRequestFieldPrivate *priv = NULL; - - g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), NULL); - - priv = purple_request_field_get_instance_private(field); - g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST, NULL); - - return priv->u.list.items; -} - -gboolean -purple_request_field_list_has_icons(PurpleRequestField *field) { - PurpleRequestFieldPrivate *priv = NULL; - - g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD(field), FALSE); - - priv = purple_request_field_get_instance_private(field); - g_return_val_if_fail(priv->type == PURPLE_REQUEST_FIELD_LIST, FALSE); - - return priv->u.list.has_icons; -} - -PurpleRequestField * purple_request_field_label_new(const char *id, const char *text) { PurpleRequestField *field; diff --git a/libpurple/purplerequestfield.h b/libpurple/purplerequestfield.h index efd18b3c35..3d3c38b06e 100644 --- a/libpurple/purplerequestfield.h +++ b/libpurple/purplerequestfield.h @@ -64,7 +64,6 @@ struct _PurpleRequestFieldClass { /** * PurpleRequestFieldType: * @PURPLE_REQUEST_FIELD_NONE: No field. - * @PURPLE_REQUEST_FIELD_LIST: List field. * @PURPLE_REQUEST_FIELD_LABEL: Label field. * @PURPLE_REQUEST_FIELD_IMAGE: Image field. * @PURPLE_REQUEST_FIELD_DATASHEET: Datasheet field. @@ -74,7 +73,6 @@ struct _PurpleRequestFieldClass { typedef enum { PURPLE_REQUEST_FIELD_NONE, - PURPLE_REQUEST_FIELD_LIST, PURPLE_REQUEST_FIELD_LABEL, PURPLE_REQUEST_FIELD_IMAGE, PURPLE_REQUEST_FIELD_DATASHEET @@ -311,139 +309,6 @@ void purple_request_field_set_sensitive(PurpleRequestField *field, gboolean purple_request_field_is_sensitive(PurpleRequestField *field); /**************************************************************************/ -/* List Field API */ -/**************************************************************************/ - -/** - * purple_request_field_list_new: - * @id: The field ID. - * @text: The optional label of the field. - * - * Creates a multiple list item field. - * - * Returns: (transfer full): The new field. - */ -PurpleRequestField *purple_request_field_list_new(const char *id, const char *text); - -/** - * purple_request_field_list_set_multi_select: - * @field: The list field. - * @multi_select: TRUE if multiple selection is enabled, - * or FALSE otherwise. - * - * Sets whether or not a list field allows multiple selection. - */ -void purple_request_field_list_set_multi_select(PurpleRequestField *field, - gboolean multi_select); - -/** - * purple_request_field_list_get_multi_select: - * @field: The list field. - * - * Returns whether or not a list field allows multiple selection. - * - * Returns: TRUE if multiple selection is enabled, or FALSE otherwise. - */ -gboolean purple_request_field_list_get_multi_select(PurpleRequestField *field); - -/** - * purple_request_field_list_get_data: - * @field: The list field. - * @text: The item text. - * - * Returns the data for a particular item. - * - * Returns: The data associated with the item. - */ -void *purple_request_field_list_get_data(PurpleRequestField *field, const char *text); - -/** - * purple_request_field_list_add_icon: - * @field: The list field. - * @item: The list item. - * @icon_path: The path to icon file, or %NULL for no icon. - * @data: The associated data. - * - * Adds an item to a list field. - */ -void purple_request_field_list_add_icon(PurpleRequestField *field, - const char *item, const char* icon_path, void* data); - -/** - * purple_request_field_list_add_selected: - * @field: The field. - * @item: The item to add. - * - * Adds a selected item to the list field. - */ -void purple_request_field_list_add_selected(PurpleRequestField *field, - const char *item); - -/** - * purple_request_field_list_clear_selected: - * @field: The field. - * - * Clears the list of selected items in a list field. - */ -void purple_request_field_list_clear_selected(PurpleRequestField *field); - -/** - * purple_request_field_list_set_selected: - * @field: The field. - * @items: (element-type utf8) (transfer none): The list of selected items. - * - * Sets a list of selected items in a list field. - */ -void purple_request_field_list_set_selected(PurpleRequestField *field, - GList *items); - -/** - * purple_request_field_list_is_selected: - * @field: The field. - * @item: The item. - * - * Returns whether or not a particular item is selected in a list field. - * - * Returns: TRUE if the item is selected. FALSE otherwise. - */ -gboolean purple_request_field_list_is_selected(PurpleRequestField *field, const char *item); - -/** - * purple_request_field_list_get_selected: - * @field: The field. - * - * Returns a list of selected items in a list field. - * - * To retrieve the data for each item, use - * purple_request_field_list_get_data(). - * - * Returns: (element-type utf8) (transfer none): The list of selected items. - */ -GList *purple_request_field_list_get_selected(PurpleRequestField *field); - -/** - * purple_request_field_list_get_items: - * @field: The field. - * - * Returns a list of items in a list field. - * - * Returns: (element-type PurpleKeyValuePair) (transfer none): The list of items. - */ -GList *purple_request_field_list_get_items(PurpleRequestField *field); - -/** - * purple_request_field_list_has_icons: - * @field: The field. - * - * Indicates if list field has icons. - * - * Returns: TRUE if list field has icons, FALSE otherwise. - * - * Since: 3.0.0 - */ -gboolean purple_request_field_list_has_icons(PurpleRequestField *field); - -/**************************************************************************/ /* Label Field API */ /**************************************************************************/ diff --git a/libpurple/request/purplerequestfieldlist.c b/libpurple/request/purplerequestfieldlist.c new file mode 100644 index 0000000000..b31450065d --- /dev/null +++ b/libpurple/request/purplerequestfieldlist.c @@ -0,0 +1,281 @@ +/* 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 <glib/gi18n-lib.h> + +#include "glibcompat.h" +#include "purplerequestfield.h" +#include "request/purplerequestfieldlist.h" +#include "debug.h" +#include "purplekeyvaluepair.h" + +struct _PurpleRequestFieldList { + PurpleRequestField parent; + + GList *items; + gboolean has_icons; + GHashTable *item_data; + GList *selected; + GHashTable *selected_table; + + gboolean multiple_selection; +}; + +enum { + PROP_0, + PROP_MULTI_SELECT, + N_PROPERTIES, +}; +static GParamSpec *properties[N_PROPERTIES] = {NULL, }; + +/****************************************************************************** + * GObject Implementation + *****************************************************************************/ +G_DEFINE_TYPE(PurpleRequestFieldList, purple_request_field_list, + PURPLE_TYPE_REQUEST_FIELD) + +static void +purple_request_field_list_get_property(GObject *obj, guint param_id, GValue *value, + GParamSpec *pspec) +{ + PurpleRequestFieldList *field = PURPLE_REQUEST_FIELD_LIST(obj); + + switch(param_id) { + case PROP_MULTI_SELECT: + g_value_set_boolean(value, + purple_request_field_list_get_multi_select(field)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_request_field_list_set_property(GObject *obj, guint param_id, + const GValue *value, GParamSpec *pspec) +{ + PurpleRequestFieldList *field = PURPLE_REQUEST_FIELD_LIST(obj); + + switch(param_id) { + case PROP_MULTI_SELECT: + purple_request_field_list_set_multi_select(field, + g_value_get_boolean(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); + break; + } +} + +static void +purple_request_field_list_finalize(GObject *obj) { + PurpleRequestFieldList *field = PURPLE_REQUEST_FIELD_LIST(obj); + + g_list_free_full(field->items, (GDestroyNotify)purple_key_value_pair_free); + g_list_free_full(field->selected, g_free); + g_hash_table_destroy(field->item_data); + g_hash_table_destroy(field->selected_table); + + G_OBJECT_CLASS(purple_request_field_list_parent_class)->finalize(obj); +} + +static void +purple_request_field_list_init(PurpleRequestFieldList *field) { + field->item_data = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + + field->selected_table = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); +} + +static void +purple_request_field_list_class_init(PurpleRequestFieldListClass *klass) { + GObjectClass *obj_class = G_OBJECT_CLASS(klass); + + obj_class->finalize = purple_request_field_list_finalize; + obj_class->get_property = purple_request_field_list_get_property; + obj_class->set_property = purple_request_field_list_set_property; + + /** + * PurpleRequestFieldChoice:multi-select: + * + * Whether the field should allow multiple selections. + * + * Since: 3.0.0 + */ + properties[PROP_MULTI_SELECT] = g_param_spec_boolean( + "multi-select", "multi-select", + "Whether the field should allow multiple selections.", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(obj_class, N_PROPERTIES, properties); +} + +/****************************************************************************** + * Public API + *****************************************************************************/ +PurpleRequestField * +purple_request_field_list_new(const char *id, const char *text) { + g_return_val_if_fail(id != NULL, NULL); + + return g_object_new(PURPLE_TYPE_REQUEST_FIELD_LIST, + "id", id, + "label", text, + NULL); +} + +void +purple_request_field_list_set_multi_select(PurpleRequestFieldList *field, + gboolean multi_select) +{ + g_return_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field)); + + if(field->multiple_selection == multi_select) { + return; + } + + field->multiple_selection = multi_select; + + g_object_notify_by_pspec(G_OBJECT(field), properties[PROP_MULTI_SELECT]); +} + +gboolean +purple_request_field_list_get_multi_select(PurpleRequestFieldList *field) { + g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field), FALSE); + + return field->multiple_selection; +} + +gpointer +purple_request_field_list_get_data(PurpleRequestFieldList *field, + const char *text) +{ + g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field), NULL); + g_return_val_if_fail(text != NULL, NULL); + + return g_hash_table_lookup(field->item_data, text); +} + +void +purple_request_field_list_add_icon(PurpleRequestFieldList *field, + const char *item, const char *icon_path, + gpointer data) +{ + PurpleKeyValuePair *kvp; + + g_return_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field)); + g_return_if_fail(item != NULL); + g_return_if_fail(data != NULL); + + field->has_icons = field->has_icons || (icon_path != NULL); + kvp = purple_key_value_pair_new_full(item, g_strdup(icon_path), g_free); + field->items = g_list_append(field->items, kvp); + g_hash_table_insert(field->item_data, g_strdup(item), data); +} + +void +purple_request_field_list_add_selected(PurpleRequestFieldList *field, + const char *item) +{ + g_return_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field)); + g_return_if_fail(item != NULL); + + if(!field->multiple_selection && field->selected != NULL) { + purple_debug_warning("request", + "More than one item added to non-multi-select " + "field %s\n", + purple_request_field_get_id(PURPLE_REQUEST_FIELD(field))); + return; + } + + field->selected = g_list_append(field->selected, g_strdup(item)); + + g_hash_table_add(field->selected_table, g_strdup(item)); +} + +void +purple_request_field_list_clear_selected(PurpleRequestFieldList *field) { + g_return_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field)); + + g_list_free_full(field->selected, g_free); + field->selected = NULL; + + g_hash_table_remove_all(field->selected_table); +} + +void +purple_request_field_list_set_selected(PurpleRequestFieldList *field, + GList *items) +{ + GList *l; + + g_return_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field)); + g_return_if_fail(items != NULL); + + purple_request_field_list_clear_selected(field); + + if (!purple_request_field_list_get_multi_select(field) && items->next) { + purple_debug_warning("request", + "More than one item added to non-multi-select " + "field %s\n", + purple_request_field_get_id(PURPLE_REQUEST_FIELD(field))); + return; + } + + for (l = items; l != NULL; l = l->next) { + char *selected = l->data; + field->selected = g_list_append(field->selected, g_strdup(selected)); + g_hash_table_add(field->selected_table, g_strdup(selected)); + } +} + +gboolean +purple_request_field_list_is_selected(PurpleRequestFieldList *field, + const char *item) +{ + g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field), FALSE); + g_return_val_if_fail(item != NULL, FALSE); + + return g_hash_table_contains(field->selected_table, item); +} + +GList * +purple_request_field_list_get_selected(PurpleRequestFieldList *field) { + g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field), NULL); + + return field->selected; +} + +GList * +purple_request_field_list_get_items(PurpleRequestFieldList *field) { + g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field), NULL); + + return field->items; +} + +gboolean +purple_request_field_list_has_icons(PurpleRequestFieldList *field) { + g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_LIST(field), FALSE); + + return field->has_icons; +} diff --git a/libpurple/request/purplerequestfieldlist.h b/libpurple/request/purplerequestfieldlist.h new file mode 100644 index 0000000000..8ba5057e77 --- /dev/null +++ b/libpurple/request/purplerequestfieldlist.h @@ -0,0 +1,177 @@ +/* + * Purple - Internet Messaging Library + * Copyright (C) Pidgin Developers <devel@pidgin.im> + * + * 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, see <https://www.gnu.org/licenses/>. + */ + +#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION) +# error "only <purple.h> may be included directly" +#endif + +#ifndef PURPLE_REQUEST_FIELD_LIST_H +#define PURPLE_REQUEST_FIELD_LIST_H + +#include <stdlib.h> + +#include <glib.h> +#include <glib-object.h> + +/** + * PurpleRequestFieldList: + * + * A list request field. + */ +typedef struct _PurpleRequestFieldList PurpleRequestFieldList; + +#include "purplerequestfield.h" + +G_BEGIN_DECLS + +#define PURPLE_TYPE_REQUEST_FIELD_LIST (purple_request_field_list_get_type()) +G_DECLARE_FINAL_TYPE(PurpleRequestFieldList, purple_request_field_list, + PURPLE, REQUEST_FIELD_LIST, PurpleRequestField) + +/** + * purple_request_field_list_new: + * @id: The field ID. + * @text: The optional label of the field. + * + * Creates a multiple list item field. + * + * Returns: (transfer full): The new field. + */ +PurpleRequestField *purple_request_field_list_new(const char *id, const char *text); + +/** + * purple_request_field_list_set_multi_select: + * @field: The list field. + * @multi_select: TRUE if multiple selection is enabled, + * or FALSE otherwise. + * + * Sets whether or not a list field allows multiple selection. + */ +void purple_request_field_list_set_multi_select(PurpleRequestFieldList *field, gboolean multi_select); + +/** + * purple_request_field_list_get_multi_select: + * @field: The list field. + * + * Returns whether or not a list field allows multiple selection. + * + * Returns: TRUE if multiple selection is enabled, or FALSE otherwise. + */ +gboolean purple_request_field_list_get_multi_select(PurpleRequestFieldList *field); + +/** + * purple_request_field_list_get_data: + * @field: The list field. + * @text: The item text. + * + * Returns the data for a particular item. + * + * Returns: The data associated with the item. + */ +gpointer purple_request_field_list_get_data(PurpleRequestFieldList *field, const char *text); + +/** + * purple_request_field_list_add_icon: + * @field: The list field. + * @item: The list item. + * @icon_path: The path to icon file, or %NULL for no icon. + * @data: The associated data. + * + * Adds an item to a list field. + */ +void purple_request_field_list_add_icon(PurpleRequestFieldList *field, const char *item, const char *icon_path, gpointer data); + +/** + * purple_request_field_list_add_selected: + * @field: The field. + * @item: The item to add. + * + * Adds a selected item to the list field. + */ +void purple_request_field_list_add_selected(PurpleRequestFieldList *field, const char *item); + +/** + * purple_request_field_list_clear_selected: + * @field: The field. + * + * Clears the list of selected items in a list field. + */ +void purple_request_field_list_clear_selected(PurpleRequestFieldList *field); + +/** + * purple_request_field_list_set_selected: + * @field: The field. + * @items: (element-type utf8) (transfer none): The list of selected items. + * + * Sets a list of selected items in a list field. + */ +void purple_request_field_list_set_selected(PurpleRequestFieldList *field, GList *items); + +/** + * purple_request_field_list_is_selected: + * @field: The field. + * @item: The item. + * + * Returns whether or not a particular item is selected in a list field. + * + * Returns: TRUE if the item is selected. FALSE otherwise. + */ +gboolean purple_request_field_list_is_selected(PurpleRequestFieldList *field, const char *item); + +/** + * purple_request_field_list_get_selected: + * @field: The field. + * + * Returns a list of selected items in a list field. + * + * To retrieve the data for each item, use + * purple_request_field_list_get_data(). + * + * Returns: (element-type utf8) (transfer none): The list of selected items. + */ +GList *purple_request_field_list_get_selected(PurpleRequestFieldList *field); + +/** + * purple_request_field_list_get_items: + * @field: The field. + * + * Returns a list of items in a list field. + * + * Returns: (element-type PurpleKeyValuePair) (transfer none): The list of items. + */ +GList *purple_request_field_list_get_items(PurpleRequestFieldList *field); + +/** + * purple_request_field_list_has_icons: + * @field: The field. + * + * Indicates if list field has icons. + * + * Returns: TRUE if list field has icons, FALSE otherwise. + * + * Since: 3.0.0 + */ +gboolean purple_request_field_list_has_icons(PurpleRequestFieldList *field); + +G_END_DECLS + +#endif /* PURPLE_REQUEST_FIELD_LIST_H */ |