From 1f7e03f2861f4b8d2bb75bd220754b7a89b7847e Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 23 Dec 2004 06:59:04 +0000 Subject: [PATCH] hook up potentially-questionable "find results status text" feature - 2004-12-23 Havoc Pennington * shell/ev-window.c: hook up potentially-questionable "find results status text" feature - something involving the sidebar or scrollbar or a continuous all-pages-on-giant-roll-of-paper-view might be better in the end. * shell/ev-view.c (ev_view_get_find_status_message): new function, with corresponding signal when it should be updated * shell/eggfindbar.c (egg_find_bar_set_status_text): new function --- ChangeLog | 12 +++++ pdf/xpdf/pdf-document.cc | 18 ++++--- shell/eggfindbar.c | 50 ++++++++++++++++- shell/eggfindbar.h | 3 ++ shell/ev-view.c | 112 ++++++++++++++++++++++++++++++++++++++- shell/ev-view.h | 2 + shell/ev-window.c | 25 +++++++-- 7 files changed, 209 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 974ea21f..65bcb035 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2004-12-23 Havoc Pennington + + * shell/ev-window.c: hook up potentially-questionable "find + results status text" feature - something involving the sidebar or + scrollbar or a continuous all-pages-on-giant-roll-of-paper-view + might be better in the end. + + * shell/ev-view.c (ev_view_get_find_status_message): new function, + with corresponding signal when it should be updated + + * shell/eggfindbar.c (egg_find_bar_set_status_text): new function + 2004-12-22 Havoc Pennington * pdf/xpdf/pdf-document.cc (pdf_document_find_begin): make search diff --git a/pdf/xpdf/pdf-document.cc b/pdf/xpdf/pdf-document.cc index 64d592ca..50055f0c 100644 --- a/pdf/xpdf/pdf-document.cc +++ b/pdf/xpdf/pdf-document.cc @@ -314,13 +314,15 @@ pdf_document_search_emit_found (PdfDocumentSearch *search) { PdfDocument *pdf_document = search->document; int n_pages; - double pages_done; + int pages_done; GArray *tmp_results; int i; n_pages = ev_document_get_n_pages (EV_DOCUMENT (search->document)); if (search->search_page > search->start_page) { pages_done = search->search_page - search->start_page; + } else if (search->search_page == search->start_page) { + pages_done = n_pages; } else { pages_done = n_pages - search->start_page + search->search_page; } @@ -467,15 +469,16 @@ pdf_document_search_idle_callback (void *data) &xMin, &yMin, &xMax, &yMax)) { /* This page has results */ search->other_page_flags[search->search_page] = TRUE; - - pdf_document_search_emit_found (search); } - + search->search_page += 1; if (search->search_page > n_pages) { /* wrap around */ search->search_page = 1; } + + /* We do this even if nothing was found, to update the percent complete */ + pdf_document_search_emit_found (search); return TRUE; @@ -537,8 +540,11 @@ pdf_document_find_begin (EvDocumentFind *document, search->document = pdf_document; - search->idle = g_idle_add (pdf_document_search_idle_callback, - search); + /* We add at low priority so the progress bar repaints */ + search->idle = g_idle_add_full (G_PRIORITY_LOW, + pdf_document_search_idle_callback, + search, + NULL); search->output_dev = 0; diff --git a/shell/eggfindbar.c b/shell/eggfindbar.c index f7b20479..c16e9b95 100644 --- a/shell/eggfindbar.c +++ b/shell/eggfindbar.c @@ -42,6 +42,8 @@ struct _EggFindBarPrivate GtkWidget *next_button; GtkWidget *previous_button; GtkWidget *case_button; + GtkWidget *status_separator; + GtkWidget *status_label; guint case_sensitive : 1; }; @@ -311,6 +313,13 @@ egg_find_bar_init (EggFindBar *find_bar) priv->case_button = gtk_check_button_new_with_mnemonic (_("C_ase Sensitive")); + priv->status_separator = gtk_vseparator_new (); + + priv->status_label = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (priv->status_label), + PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment (GTK_MISC (priv->status_label), 0.0, 0.5); + #if 0 { GtkWidget *button_label; @@ -339,7 +348,11 @@ egg_find_bar_init (EggFindBar *find_bar) separator, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (priv->hbox), priv->case_button, FALSE, FALSE, 0); - + gtk_box_pack_start (GTK_BOX (priv->hbox), + priv->status_separator, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (priv->hbox), + priv->status_label, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER (find_bar), priv->hbox); gtk_widget_show (priv->hbox); @@ -352,6 +365,7 @@ egg_find_bar_init (EggFindBar *find_bar) gtk_widget_show (image); gtk_widget_show (image_back); gtk_widget_show (image_forward); + /* don't show status separator/label until they are set */ gtk_widget_pop_composite_child (); @@ -690,3 +704,37 @@ egg_find_bar_grab_focus (EggFindBar *find_bar) gtk_widget_grab_focus (priv->find_entry); } + +/** + * egg_find_bar_set_status_text: + * + * Sets some text to display if there's space; typical text would + * be something like "5 results on this page" or "No results" + * + * @text: the text to display + * + * Since: 2.6 + */ +void +egg_find_bar_set_status_text (EggFindBar *find_bar, + const char *text) +{ + EggFindBarPrivate *priv; + + g_return_if_fail (EGG_IS_FIND_BAR (find_bar)); + + priv = (EggFindBarPrivate *)find_bar->private_data; + + if (text == NULL || *text == '\0') + { + gtk_widget_hide (priv->status_label); + gtk_widget_hide (priv->status_separator); + gtk_label_set_text (GTK_LABEL (priv->status_label), NULL); + } + else + { + gtk_label_set_text (GTK_LABEL (priv->status_label), text); + gtk_widget_show (priv->status_label); + gtk_widget_show (priv->status_separator); + } +} diff --git a/shell/eggfindbar.h b/shell/eggfindbar.h index 0ac665ad..217a180f 100644 --- a/shell/eggfindbar.h +++ b/shell/eggfindbar.h @@ -67,6 +67,9 @@ void egg_find_bar_get_current_match_color (EggFindBar *find_bar, GdkColor *color); void egg_find_bar_grab_focus (EggFindBar *find_bar); +void egg_find_bar_set_status_text (EggFindBar *find_bar, + const char *text); + G_END_DECLS #endif /* __EGG_FIND_BAR_H__ */ diff --git a/shell/ev-view.c b/shell/ev-view.c index d0950936..07fdecd8 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -19,6 +19,7 @@ */ #include +#include #include "ev-marshal.h" #include "ev-view.h" @@ -42,6 +43,9 @@ struct _EvView { GtkAdjustment *vadjustment; GArray *find_results; + int results_on_this_page; + int next_page_with_result; + double find_percent_complete; double scale; }; @@ -458,6 +462,14 @@ ev_view_class_init (EvViewClass *class) NULL, NULL, ev_marshal_VOID__NONE, G_TYPE_NONE, 0); + + g_signal_new ("find-status-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + ev_marshal_VOID__NONE, + G_TYPE_NONE, 0); } static void @@ -472,8 +484,73 @@ ev_view_init (EvView *view) view->find_results = g_array_new (FALSE, FALSE, sizeof (EvFindResult)); + view->results_on_this_page = 0; + view->next_page_with_result = 0; } +static void +update_find_results (EvView *view) +{ + const EvFindResult *results; + int i; + int on_this_page; + int next_page_with_result; + int earliest_page_with_result; + int current_page; + gboolean counts_changed; + + results = (EvFindResult*) view->find_results->data; + current_page = ev_document_get_page (view->document); + next_page_with_result = 0; + on_this_page = 0; + earliest_page_with_result = 0; + + i = 0; + while (i < view->find_results->len) { + if (results[i].page_num == current_page) { + ++on_this_page; + } else { + int delta = results[i].page_num - current_page; + + if (delta > 0 && /* result on later page */ + (next_page_with_result == 0 || + results[i].page_num < next_page_with_result)) + next_page_with_result = results[i].page_num; + + if (delta < 0 && /* result on a previous page */ + (earliest_page_with_result == 0 || + results[i].page_num < earliest_page_with_result)) + earliest_page_with_result = results[i].page_num; + } + ++i; + } + + /* If earliest page is just the current page, there is no earliest page */ + if (earliest_page_with_result == current_page) + earliest_page_with_result = 0; + + /* If no next page, then wrap and the wrapped page is the next page */ + if (next_page_with_result == 0) + next_page_with_result = earliest_page_with_result; + + counts_changed = FALSE; + if (on_this_page != view->results_on_this_page || + next_page_with_result != view->next_page_with_result) { + view->results_on_this_page = on_this_page; + view->next_page_with_result = next_page_with_result; + counts_changed = TRUE; + } + + /* If there are no results at all, then the + * results of ev_view_get_find_status_message() will change + * to reflect the percent_complete so we have to emit the signal + */ + if (counts_changed || + view->find_results->len == 0) { + g_signal_emit_by_name (view, + "find-status-changed"); + } +} static void found_results_callback (EvDocument *document, @@ -494,7 +571,8 @@ found_results_callback (EvDocument *document, { int i; - g_printerr ("%d results: ", n_results); + g_printerr ("%d results %d%%: ", n_results, + (int) (percent_complete * 100)); i = 0; while (i < n_results) { g_printerr ("%d ", results[i].page_num); @@ -503,6 +581,9 @@ found_results_callback (EvDocument *document, g_printerr ("\n"); } #endif + + view->find_percent_complete = percent_complete; + update_find_results (view); gtk_widget_queue_draw (GTK_WIDGET (view)); } @@ -525,11 +606,14 @@ ev_view_set_document (EvView *view, int old_page = ev_view_get_page (view); if (view->document) { - g_object_unref (view->document); g_signal_handlers_disconnect_by_func (view->document, found_results_callback, view); g_array_set_size (view->find_results, 0); + view->results_on_this_page = 0; + view->next_page_with_result = 0; + + g_object_unref (view->document); } view->document = document; @@ -562,6 +646,10 @@ ev_view_set_page (EvView *view, ev_document_set_page (view->document, page); if (old_page != ev_document_get_page (view->document)) { g_signal_emit (view, page_changed_signal, 0); + + view->find_percent_complete = 0.0; + update_find_results (view); + gtk_widget_queue_draw (GTK_WIDGET (view)); } } @@ -656,3 +744,23 @@ ev_view_fit_width (EvView *view) ev_view_zoom (view, scale, FALSE); } + +char* +ev_view_get_find_status_message (EvView *view) +{ + if (view->find_results->len == 0) { + if (view->find_percent_complete >= (1.0 - 1e-10)) { + return g_strdup (_("Not found")); + } else { + return g_strdup_printf (_("%3d%% remaining to search"), + (int) ((1.0 - view->find_percent_complete) * 100)); + } + } else if (view->results_on_this_page == 0) { + g_assert (view->next_page_with_result != 0); + return g_strdup_printf (_("Found on page %d"), + view->next_page_with_result); + } else { + return g_strdup_printf (_("%d found on this page"), + view->results_on_this_page); + } +} diff --git a/shell/ev-view.h b/shell/ev-view.h index f175b16f..600c7b94 100644 --- a/shell/ev-view.h +++ b/shell/ev-view.h @@ -49,6 +49,8 @@ void ev_view_normal_size (EvView *view); void ev_view_best_fit (EvView *view); void ev_view_fit_width (EvView *view); +char* ev_view_get_find_status_message (EvView *view); + G_END_DECLS #endif /* __EV_VIEW_H__ */ diff --git a/shell/ev-window.c b/shell/ev-window.c index 405f86bc..27edfee8 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -894,6 +894,20 @@ view_page_changed_cb (EvView *view, update_action_sensitivity (ev_window); } +static void +view_find_status_changed_cb (EvView *view, + EvWindow *ev_window) +{ + char *text; + + text = ev_view_get_find_status_message (view); + + egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), + text); + + g_free (text); +} + static void find_bar_previous_cb (EggFindBar *find_bar, EvWindow *ev_window) @@ -946,15 +960,14 @@ find_bar_search_changed_cb (EggFindBar *find_bar, g_printerr ("search for '%s'\n", search_string ? search_string : "(nil)"); #endif - /* We don't require begin/end find calls to be matched up, it's really - * start_find and cancel_any_find_that_may_not_be_finished - */ if (ev_window->priv->document && EV_IS_DOCUMENT_FIND (ev_window->priv->document)) { if (visible && search_string) { ev_document_find_begin (EV_DOCUMENT_FIND (ev_window->priv->document), search_string, case_sensitive); } else { ev_document_find_cancel (EV_DOCUMENT_FIND (ev_window->priv->document)); + egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), + NULL); } } } @@ -1218,7 +1231,11 @@ ev_window_init (EvWindow *ev_window) "page-changed", G_CALLBACK (view_page_changed_cb), ev_window); - + g_signal_connect (ev_window->priv->view, + "find-status-changed", + G_CALLBACK (view_find_status_changed_cb), + ev_window); + ev_window->priv->statusbar = gtk_statusbar_new (); gtk_widget_show (ev_window->priv->statusbar); gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box), -- 2.43.5