qulogic/pidgin

Remove the screen name auto-completion API

4 months ago, Gary Kramlich
d745bb34f491
Parents 4157c07b840c
Children 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/
--- 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.