changeset 7295:c7f0a4397d9e

[gaim-migrate @ 7879] I added a search feature to conversations. I actually did most of this a while ago for the log viewer. GtkIMHtml has some functions to handle searching itself. I just added a new item to the conversation menu to handle it. This should be useful for long IRC channel backlogs and the sorts. It's case-sensitive right now. That kinda sucks, but that's all GTK lets me do. GtkSourceView has some nice case-insensitive search functions that I'll likely bring in before the release. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Sat, 18 Oct 2003 01:58:02 +0000
parents e5d0f5cb61fb
children 3bc7bd545a0b
files ChangeLog src/gtkconv.c src/gtkconv.h src/gtkimhtml.c src/gtkimhtml.h
diffstat 5 files changed, 145 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Fri Oct 17 21:29:15 2003 +0000
+++ b/ChangeLog	Sat Oct 18 01:58:02 2003 +0000
@@ -1,6 +1,7 @@
 Gaim: The Pimpin' Penguin IM Clone that's good for the soul!
 
 version 0.72
+	* Added a search feature to conversations.
 	* Fixed a crash in the Add Chat dialog when selecting an
 	  account that doesn't support chats. Closes bug #821606.
 	* If SSL is not enabled, MSN will load, but error on connect.
--- a/src/gtkconv.c	Fri Oct 17 21:29:15 2003 +0000
+++ b/src/gtkconv.c	Sat Oct 18 01:58:02 2003 +0000
@@ -715,6 +715,82 @@
 	conv_show_log(NULL, (char *)gaim_conversation_get_name(conv));
 }
 
+struct _search {
+	GaimGtkConversation *gtkconv;
+	GtkWidget *entry;
+};
+
+static void do_search_cb(GtkWidget *widget, gint resp, struct _search *s)
+{
+	switch (resp) {
+	case GTK_RESPONSE_OK:
+		gtk_imhtml_search_find(s->gtkconv->imhtml, gtk_entry_get_text(GTK_ENTRY(s->entry)));
+		break;
+	case GTK_RESPONSE_CLOSE:
+		gtk_imhtml_search_clear(s->gtkconv->imhtml);
+		gtk_widget_destroy(s->gtkconv->dialogs.search);
+		s->gtkconv->dialogs.search = NULL;
+		g_free(s);
+		break;
+	}
+}
+
+static void
+menu_search_cb(gpointer data, guint action, GtkWidget *widget)
+{
+	GaimConvWindow *win = (GaimConvWindow *)data;
+	GaimConversation *conv = gaim_conv_window_get_active_conversation(win);
+	GaimGtkWindow *gtkwin = GAIM_GTK_WINDOW(win);
+	GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv);
+	GtkWidget *hbox, *vbox;
+	GtkWidget *img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG);
+	GtkWidget *label, *entry;
+	struct _search *s;
+
+	if (gtkconv->dialogs.search)
+		return;
+	
+	gtkconv->dialogs.search = gtk_dialog_new_with_buttons("", GTK_WINDOW(gtkwin->window),
+							      GTK_DIALOG_DESTROY_WITH_PARENT,
+							      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, 
+							      GTK_STOCK_FIND, GTK_RESPONSE_OK, NULL);
+	gtk_container_set_border_width (GTK_CONTAINER(gtkconv->dialogs.search), 6);
+	gtk_window_set_resizable(GTK_WINDOW(gtkconv->dialogs.search), FALSE);
+	gtk_dialog_set_has_separator(GTK_DIALOG(gtkconv->dialogs.search), FALSE);
+	gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(gtkconv->dialogs.search)->vbox), 12);
+	gtk_container_set_border_width (GTK_CONTAINER(GTK_DIALOG(gtkconv->dialogs.search)->vbox), 6);
+	
+	hbox = gtk_hbox_new(FALSE, 6);
+	gtk_container_add(GTK_CONTAINER(GTK_DIALOG(gtkconv->dialogs.search)->vbox), hbox);
+	gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0);
+	gtk_misc_set_alignment(GTK_MISC(img), 0, 0);
+
+	vbox = gtk_vbox_new(FALSE, 0);
+	gtk_container_add(GTK_CONTAINER(hbox), vbox);
+
+	label = gtk_label_new(NULL);
+	gtk_label_set_markup(GTK_LABEL(label), _("<span weight='bold' size='larger'>Enter a search phrase\n</span>"));
+	gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+	gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+	
+	hbox = gtk_hbox_new(FALSE, 6);
+	gtk_container_add(GTK_CONTAINER(vbox), hbox);
+	label = gtk_label_new(_("Search term: "));
+	entry = gtk_entry_new();
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 0);
+
+	s = g_malloc(sizeof(struct _search));
+	s->gtkconv = gtkconv;
+	s->entry = entry;
+	
+	gtk_dialog_set_default_response (GTK_DIALOG(gtkconv->dialogs.search), GTK_RESPONSE_OK);
+	g_signal_connect(G_OBJECT(gtkconv->dialogs.search), "response", G_CALLBACK(do_search_cb), s);
+	
+	gtk_widget_show_all(gtkconv->dialogs.search);
+}
+
 static void
 menu_add_pounce_cb(gpointer data, guint action, GtkWidget *widget)
 {
@@ -2837,7 +2913,8 @@
 
 	{ N_("/Conversation/_Save As..."), NULL, menu_save_as_cb, 0,
 	  "<StockItem>", GTK_STOCK_SAVE_AS },
-	{ N_("/Conversation/View _Log..."), NULL, menu_view_log_cb, 0, NULL },
+	{ N_("/Conversation/View _Log"), NULL, menu_view_log_cb, 0, NULL },
+	{ N_("/Conversation/Search..."), NULL, menu_search_cb, 0, "<StockItem>", GTK_STOCK_FIND },
 
 	{ "/Conversation/sep1", NULL, NULL, 0, "<Separator>" },
 
@@ -2916,7 +2993,7 @@
 
 	gtkwin->menu.view_log =
 		gtk_item_factory_get_widget(gtkwin->menu.item_factory,
-									N_("/Conversation/View Log..."));
+									N_("/Conversation/View Log"));
 	/* --- */
 
 	gtkwin->menu.add_pounce =
