[evince/wip/find_results: 1/2] libview: add Model for find_results to EvJobFind.



commit 6d09c5e323e2b23288117d6a2879161d7f18debb
Author: Josà Aliste <jaliste src gnome org>
Date:   Wed Nov 7 16:02:21 2012 +0100

    libview: add Model for find_results to EvJobFind.

 libview/ev-jobs.c            |  150 +++++++++++++++++++++++++++++++++++++++++-
 libview/ev-jobs.h            |    3 +
 libview/ev-view-marshal.list |    1 +
 libview/ev-view.c            |   33 +++++++++
 libview/ev-view.h            |    3 +
 5 files changed, 188 insertions(+), 2 deletions(-)
---
diff --git a/libview/ev-jobs.c b/libview/ev-jobs.c
index 63097d6..fb4a915 100644
--- a/libview/ev-jobs.c
+++ b/libview/ev-jobs.c
@@ -1512,6 +1512,138 @@ ev_job_save_new (EvDocument  *document,
 }
 
 /* EvJobFind */
+static gchar *
+get_surrounding_text_markup (GtkTextIter *match_start,
+		             GtkTextIter *match_end)
+{
+	gchar *match, *prec, *succ, *markup;
+	GtkTextIter surrounding_start = *match_start;
+	GtkTextIter surrounding_end = *match_end;
+
+	gtk_text_iter_backward_word_start (&surrounding_start);
+	gtk_text_iter_forward_word_ends (&surrounding_end, 2);
+	
+	match = gtk_text_iter_get_text (match_start, match_end);
+	prec = gtk_text_iter_get_text (&surrounding_start, match_start);
+	succ = gtk_text_iter_get_text (match_end, &surrounding_end);
+
+	markup = g_markup_printf_escaped ("%s<span weight = \"bold\">%s</span>%s",
+                                	  prec, match, succ);
+	g_free (match);
+	g_free (prec);
+	g_free (succ);
+
+	return markup;
+}
+
+static gchar *
+ev_job_find_get_matched_line (EvJob *job, EvPage *page, EvRectangle *match)
+{
+	EvRectangle r;
+	gchar *tmp, *result;
+
+	r = *match;
+	r.y1 = r.y2 = (r.y1 + r.y2)/2;
+	r.x1 = r.x2 = (r.x1 + r.x2)/2;
+
+	tmp = ev_selection_get_selected_text (
+			EV_SELECTION (job->document),
+			page,
+			EV_SELECTION_STYLE_LINE,
+			&r);
+	result = g_utf8_normalize (tmp, -1, G_NORMALIZE_ALL);
+	g_free (tmp);
+
+	return result;
+
+}
+
+static void
+ev_job_find_process_matches (EvJob *job)
+{
+	EvJobFind *job_find;
+	GList *matches;
+	EvPage *page;
+	GtkTreeIter iter;
+	gint occno, j, k;
+	gchar *matched_line, *text_to_find;
+	GtkTextBuffer *buffer;
+	GtkTextIter find_iter, start, end;
+	gchar *markup;
+
+	job_find = EV_JOB_FIND (job);
+	buffer = gtk_text_buffer_new (NULL);
+	matches = job_find->pages[job_find->current_page];
+
+	if (!matches)
+		return;
+
+
+	page = ev_document_get_page (job->document, job_find->current_page);
+
+	occno = 0;
+	j = 0;
+
+	if (job_find->case_sensitive)
+		text_to_find = g_strdup (job_find->text);
+	else
+		text_to_find = g_utf8_strdown (job_find->text, -1);
+
+	while (matches != NULL) {
+
+		matched_line = ev_job_find_get_matched_line (job, page, (EvRectangle *) matches->data);
+		g_assert (matched_line != NULL);
+
+		if (!job_find->case_sensitive) {
+			gchar *tmp = matched_line;
+
+			matched_line = g_utf8_strdown (tmp, -1);
+			g_free (tmp);
+		} 
+		
+		gtk_text_buffer_set_text (buffer, matched_line, -1);
+		gtk_text_buffer_get_start_iter (buffer, &find_iter);
+
+		/* search the proper occurrence of text in the line */
+		occno++;
+		for (k = 0; k < occno; k++ ) {
+			if (!gtk_text_iter_forward_search (&find_iter, text_to_find, 0, &start, &end, NULL))
+				break;
+			find_iter = end;
+			gtk_text_iter_forward_char (&find_iter);
+		}
+
+		/* additional search to determine that current match is the last one on the line */
+		if (!gtk_text_iter_forward_search (&find_iter, text_to_find, 0, NULL, NULL, NULL)) 
+			occno = 0;
+
+		markup = get_surrounding_text_markup (&start, &end);
+
+		if (job_find->current_page >= job_find->start_page) {
+			gtk_list_store_append (GTK_LIST_STORE (job_find->model), &iter);
+		} else {
+			gtk_list_store_insert (
+					GTK_LIST_STORE (job_find->model),
+					&iter,
+					job_find->insert_position);
+			job_find->insert_position++;
+		};
+		gtk_list_store_set (GTK_LIST_STORE (job_find->model), &iter,
+				0, markup,
+				1, job_find->current_page + 1,
+				2, j,
+				- 1);
+
+		g_free (markup);
+		g_free (matched_line);
+		
+		matches = g_list_next (matches);
+		j++;
+	}
+	g_free (text_to_find);
+
+}
+
 static void
 ev_job_find_init (EvJobFind *job)
 {
@@ -1541,7 +1673,13 @@ ev_job_find_dispose (GObject *object)
 		g_free (job->pages);
 		job->pages = NULL;
 	}
