changeset 8294:d5e59ea083be

[gaim-migrate @ 9018] Added auto-completion for screen names to the New Instant Message and Get User Info dialogs. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Thu, 19 Feb 2004 09:47:44 +0000
parents a1b7c7f3d9a7
children bc850664b559
files ChangeLog src/gtkrequest.c
diffstat 2 files changed, 195 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Feb 19 08:36:02 2004 +0000
+++ b/ChangeLog	Thu Feb 19 09:47:44 2004 +0000
@@ -5,6 +5,8 @@
 	* WYSIWYG text input
 	* Ability to be invisible on AIM
 	* Chatroom list support (Tim Ringenbach)
+	* Added auto-completion for screen names to the New Instant Message and
+	  Get User Info dialogs.
 	* Non-ascii character support in AIM chats (Uli Luckas and Marco Ziech)
 	* Vastly improved browser opening, with tab support! (Nathan Fredrickson)
 	* Support for Mozilla Firefox (Chris Friesen and Nathan Fredrickson)
--- a/src/gtkrequest.c	Thu Feb 19 08:36:02 2004 +0000
+++ b/src/gtkrequest.c	Thu Feb 19 09:47:44 2004 +0000
@@ -31,6 +31,12 @@
 #include "stock.h"
 #include "ui.h"
 
+#include <gdk/gdkkeysyms.h>
+
+#if GTK_CHECK_VERSION(2,3,0)
+# define NEW_STYLE_COMPLETION
+#endif
+
 typedef struct
 {
 	GaimRequestType type;
@@ -63,6 +69,16 @@
 
 } GaimGtkRequestData;
 
+#ifndef NEW_STYLE_COMPLETION
+typedef struct
+{
+	GCompletion *completion;
+
+	gboolean completion_started;
+
+} GaimGtkCompletionData;
+#endif
+
 static void
 input_response_cb(GtkDialog *dialog, gint id, GaimGtkRequestData *data)
 {
@@ -460,9 +476,178 @@
 		gaim_request_fields_all_required_filled(field->group->fields_list));
 }
 
+GList *
+get_online_screennames(void)
+{
+	GList *screennames = NULL;
+	GaimBlistNode *gnode, *cnode, *bnode;
+
+	for (gnode = gaim_get_blist()->root; gnode != NULL; gnode = gnode->next)
+	{
+		if (!GAIM_BLIST_NODE_IS_GROUP(gnode))
+			continue;
+
+		for (cnode = gnode->child; cnode != NULL; cnode = cnode->next)
+		{
+			if (!GAIM_BLIST_NODE_IS_CONTACT(cnode))
+				continue;
+
+			for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
+			{
+				GaimBuddy *buddy = (GaimBuddy *)bnode;
+
+				if (!gaim_account_is_connected(buddy->account))
+					continue;
+
+				screennames = g_list_append(screennames, g_strdup(buddy->name));
+			}
+		}
+	}
+
+	return screennames;
+}
+
+#ifndef NEW_STYLE_COMPLETION
+static gboolean
+completion_entry_event(GtkEditable *entry, GdkEventKey *event,
+					   GaimGtkCompletionData *data)
+{
+	int pos, end_pos;
+
+	if (event->type == GDK_KEY_PRESS && event->keyval == GDK_Tab)
+	{
+		gtk_editable_get_selection_bounds(entry, &pos, &end_pos);
+
+		if (data->completion_started &&
+			pos != end_pos && pos > 1 &&
+			end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry))))
+		{
+			gtk_editable_select_region(entry, 0, 0);
+			gtk_editable_set_position(entry, -1);
+
+			return TRUE;
+		}
+	}
+	else if (event->type == GDK_KEY_PRESS && event->length > 0)
+	{
+		char *prefix, *nprefix;
+
+		gtk_editable_get_selection_bounds(entry, &pos, &end_pos);
+
+		if (data->completion_started &&
+			pos != end_pos && pos > 1 &&
+			end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry))))
+		{
+			char *temp;
+
+			temp = gtk_editable_get_chars(entry, 0, pos);
+			prefix = g_strconcat(temp, event->string, NULL);
+			g_free(temp);
+		}
+		else if (pos == end_pos && pos > 1 &&
+				 end_pos == strlen(gtk_entry_get_text(GTK_ENTRY(entry))))
+		{
+			prefix = g_strconcat(gtk_entry_get_text(GTK_ENTRY(entry)),
+								 event->string, NULL);
+		}
+		else
+			return FALSE;
+
+		pos = strlen(prefix);
+		nprefix = NULL;
+
+		g_completion_complete(data->completion, prefix, &nprefix);
+
+		if (nprefix != NULL)
+		{
+			gtk_entry_set_text(GTK_ENTRY(entry), nprefix);
+			gtk_editable_set_position(entry, pos);
+			gtk_editable_select_region(entry, pos, -1);
+
+			data->completion_started = TRUE;
+
+			g_free(nprefix);
+			g_free(prefix);
+
+			return TRUE;
+		}
+
+		g_free(prefix);
+	}
+
+	return FALSE;
+}
+
+static void
+destroy_completion_data(GtkWidget *w, GaimGtkCompletionData *data)
+{
+	g_list_foreach(data->completion->items, (GFunc)g_free, NULL);
+	g_completion_free(data->completion);
+
+	g_free(data);
+}
+#endif /* !NEW_STYLE_COMPLETION */
+
+static void
+setup_screenname_autocomplete(GtkWidget *entry, GaimRequestField *field)
+{
+#ifdef NEW_STYLE_COMPLETION
+	GtkListStore *store;
+	GtkTreeIter iter;
+	GtkEntryCompletion *completion;
+	GList *screennames, *l;
+
+	store = gtk_list_store_new(1, G_TYPE_STRING);
+
+	screennames = get_online_screennames();
+
+	for (l = screennames; l != NULL; l = l->next)
+	{
+		gtk_list_store_append(store, &iter);
+		gtk_list_store_set(store, &iter, 0, l->data, -1);
+	}
+
+	g_list_foreach(screennames, (GFunc)g_free, NULL);
+	g_list_free(screennames);
+
+	completion = gtk_entry_completion_new();
+	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, 0);
+
+#else /* !NEW_STYLE_COMPLETION */
+	GaimGtkCompletionData *data;
+	GList *screennames;
+
+	data = g_new0(GaimGtkCompletionData, 1);
+
+	data->completion = g_completion_new(NULL);
+
+	g_completion_set_compare(data->completion, g_ascii_strncasecmp);
+
+	screennames = get_online_screennames();
+
+	g_completion_add_items(data->completion, screennames);
+
+	g_list_free(screennames);
+
+	g_signal_connect(G_OBJECT(entry), "event",
+					 G_CALLBACK(completion_entry_event), data);
+	g_signal_connect(G_OBJECT(entry), "destroy",
+					 G_CALLBACK(destroy_completion_data), data);
+
+#endif /* !NEW_STYLE_COMPLETION */
+}
+
 static void
 setup_entry_field(GtkWidget *entry, GaimRequestField *field)
 {
+	const char *type_hint;
+
 	gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
 
 	if (gaim_request_field_is_required(field))
@@ -470,6 +655,14 @@
 		g_signal_connect(G_OBJECT(entry), "changed",
 						 G_CALLBACK(req_entry_field_changed_cb), field);
 	}
+
+	if ((type_hint = gaim_request_field_get_type_hint(field)) != NULL)
+	{
+		if (!strcmp(type_hint, "screenname"))
+		{
+			setup_screenname_autocomplete(entry, field);
+		}
+	}
 }
 
 static GtkWidget *