@@ -4247,6 +4324,9 @@
 	if (gtkconv->dialogs.log != NULL)
 		gtk_widget_destroy(gtkconv->dialogs.log);
 
+	if (gtkconv->dialogs.search != NULL)
+		gtk_widget_destroy(gtkconv->dialogs.search);
+
 	gtk_widget_destroy(gtkconv->tab_cont);
 	g_object_unref(gtkconv->tab_cont);
 
--- a/src/gtkconv.h	Fri Oct 17 21:29:15 2003 +0000
+++ b/src/gtkconv.h	Sat Oct 18 01:58:02 2003 +0000
@@ -185,6 +185,7 @@
 		GtkWidget *link;
 		GtkWidget *image;
 		GtkWidget *log;
+		GtkWidget *search;
 
 	} dialogs;
 
--- a/src/gtkimhtml.c	Fri Oct 17 21:29:15 2003 +0000
+++ b/src/gtkimhtml.c	Sat Oct 18 01:58:02 2003 +0000
@@ -409,7 +409,8 @@
 	gtk_text_buffer_create_tag(imhtml->text_buffer, "SUB", "rise", -5000, NULL);
 	gtk_text_buffer_create_tag(imhtml->text_buffer, "SUP", "rise", 5000, NULL);
 	gtk_text_buffer_create_tag(imhtml->text_buffer, "PRE", "family", "Monospace", NULL);
-	
+	gtk_text_buffer_create_tag(imhtml->text_buffer, "search", "background", "#22ff00", "weight", "bold", NULL);
+
 	/* When hovering over a link, we show the hand cursor--elsewhere we show the plain ol' pointer cursor */
 	imhtml->hand_cursor = gdk_cursor_new (GDK_HAND2);
 	imhtml->arrow_cursor = gdk_cursor_new (GDK_LEFT_PTR);
@@ -1764,3 +1765,57 @@
 {
 	g_free(scale);
 }
+
+gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text)
+{
+	GtkTextIter iter, start, end;
+	gboolean new_search = TRUE;
+
+	g_return_val_if_fail(imhtml != NULL, FALSE);
+	g_return_val_if_fail(text != NULL, FALSE);
+	
+	if (imhtml->search_string && !strcmp(text, imhtml->search_string))
+		new_search = FALSE;
+	 
+	
+	if (new_search) {
+		gtk_imhtml_search_clear(imhtml);
+		gtk_text_buffer_get_start_iter(imhtml->text_buffer, &iter);
+	} else {
+		gtk_text_buffer_get_iter_at_mark(imhtml->text_buffer, &iter,
+						 gtk_text_buffer_get_mark(imhtml->text_buffer, "search"));	
+	}
+	imhtml->search_string = g_strdup(text);
+
+	if (gtk_text_iter_forward_search(&iter, imhtml->search_string,
+					 GTK_TEXT_SEARCH_VISIBLE_ONLY,
+					 &start, &end, NULL)) {
+
+		gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(imhtml), &start, 0, TRUE, 0, 0);
+		gtk_text_buffer_create_mark(imhtml->text_buffer, "search", &end, FALSE);
+		if (new_search) {
+			gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &iter, &end);
+			do 
+				gtk_text_buffer_apply_tag_by_name(imhtml->text_buffer, "search", &start, &end);
+			while (gtk_text_iter_forward_search(&end, imhtml->search_string, GTK_TEXT_SEARCH_VISIBLE_ONLY,
+							      &start, &end, NULL));
+		}
+		return TRUE;
+	}
+	return FALSE;
+}
+
+void gtk_imhtml_search_clear(GtkIMHtml *imhtml)
+{
+	GtkTextIter start, end;
+	
+	g_return_if_fail(imhtml != NULL);
+	
+	gtk_text_buffer_get_start_iter(imhtml->text_buffer, &start);
+	gtk_text_buffer_get_end_iter(imhtml->text_buffer, &end);
+
+	gtk_text_buffer_remove_tag_by_name(imhtml->text_buffer, "search", &start, &end);
+	if (imhtml->search_string)
+		g_free(imhtml->search_string);
+	imhtml->search_string = NULL;
+}
--- a/src/gtkimhtml.h	Fri Oct 17 21:29:15 2003 +0000
+++ b/src/gtkimhtml.h	Sat Oct 18 01:58:02 2003 +0000
@@ -66,6 +66,8 @@
 
 	GList *scalables;
 	GdkRectangle old_rect;
+
+	gchar *search_string;
 };
 
 struct _GtkIMHtmlClass {
@@ -167,6 +169,9 @@
 void gtk_imhtml_hr_scale(GtkIMHtmlScalable *, int, int);
 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *, GtkIMHtml *, GtkTextIter *);
 
+/* Search functions */
+gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text);
+void gtk_imhtml_search_clear(GtkIMHtml *imhtml);
 
 #ifdef __cplusplus
 }