Remove the screen name auto-completion API

Sat, 30 Dec 2023 18:22:52 -0600

author
Gary Kramlich <grim@reaperworld.com>
date
Sat, 30 Dec 2023 18:22:52 -0600
changeset 42550
d745bb34f491
parent 42549
4157c07b840c
child 42551
ba39c2657d78

Remove the screen name auto-completion API

This isn't compatible with PurpleContactInfo and GTK has deprecated entry
completion in GTK 4 with the intent to remove it in GTK 5 and they don't
mention a replacement.

Testing Done:
Consulted with the turtles and ran the program.

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

ChangeLog.API file | annotate | diff | comparison | revisions
pidgin/gtkrequest.c file | annotate | diff | comparison | revisions
pidgin/gtkutils.c file | annotate | diff | comparison | revisions
pidgin/gtkutils.h file | annotate | diff | comparison | revisions
--- a/ChangeLog.API	Sat Dec 30 01:50:32 2023 -0600
+++ b/ChangeLog.API	Sat Dec 30 18:22:52 2023 -0600
@@ -990,6 +990,8 @@
 		* pidgin_blist_visibility_manager_add
 		* pidgin_blist_visibility_manager_remove
 		* PidginBlistLayout
+		* PidginBuddyCompletionEntry
+		* PidginFilterBuddyCompletionEntryFunc
 		* pidgin_buddy_icon_chooser_new
 		* pidgin_buddy_icon_get_scale_size
 		* PidginBuddyList.connection_errors
@@ -1150,6 +1152,7 @@
 		* pidgin_request_add_block
 		* pidgin_save_accels
 		* pidgin_save_accels_cb
+		* pidgin_screenname_autocomplete_default_filter
 		* PidginScrollBook
 		* pidgin_scroll_book_new
 		* pidgin_scroll_book_get_notebook
@@ -1160,6 +1163,7 @@
 		* pidgin_set_sensitive_if_input
 		* pidgin_set_urgent, use gtk_window_set_urgency_hint instead.
 		* pidgin_set_xfer_dialog
+		* pidgin_setup_screenname_autocomplete
 		* pidgin_setup_screenname_autocomplete_with_filter
 		* PidginSmiley
 		* pidgin_smiley_add_to_list
--- a/pidgin/gtkrequest.c	Sat Dec 30 01:50:32 2023 -0600
+++ b/pidgin/gtkrequest.c	Sat Dec 30 18:22:52 2023 -0600
@@ -1960,28 +1960,8 @@
 			g_object_unref(field);
 		}
 
-		/* Link autocompletion of entry widgets to account if we found any. */
-		if(username_widgets != NULL && account_hint != NULL) {
-
-			while(username_widgets != NULL) {
-				PurpleKeyValuePair *pair = username_widgets->data;
-				const char *type_hint = pair->key;
-				GtkWidget *entry = pair->value;
-				gboolean show_all;
-
-				show_all = purple_strequal(type_hint, "screenname-all");
-				pidgin_setup_screenname_autocomplete(entry, account_hint,
-				                                     pidgin_screenname_autocomplete_default_filter,
-				                                     GINT_TO_POINTER(show_all));
-
-				purple_key_value_pair_free(pair);
-				username_widgets = g_slist_delete_link(username_widgets,
-				                                       username_widgets);
-			}
-		} else {
-			g_slist_free_full(username_widgets,
-			                  (GDestroyNotify)purple_key_value_pair_free);
-		}
+		g_slist_free_full(username_widgets,
+		                  (GDestroyNotify)purple_key_value_pair_free);
 
 		g_object_unref(group);
 	}
--- a/pidgin/gtkutils.c	Sat Dec 30 01:50:32 2023 -0600
+++ b/pidgin/gtkutils.c	Sat Dec 30 18:22:52 2023 -0600
@@ -21,12 +21,7 @@
 
 #include <purpleconfig.h>
 
-#include <errno.h>
-
 #include <glib/gi18n-lib.h>