-	
+
+	if (job->model)	{
+		gtk_list_store_clear (GTK_LIST_STORE (job->model));
+		g_object_unref (job->model);
+		job->model = NULL;
+	};
+
 	(* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
 }
 
@@ -1570,12 +1708,15 @@ ev_job_find_run (EvJob *job)
                                                            job_find->options);
 	g_object_unref (ev_page);
 	
-	ev_document_doc_mutex_unlock ();
 
 	if (!job_find->has_results)
 		job_find->has_results = (matches != NULL);
 
 	job_find->pages[job_find->current_page] = matches;
+	ev_job_find_process_matches (job);
+	
+	ev_document_doc_mutex_unlock ();
+
 	g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page);
 		       
 	job_find->current_page = (job_find->current_page + 1) % job_find->n_pages;
@@ -1633,6 +1774,11 @@ ev_job_find_new (EvDocument  *document,
         if (case_sensitive)
                 job->options |= EV_FIND_CASE_SENSITIVE;
 
+	job->model = (GtkTreeModel *)gtk_list_store_new (3,
+						G_TYPE_STRING,
+						G_TYPE_INT,
+						G_TYPE_INT);
+	job->insert_position = 0;
 	return EV_JOB (job);
 }
 
diff --git a/libview/ev-jobs.h b/libview/ev-jobs.h
index cc9b7ad..8b4234d 100644
--- a/libview/ev-jobs.h
+++ b/libview/ev-jobs.h
@@ -392,6 +392,9 @@ struct _EvJobFind
 	gboolean case_sensitive;
 	gboolean has_results;
         EvFindOptions options;
+
+	GtkTreeModel *model;
+	gint insert_position;
 };
 
 struct _EvJobFindClass
diff --git a/libview/ev-view-marshal.list b/libview/ev-view-marshal.list
index d7b0e75..cd02f42 100644
--- a/libview/ev-view-marshal.list
+++ b/libview/ev-view-marshal.list
@@ -1,2 +1,3 @@
 VOID:ENUM,BOOLEAN
 VOID:INT,INT
+VOID:POINTER,INT,INT
diff --git a/libview/ev-view.c b/libview/ev-view.c
index 7aa2c73..dfc4085 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -57,6 +57,7 @@ enum {
 	SIGNAL_SYNC_SOURCE,
 	SIGNAL_ANNOT_ADDED,
 	SIGNAL_LAYERS_CHANGED,
+	SIGNAL_FIND_RESULT_HIGHLIGHT_CHANGED,
 	N_SIGNALS
 };
 
@@ -4875,6 +4876,15 @@ ev_view_class_init (EvViewClass *class)
 		         g_cclosure_marshal_VOID__VOID,
 		         G_TYPE_NONE, 0,
 			 G_TYPE_NONE);
+	signals[SIGNAL_FIND_RESULT_HIGHLIGHT_CHANGED] = g_signal_new ("find-result-highlight-changed",
+		G_TYPE_FROM_CLASS (object_class),
+		G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		0,
+		NULL, NULL,
+		ev_view_marshal_VOID__POINTER_INT_INT,
+		G_TYPE_NONE, 3,
+		G_TYPE_POINTER, G_TYPE_INT, G_TYPE_INT);
+
 
 	binding_set = gtk_binding_set_by_class (class);
 
@@ -4992,6 +5002,13 @@ ev_view_page_changed_cb (EvDocumentModel *model,
 	}
 
 	view->find_result = 0;
+
+	g_signal_emit (view,
+		signals[SIGNAL_FIND_RESULT_HIGHLIGHT_CHANGED],
+		0,
+		view->find_pages,
+		new_page,
+		view->find_result);
 }
 
 static void
@@ -5821,6 +5838,13 @@ jump_to_find_result (EvView *view)
 		ensure_rectangle_is_visible (view, &view_rect);
 		view->jump_to_find_result = FALSE;
 	}
+
+	g_signal_emit (view,
+		signals[SIGNAL_FIND_RESULT_HIGHLIGHT_CHANGED],
+		0,
+		view->find_pages,
+		page,
+		view->find_result);
 }
 
 /**
@@ -5927,6 +5951,15 @@ ev_view_find_previous (EvView *view)
 }
 
 void
+ev_view_find_arbitrary (EvView *view, gint page, gint result)
+{
+	ev_document_model_set_page (view->model, page);
+	view->find_result = result;
+	jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0);
+	jump_to_find_result (view);
+}
+
+void
 ev_view_find_search_changed (EvView *view)
 {
 	/* search string has changed, focus on new search result */
diff --git a/libview/ev-view.h b/libview/ev-view.h
index f82dc9a..4ede1ec 100644
--- a/libview/ev-view.h
+++ b/libview/ev-view.h
@@ -75,6 +75,9 @@ void            ev_view_find_started              (EvView         *view,
 						   EvJobFind      *job);
 void            ev_view_find_next                 (EvView         *view);
 void            ev_view_find_previous             (EvView         *view);
+void ev_view_find_arbitrary (EvView *view,
+						gint page,
+						gint result);
 void            ev_view_find_search_changed       (EvView         *view);
 void     	ev_view_find_set_highlight_search (EvView         *view,
 						   gboolean        value);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]