Sat, 30 Dec 2023 18:22:52 -0600
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.