summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Sales de Andrade <quantum.analyst@gmail.com>2023-02-26 01:19:04 -0600
committerElliott Sales de Andrade <quantum.analyst@gmail.com>2023-02-26 01:19:04 -0600
commit573049e0f76f57cf096c7003fd9a0636d91bdd34 (patch)
tree485982676f25424b660c74e49e61e6a405b46c62
parentcd8dfbe5babceb95a9121a6286d99c857c2c308b (diff)
downloadpidgin-573049e0f76f57cf096c7003fd9a0636d91bdd34.tar.gz
Port list request fields from GtkTreeView to GtkListView
This uses the same "trick" used elsewhere of a plain `GObject` to store the data we need in the list model. Note this does not change datasheets. Testing Done: Opened a request with a list field and confirmed that the selected options were correct upon accepting the dialog. Bugs closed: PIDGIN-17750 Reviewed at https://reviews.imfreedom.org/r/2294/
-rw-r--r--pidgin/gtkrequest.c161
1 files changed, 100 insertions, 61 deletions
diff --git a/pidgin/gtkrequest.c b/pidgin/gtkrequest.c
index 46578a8b4d..9d606e67b6 100644
--- a/pidgin/gtkrequest.c
+++ b/pidgin/gtkrequest.c
@@ -1380,102 +1380,142 @@ create_account_field(PurpleRequestField *field)
}
static void
-select_field_list_item(GtkTreeModel *model, G_GNUC_UNUSED GtkTreePath *path,
- GtkTreeIter *iter, gpointer data)
+setup_list_field_listitem_cb(G_GNUC_UNUSED GtkSignalListItemFactory *self,
+ GtkListItem *item, gpointer data)
{
- PurpleRequestField *field = (PurpleRequestField *)data;
- char *text;
+ PurpleRequestField *field = data;
+ GtkWidget *box = NULL;
+ GtkWidget *widget = NULL;
+
+ box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_list_item_set_child(item, box);
- gtk_tree_model_get(model, iter, 1, &text, -1);
+ widget = gtk_label_new(NULL);
+ gtk_box_append(GTK_BOX(box), widget);
- purple_request_field_list_add_selected(field, text);
- g_free(text);
+ if(purple_request_field_list_has_icons(field)) {
+ widget = gtk_image_new();
+ gtk_box_append(GTK_BOX(box), widget);
+ }
}
static void
-list_field_select_changed_cb(GtkTreeSelection *sel, PurpleRequestField *field)
+bind_list_field_listitem_cb(G_GNUC_UNUSED GtkSignalListItemFactory *self,
+ GtkListItem *item, gpointer data)
{
+ PurpleRequestField *field = data;
+ GtkWidget *box = NULL;
+ GtkWidget *label = NULL;
+ GObject *wrapper = NULL;
+
+ box = gtk_list_item_get_child(item);
+ wrapper = gtk_list_item_get_item(item);
+
+ label = gtk_widget_get_first_child(box);
+ gtk_label_set_text(GTK_LABEL(label), g_object_get_data(wrapper, "text"));
+
+ if(purple_request_field_list_has_icons(field)) {
+ GtkWidget *image = NULL;
+
+ image = gtk_widget_get_last_child(box);
+ gtk_image_set_from_pixbuf(GTK_IMAGE(image),
+ g_object_get_data(wrapper, "pixbuf"));
+ }
+}
+
+static void
+list_field_select_changed_cb(GtkSelectionModel *self,
+ G_GNUC_UNUSED guint position,
+ G_GNUC_UNUSED guint n_items, gpointer data)
+{
+ PurpleRequestField *field = data;
+ GtkBitset *bitset = NULL;
+
purple_request_field_list_clear_selected(field);
- gtk_tree_selection_selected_foreach(sel, select_field_list_item, field);
+ bitset = gtk_selection_model_get_selection(self);
+ n_items = gtk_bitset_get_size(bitset);
+
+ for(guint index = 0; index < n_items; index++) {
+ GObject *wrapper = NULL;
+ const char *text = NULL;
+
+ wrapper = g_list_model_get_item(G_LIST_MODEL(self),
+ gtk_bitset_get_nth(bitset, index));
+
+ text = g_object_get_data(wrapper, "text");
+ purple_request_field_list_add_selected(field, text);
+
+ g_object_unref(wrapper);
+ }
+
+ gtk_bitset_unref(bitset);
}
static GtkWidget *
create_list_field(PurpleRequestField *field)
{
GtkWidget *sw;
- GtkWidget *treeview;
- GtkListStore *store;
- GtkCellRenderer *renderer;
- GtkTreeSelection *sel;
- GtkTreeViewColumn *column;
- GtkTreeIter iter;
+ GtkWidget *listview = NULL;
+ GtkSelectionModel *sel = NULL;
+ GtkListItemFactory *factory = NULL;
+ GListStore *store = NULL;
+ guint index = 0;
GList *l;
gboolean has_icons;
has_icons = purple_request_field_list_has_icons(field);
-
/* Create the list store */
- if (has_icons) {
- store = gtk_list_store_new(3, G_TYPE_POINTER, G_TYPE_STRING, GDK_TYPE_PIXBUF);
+ store = g_list_store_new(G_TYPE_OBJECT);
+ if(purple_request_field_list_get_multi_select(field)) {
+ sel = GTK_SELECTION_MODEL(gtk_multi_selection_new(G_LIST_MODEL(store)));
} else {
- store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING);
+ sel = GTK_SELECTION_MODEL(gtk_single_selection_new(G_LIST_MODEL(store)));
}
- /* Create the tree view */
- treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
- g_object_unref(G_OBJECT(store));
- gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
-
- sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
-
- if (purple_request_field_list_get_multi_select(field))
- gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
-
- column = gtk_tree_view_column_new();
- gtk_tree_view_insert_column(GTK_TREE_VIEW(treeview), column, -1);
+ /* Create the row factory. */
+ factory = gtk_signal_list_item_factory_new();
+ g_signal_connect(factory, "setup", G_CALLBACK(setup_list_field_listitem_cb),
+ field);
+ g_signal_connect(factory, "bind", G_CALLBACK(bind_list_field_listitem_cb),
+ field);
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "text", 1);
+ /* Create the list view */
+ listview = gtk_list_view_new(sel, factory);
if (has_icons) {
- renderer = gtk_cell_renderer_pixbuf_new();
- gtk_tree_view_column_pack_start(column, renderer, TRUE);
- gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", 2);
-
- gtk_widget_set_size_request(treeview, 200, 400);
+ gtk_widget_set_size_request(listview, 200, 400);
}
- for (l = purple_request_field_list_get_items(field); l != NULL; l = l->next)
+ for(index = 0, l = purple_request_field_list_get_items(field);
+ l != NULL;
+ index++, l = l->next)
{
PurpleKeyValuePair *item = l->data;
const char *text = (const char *)item->key;
+ GObject *wrapper = NULL;
+
+ wrapper = g_object_new(G_TYPE_OBJECT, NULL);
+ g_list_store_append(store, wrapper);
- gtk_list_store_append(store, &iter);
+ g_object_set_data(wrapper, "data",
+ purple_request_field_list_get_data(field, text));
+ g_object_set_data_full(wrapper, "text", g_strdup(text), g_free);
- if (has_icons) {
+ if(has_icons) {
const char *icon_path = (const char *)item->value;
GdkPixbuf* pixbuf = NULL;
- if (icon_path)
+ if(icon_path) {
pixbuf = purple_gdk_pixbuf_new_from_file(icon_path);
+ }
- gtk_list_store_set(store, &iter,
- 0, purple_request_field_list_get_data(field, text),
- 1, text,
- 2, pixbuf,
- -1);
- } else {
- gtk_list_store_set(store, &iter,
- 0, purple_request_field_list_get_data(field, text),
- 1, text,
- -1);
+ g_object_set_data_full(wrapper, "pixbuf", pixbuf, g_object_unref);
}
- if (purple_request_field_list_is_selected(field, text)) {
- gtk_tree_selection_select_iter(sel, &iter);
+ if(purple_request_field_list_is_selected(field, text)) {
+ gtk_selection_model_select_item(sel, index, FALSE);
}
}
@@ -1483,18 +1523,17 @@ create_list_field(PurpleRequestField *field)
* We only want to catch changes made by the user, so it's important
* that we wait until after the list is created to connect this
* handler. If we connect the handler before the loop above and
- * there are multiple items selected, then selecting the first iter
- * in the tree causes list_field_select_changed_cb to be triggered
+ * there are multiple items selected, then selecting the first item
+ * in the view causes list_field_select_changed_cb to be triggered
* which clears out the rest of the list of selected items.
*/
- g_signal_connect(G_OBJECT(sel), "changed",
- G_CALLBACK(list_field_select_changed_cb), field);
-
+ g_signal_connect(G_OBJECT(sel), "selection-changed",
+ G_CALLBACK(list_field_select_changed_cb), field);
sw = gtk_scrolled_window_new();
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(sw), treeview);
+ gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(sw), listview);
return sw;
}