-#include <glib/gstdio.h>
-
-#include <gdk/gdkkeysyms.h>
 
 #include <purple.h>
 
@@ -35,46 +30,8 @@
 #  include <shellapi.h>
 #endif /*_WIN32*/
 
-#include "gtkdialogs.h"
 #include "gtkrequest.h"
 #include "gtkutils.h"
-#include "pidginaccountchooser.h"
-#include "pidgincore.h"
-
-/******************************************************************************
- * Enums
- *****************************************************************************/
-
-enum {
-	AOP_ICON_COLUMN,
-	AOP_NAME_COLUMN,
-	AOP_DATA_COLUMN,
-	AOP_COLUMN_COUNT
-};
-
-enum {
-	COMPLETION_DISPLAYED_COLUMN,  /* displayed completion value */
-	COMPLETION_BUDDY_COLUMN,      /* buddy name */
-	COMPLETION_NORMALIZED_COLUMN, /* UTF-8 normalized & casefolded buddy name */
-	COMPLETION_COMPARISON_COLUMN, /* UTF-8 normalized & casefolded value for comparison */
-	COMPLETION_ACCOUNT_COLUMN,    /* account */
-	COMPLETION_COLUMN_COUNT
-};
-
-/******************************************************************************
- * Structs
- *****************************************************************************/
-
-typedef struct
-{
-	GtkWidget *entry;
-	GtkWidget *chooser;
-
-	PidginFilterBuddyCompletionEntryFunc filter_func;
-	gpointer filter_func_user_data;
-
-	GtkListStore *store;
-} PidginCompletionData;
 
 /******************************************************************************
  * Code
@@ -134,300 +91,6 @@
 	                               label, NULL, -1);
 }
 
-static gboolean
-buddyname_completion_match_func(GtkEntryCompletion *completion,
-                                const char *key, GtkTreeIter *iter,
-                                G_GNUC_UNUSED gpointer user_data)
-{
-	GtkTreeModel *model;
-	GValue val1;
-	GValue val2;
-	const char *tmp;
-
-	model = gtk_entry_completion_get_model(completion);
-
-	val1.g_type = 0;
-	gtk_tree_model_get_value(model, iter, COMPLETION_NORMALIZED_COLUMN, &val1);
-	tmp = g_value_get_string(&val1);
-	if (tmp != NULL && g_str_has_prefix(tmp, key)) {
-		g_value_unset(&val1);
-		return TRUE;
-	}
-	g_value_unset(&val1);
-
-	val2.g_type = 0;
-	gtk_tree_model_get_value(model, iter, COMPLETION_COMPARISON_COLUMN, &val2);
-	tmp = g_value_get_string(&val2);
-	if (tmp != NULL && g_str_has_prefix(tmp, key)) {
-		g_value_unset(&val2);
-		return TRUE;
-	}
-	g_value_unset(&val2);
-
-	return FALSE;
-}
-
-static gboolean
-buddyname_completion_match_selected_cb(G_GNUC_UNUSED GtkEntryCompletion *completion,
-                                       GtkTreeModel *model, GtkTreeIter *iter,
-                                       PidginCompletionData *data)
-{
-	GValue val;
-	PurpleAccount *account = NULL;
-
-	val.g_type = 0;
-	gtk_tree_model_get_value(model, iter, COMPLETION_BUDDY_COLUMN, &val);
-	gtk_editable_set_text(GTK_EDITABLE(data->entry), g_value_get_string(&val));
-	g_value_unset(&val);
-
-	gtk_tree_model_get_value(model, iter, COMPLETION_ACCOUNT_COLUMN, &val);
-	account = g_value_get_pointer(&val);
-	g_value_unset(&val);
-
-	if(!PURPLE_IS_ACCOUNT(account)) {
-		return TRUE;
-	}
-
-	if(PIDGIN_IS_ACCOUNT_CHOOSER(data->chooser)) {
-		pidgin_account_chooser_set_selected(PIDGIN_ACCOUNT_CHOOSER(data->chooser),
-		                                    account);
-	}
-
-	return TRUE;
-}
-
-static void
-add_buddyname_autocomplete_entry(GtkListStore *store, const char *buddy_alias, const char *contact_alias,
-								  const PurpleAccount *account, const char *buddyname)
-{
-	GtkTreeIter iter;
-	gboolean completion_added = FALSE;
-	gchar *normalized_buddyname;
-	gchar *tmp;
-
-	tmp = g_utf8_normalize(buddyname, -1, G_NORMALIZE_DEFAULT);
-	normalized_buddyname = g_utf8_casefold(tmp, -1);
-	g_free(tmp);
-
-	/* There's no sense listing things like: 'xxx "xxx"'
-	   when the name and buddy alias match. */
-	if (buddy_alias && !purple_strequal(buddy_alias, buddyname)) {
-		char *completion_entry = g_strdup_printf("%s \"%s\"", buddyname, buddy_alias);
-		char *tmp2 = g_utf8_normalize(buddy_alias, -1, G_NORMALIZE_DEFAULT);
-
-		tmp = g_utf8_casefold(tmp2, -1);
-		g_free(tmp2);
-
-		gtk_list_store_append(store, &iter);
-		gtk_list_store_set(store, &iter,
-				COMPLETION_DISPLAYED_COLUMN, completion_entry,
-				COMPLETION_BUDDY_COLUMN, buddyname,
-				COMPLETION_NORMALIZED_COLUMN, normalized_buddyname,
-				COMPLETION_COMPARISON_COLUMN, tmp,
-				COMPLETION_ACCOUNT_COLUMN, account,
-				-1);
-		g_free(completion_entry);
-		g_free(tmp);
-		completion_added = TRUE;
-	}
-
-	/* There's no sense listing things like: 'xxx "xxx"'
-	   when the name and contact alias match. */
-	if (contact_alias && !purple_strequal(contact_alias, buddyname)) {
-		/* We don't want duplicates when the contact and buddy alias match. */
-		if (!purple_strequal(contact_alias, buddy_alias)) {
-			char *completion_entry = g_strdup_printf("%s \"%s\"",
-							buddyname, contact_alias);
-			char *tmp2 = g_utf8_normalize(contact_alias, -1, G_NORMALIZE_DEFAULT);
-
-			tmp = g_utf8_casefold(tmp2, -1);
-			g_free(tmp2);
-
-			gtk_list_store_append(store, &iter);
-			gtk_list_store_set(store, &iter,
-					COMPLETION_DISPLAYED_COLUMN, completion_entry,
-					COMPLETION_BUDDY_COLUMN, buddyname,
-					COMPLETION_NORMALIZED_COLUMN, normalized_buddyname,
-					COMPLETION_COMPARISON_COLUMN, tmp,
-					COMPLETION_ACCOUNT_COLUMN, account,
-					-1);
-			g_free(completion_entry);
-			g_free(tmp);
-			completion_added = TRUE;
-		}
-	}
-
-	if (completion_added == FALSE) {
-		/* Add the buddy's name. */
-		gtk_list_store_append(store, &iter);
-		gtk_list_store_set(store, &iter,
-				COMPLETION_DISPLAYED_COLUMN, buddyname,
-				COMPLETION_BUDDY_COLUMN, buddyname,
-				COMPLETION_NORMALIZED_COLUMN, normalized_buddyname,
-				COMPLETION_COMPARISON_COLUMN, NULL,
-				COMPLETION_ACCOUNT_COLUMN, account,
-				-1);
-	}
-
-	g_free(normalized_buddyname);
-}
-
-static void
-add_completion_list(PidginCompletionData *data)
-{
-	PurpleBlistNode *gnode, *cnode, *bnode;
-	PidginFilterBuddyCompletionEntryFunc filter_func = data->filter_func;
-	gpointer user_data = data->filter_func_user_data;
-	gchar *alias;
-
-	gtk_list_store_clear(data->store);
-
-	for (gnode = purple_blist_get_default_root(); gnode != NULL;
-	     gnode = gnode->next) {
-		if (!PURPLE_IS_GROUP(gnode))
-			continue;
-
-		for (cnode = gnode->child; cnode != NULL; cnode = cnode->next)
-		{
-			if (!PURPLE_IS_META_CONTACT(cnode))
-				continue;
-
-			g_object_get(cnode, "alias", &alias, NULL);
-
-			for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
-			{
-				PidginBuddyCompletionEntry entry;
-				entry.is_buddy = TRUE;
-				entry.buddy = (PurpleBuddy *) bnode;
-
-				if (filter_func(&entry, user_data)) {
-					add_buddyname_autocomplete_entry(data->store,
-														alias,
-														purple_buddy_get_contact_alias(entry.buddy),
-														purple_buddy_get_account(entry.buddy),
-														purple_buddy_get_name(entry.buddy)
-													 );
-				}
-			}
-
-			g_free(alias);
-		}
-	}
-}
-
-static void
-repopulate_autocomplete(G_GNUC_UNUSED gpointer something, gpointer data)
-{
-	add_completion_list(data);
-}
-
-static void
-autocomplete_account_added_cb(G_GNUC_UNUSED PurpleAccountManager *manager,
-                              G_GNUC_UNUSED PurpleAccount *account,
-                              gpointer data)
-{
-	add_completion_list(data);
-}
-
-static void
-autocomplete_account_removed_cb(G_GNUC_UNUSED PurpleAccountManager *manager,
-                                G_GNUC_UNUSED PurpleAccount *account,
-                                gpointer data)
-{
-	add_completion_list(data);
-}
-
-static void
-buddyname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data)
-{
-	PurpleAccountManager *manager = purple_account_manager_get_default();
-
-	purple_signals_disconnect_by_handle(widget);
-
-	g_signal_handlers_disconnect_by_func(manager,
-	                                     autocomplete_account_added_cb, data);
-	g_signal_handlers_disconnect_by_func(manager,
-	                                     autocomplete_account_removed_cb,
-	                                     data);
-
-	g_free(data);
-}
-
-void
-pidgin_setup_screenname_autocomplete(
-        GtkWidget *entry, GtkWidget *chooser,
-        PidginFilterBuddyCompletionEntryFunc filter_func, gpointer user_data)
-{
-	PidginCompletionData *data;
-	PurpleAccountManager *manager = NULL;
-
-	/*
-	 * Store the displayed completion value, the buddy name, the UTF-8
-	 * normalized & casefolded buddy name, the UTF-8 normalized &
-	 * casefolded value for comparison, and the account.
-	 */
-	GtkListStore *store;
-
-	GtkEntryCompletion *completion;
-
-	data = g_new0(PidginCompletionData, 1);
-	store = gtk_list_store_new(COMPLETION_COLUMN_COUNT, G_TYPE_STRING,
-	                           G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
-	                           G_TYPE_POINTER);
-
-	data->entry = entry;
-	data->chooser = chooser;
-	if (filter_func == NULL) {
-		data->filter_func = pidgin_screenname_autocomplete_default_filter;
-		data->filter_func_user_data = NULL;
-	} else {
-		data->filter_func = filter_func;
-		data->filter_func_user_data = user_data;
-	}
-	data->store = store;
-
-	add_completion_list(data);
-
-	/* Sort the completion list by buddy name */
-	gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store),
-	                                     COMPLETION_BUDDY_COLUMN,
-	                                     GTK_SORT_ASCENDING);
-
-	completion = gtk_entry_completion_new();
-	gtk_entry_completion_set_match_func(completion, buddyname_completion_match_func, NULL, NULL);
-
-	g_signal_connect(G_OBJECT(completion), "match-selected",
-		G_CALLBACK(buddyname_completion_match_selected_cb), data);
-
-	gtk_entry_set_completion(GTK_ENTRY(entry), completion);
-	g_object_unref(completion);
-
-	gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store));
-	g_object_unref(store);
-
-	gtk_entry_completion_set_text_column(completion, COMPLETION_DISPLAYED_COLUMN);
-
-	purple_signal_connect(purple_connections_get_handle(), "signed-on", entry,
-						G_CALLBACK(repopulate_autocomplete), data);
-	purple_signal_connect(purple_connections_get_handle(), "signed-off", entry,
-						G_CALLBACK(repopulate_autocomplete), data);
-
-	manager = purple_account_manager_get_default();
-	g_signal_connect(manager, "added",
-	                 G_CALLBACK(autocomplete_account_added_cb), data);
-	g_signal_connect(manager, "removed",
-	                 G_CALLBACK(autocomplete_account_removed_cb), data);
-
-	g_signal_connect(G_OBJECT(entry), "destroy", G_CALLBACK(buddyname_autocomplete_destroyed_cb), data);
-}
-
-gboolean
-pidgin_screenname_autocomplete_default_filter(const PidginBuddyCompletionEntry *completion_entry, gpointer all_accounts) {
-	gboolean all = GPOINTER_TO_INT(all_accounts);
-
-	return all || purple_account_is_connected(purple_buddy_get_account(completion_entry->buddy));
-}
-
 GtkWidget *
 pidgin_add_widget_to_vbox(GtkBox *vbox, const char *widget_label, GtkSizeGroup *sg, GtkWidget *widget, gboolean expand, GtkWidget **p_label)
 {
--- a/pidgin/gtkutils.h	Sat Dec 30 01:50:32 2023 -0600
+++ b/pidgin/gtkutils.h	Sat Dec 30 18:22:52 2023 -0600
@@ -32,54 +32,10 @@
 
 #include "pidginversion.h"
 
-PIDGIN_AVAILABLE_TYPE_IN_2_1
-typedef struct {
-	gboolean is_buddy;
-	PurpleBuddy *buddy;
-} PidginBuddyCompletionEntry;
-
-PIDGIN_AVAILABLE_TYPE_IN_2_1
-typedef gboolean (*PidginFilterBuddyCompletionEntryFunc) (const PidginBuddyCompletionEntry *completion_entry, gpointer user_data);
-
 
 G_BEGIN_DECLS
 
 /**
- * pidgin_setup_screenname_autocomplete:
- * @entry:       The GtkEntry on which to setup autocomplete.
- * @chooser: A menu for accounts, returned by pidgin_account_chooser_new(). If
- *           @chooser is not %NULL, it'll be updated when a username is chosen
- *           from the autocomplete list.
- * @filter_func: (scope call): A function for checking if an autocomplete entry
- *                    should be shown. This can be %NULL.
- * @user_data:  The data to be passed to the filter_func function.
- *
- * Add autocompletion of screenames to an entry, supporting a filtering
- * function.
- *
- * Since: 2.0.0
- */
-PIDGIN_AVAILABLE_IN_ALL
-void pidgin_setup_screenname_autocomplete(
-        GtkWidget *entry, GtkWidget *chooser,
-        PidginFilterBuddyCompletionEntryFunc filter_func, gpointer user_data);
-
-/**
- * pidgin_screenname_autocomplete_default_filter:
- * @completion_entry: The completion entry to filter.
- * @all_accounts:  If this is %FALSE, only the autocompletion entries
- *                         which belong to an online account will be filtered.
- *
- * The default filter function for username autocomplete.
- *
- * Returns: Returns %TRUE if the autocompletion entry is filtered.
- *
- * Since: 2.1.0
- */
-PIDGIN_AVAILABLE_IN_2_1
-gboolean pidgin_screenname_autocomplete_default_filter(const PidginBuddyCompletionEntry *completion_entry, gpointer all_accounts);
-
-/**
  * pidgin_retrieve_user_info:
  * @conn:   The connection to get information from.
  * @name:   The user to get information about.

mercurial