1
0
mirror of https://gitlab.gnome.org/GNOME/evince synced 2024-07-05 00:59:07 +00:00
2008-08-27  Carlos Garcia Campos  <carlosgc@gnome.org>

	* backend/djvu/Makefile.am:
	* backend/djvu/djvu-document-private.h:
	* backend/djvu/djvu-document.c: (djvu_document_find_find_text),
	(djvu_document_find_iface_init):
	* backend/djvu/djvu-text-page.[ch]:
	* backend/djvu/djvu-text.[ch]: Removed
	* backend/pdf/ev-poppler.cc: (pdf_document_find_find_text),
	(pdf_document_find_iface_init):
	* libdocument/ev-document-find.[ch]: (ev_document_find_find_text):
	* shell/ev-jobs.[ch]: (ev_job_find_init), (ev_job_find_dispose),
	(ev_job_find_run), (ev_job_find_class_init), (ev_job_find_new),
	(ev_job_find_get_n_results), (ev_job_find_get_progress),
	(ev_job_find_has_results), (ev_job_find_get_results):
	* shell/ev-view-private.h:
	* shell/ev-view.[ch]: (ev_view_expose_event),
	(highlight_find_results), (ev_view_finalize),
	(ev_view_get_property), (ev_view_class_init), (page_changed_cb),
	(ev_view_set_document), (ev_view_find_get_n_results),
	(ev_view_find_get_result), (jump_to_find_result),
	(jump_to_find_page), (ev_view_find_changed), (ev_view_find_next),
	(ev_view_find_previous), (ev_view_find_search_changed),
	(ev_view_find_set_highlight_search), (ev_view_find_cancel):
	* shell/ev-window.c: (ev_window_update_actions),
	(page_changed_cb), (ev_window_setup_document),
	(ev_window_update_find_status_message),
	(ev_window_find_job_finished_cb), (ev_window_find_job_updated_cb),
	(ev_window_clear_find_job), (find_bar_close_cb),
	(find_bar_search_changed_cb), (find_bar_visibility_changed_cb),
	(ev_window_dispose), (ev_window_init):

	Rework find interface. The find logic has been moved from backends
	to the shell avoiding a lot of duplicated code in the backends and
	making easier to implement the find interface in the backends.

svn path=/trunk/; revision=3123
This commit is contained in:
Carlos Garcia Campos 2008-08-27 09:01:41 +00:00 committed by Carlos Garcia Campos
parent 8d5f4e92b9
commit c86fea7366
17 changed files with 534 additions and 1003 deletions

View File

@ -1,3 +1,39 @@
2008-08-27 Carlos Garcia Campos <carlosgc@gnome.org>
* backend/djvu/Makefile.am:
* backend/djvu/djvu-document-private.h:
* backend/djvu/djvu-document.c: (djvu_document_find_find_text),
(djvu_document_find_iface_init):
* backend/djvu/djvu-text-page.[ch]:
* backend/djvu/djvu-text.[ch]: Removed
* backend/pdf/ev-poppler.cc: (pdf_document_find_find_text),
(pdf_document_find_iface_init):
* libdocument/ev-document-find.[ch]: (ev_document_find_find_text):
* shell/ev-jobs.[ch]: (ev_job_find_init), (ev_job_find_dispose),
(ev_job_find_run), (ev_job_find_class_init), (ev_job_find_new),
(ev_job_find_get_n_results), (ev_job_find_get_progress),
(ev_job_find_has_results), (ev_job_find_get_results):
* shell/ev-view-private.h:
* shell/ev-view.[ch]: (ev_view_expose_event),
(highlight_find_results), (ev_view_finalize),
(ev_view_get_property), (ev_view_class_init), (page_changed_cb),
(ev_view_set_document), (ev_view_find_get_n_results),
(ev_view_find_get_result), (jump_to_find_result),
(jump_to_find_page), (ev_view_find_changed), (ev_view_find_next),
(ev_view_find_previous), (ev_view_find_search_changed),
(ev_view_find_set_highlight_search), (ev_view_find_cancel):
* shell/ev-window.c: (ev_window_update_actions),
(page_changed_cb), (ev_window_setup_document),
(ev_window_update_find_status_message),
(ev_window_find_job_finished_cb), (ev_window_find_job_updated_cb),
(ev_window_clear_find_job), (find_bar_close_cb),
(find_bar_search_changed_cb), (find_bar_visibility_changed_cb),
(ev_window_dispose), (ev_window_init):
Rework find interface. The find logic has been moved from backends
to the shell avoiding a lot of duplicated code in the backends and
making easier to implement the find interface in the backends.
2008-08-25 Carlos Garcia Campos <carlosgc@gnome.org>
* backend/pdf/ev-poppler.cc:

View File

@ -18,8 +18,6 @@ libdjvudocument_la_SOURCES = \
djvu-document-private.h \
djvu-links.c \
djvu-links.h \
djvu-text.c \
djvu-text.h \
djvu-text-page.c \
djvu-text-page.h

View File

@ -22,7 +22,6 @@
#define __DJVU_DOCUMENT_INTERNAL_H__
#include "djvu-document.h"
#include "djvu-text.h"
#include <libdjvu/ddjvuapi.h>
@ -36,8 +35,6 @@ struct _DjvuDocument {
gchar *uri;
DjvuText *search;
/* PS exporter */
gchar *ps_filename;
GString *opts;

View File

@ -21,7 +21,7 @@
#include <config.h>
#include "djvu-document.h"
#include "djvu-text.h"
#include "djvu-text-page.h"
#include "djvu-links.h"
#include "djvu-document-private.h"
#include "ev-document-thumbnails.h"
@ -388,9 +388,6 @@ djvu_document_finalize (GObject *object)
{
DjvuDocument *djvu_document = DJVU_DOCUMENT (object);
if (djvu_document->search)
djvu_text_free (djvu_document->search);
if (djvu_document->d_document)
ddjvu_document_release (djvu_document->d_document);
@ -437,6 +434,30 @@ djvu_document_document_iface_init (EvDocumentIface *iface)
iface->get_info = djvu_document_get_info;
}
static gchar *
djvu_text_copy (DjvuDocument *djvu_document,
gint page,
EvRectangle *rectangle)
{
miniexp_t page_text;
gchar *text = NULL;
while ((page_text =
ddjvu_document_get_pagetext (djvu_document->d_document,
page, "char")) == miniexp_dummy)
djvu_handle_events (djvu_document, TRUE, NULL);
if (page_text != miniexp_nil) {
DjvuTextPage *page = djvu_text_page_new (page_text);
text = djvu_text_page_copy (page, rectangle);
djvu_text_page_free (page);
ddjvu_miniexp_release (djvu_document->d_document, page_text);
}
return text;
}
static gchar *
djvu_selection_get_selected_text (EvSelection *selection,
EvRenderContext *rc,
@ -627,107 +648,62 @@ djvu_document_init (DjvuDocument *djvu_document)
djvu_document->d_document = NULL;
}
static void
djvu_document_find_begin (EvDocumentFind *document,
int page,
const char *search_string,
gboolean case_sensitive)
static GList *
djvu_document_find_find_text (EvDocumentFind *document,
EvPage *page,
const char *text,
gboolean case_sensitive)
{
DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
miniexp_t page_text;
gdouble width, height;
GList *matches = NULL, *l;
if (djvu_document->search &&
strcmp (search_string, djvu_text_get_text (djvu_document->search)) == 0)
return;
g_return_val_if_fail (text != NULL, NULL);
if (djvu_document->search)
djvu_text_free (djvu_document->search);
while ((page_text = ddjvu_document_get_pagetext (djvu_document->d_document,
page->index,
"char")) == miniexp_dummy)
djvu_handle_events (djvu_document, TRUE, NULL);
djvu_document->search = djvu_text_new (djvu_document,
page,
case_sensitive,
search_string);
}
static int
djvu_document_find_get_n_results (EvDocumentFind *document_find, int page)
{
DjvuText *search = DJVU_DOCUMENT (document_find)->search;
if (search) {
return djvu_text_n_results (search, page);
} else {
return 0;
}
}
static gboolean
djvu_document_find_get_result (EvDocumentFind *document_find,
int page,
int n_result,
EvRectangle *rectangle)
{
DjvuDocument *djvu_document = DJVU_DOCUMENT (document_find);
DjvuText *search = djvu_document->search;
EvRectangle *r;
double width, height;
if (search == NULL)
return FALSE;
r = djvu_text_get_result (search, page, n_result);
if (r == NULL)
return FALSE;
document_get_page_size (djvu_document, page, &width, &height);
rectangle->x1 = r->x1 * SCALE_FACTOR;
rectangle->y1 = height - r->y2 * SCALE_FACTOR;
rectangle->x2 = r->x2 * SCALE_FACTOR;
rectangle->y2 = height - r->y1 * SCALE_FACTOR;
if (page_text != miniexp_nil) {
DjvuTextPage *tpage = djvu_text_page_new (page_text);
return TRUE;
}
djvu_text_page_prepare_search (tpage, case_sensitive);
if (tpage->links->len > 0) {
djvu_text_page_search (tpage, text);
matches = tpage->results;
}
djvu_text_page_free (tpage);
ddjvu_miniexp_release (djvu_document->d_document, page_text);
}
static int
djvu_document_find_page_has_results (EvDocumentFind *document_find,
int page)
{
DjvuText *search = DJVU_DOCUMENT (document_find)->search;
if (!matches)
return NULL;
return search && djvu_text_has_results (search, page);
}
document_get_page_size (djvu_document, page->index, &width, &height);
for (l = matches; l && l->data; l = g_list_next (l)) {
EvRectangle *r = (EvRectangle *)l->data;
gdouble tmp;
static double
djvu_document_find_get_progress (EvDocumentFind *document_find)
{
DjvuText *search = DJVU_DOCUMENT (document_find)->search;
tmp = r->y1;
r->x1 *= SCALE_FACTOR;
r->x2 *= SCALE_FACTOR;
tmp = r->y1;
r->y1 = height - r->y2 * SCALE_FACTOR;
r->y2 = height - tmp * SCALE_FACTOR;
}
if (search == NULL) {
return 0;
}
return djvu_text_get_progress (search);
}
static void
djvu_document_find_cancel (EvDocumentFind *document)
{
DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
if (djvu_document->search) {
djvu_text_free (djvu_document->search);
djvu_document->search = NULL;
}
return matches;
}
static void
djvu_document_find_iface_init (EvDocumentFindIface *iface)
{
iface->begin = djvu_document_find_begin;
iface->get_n_results = djvu_document_find_get_n_results;
iface->get_result = djvu_document_find_get_result;
iface->page_has_results = djvu_document_find_page_has_results;
iface->get_progress = djvu_document_find_get_progress;
iface->cancel = djvu_document_find_cancel;
iface->find_text = djvu_document_find_find_text;
}
static GList *

View File

@ -371,7 +371,7 @@ djvu_text_page_append_text (DjvuTextPage *page,
*/
void
djvu_text_page_search (DjvuTextPage *page,
char *text)
const char *text)
{
char *haystack = page->text;
int search_len;

View File

@ -23,6 +23,7 @@
#include <string.h>
#include <glib.h>
#include <libdjvu/miniexp.h>
typedef struct _DjvuTextPage DjvuTextPage;
@ -50,8 +51,8 @@ char * djvu_text_page_copy (DjvuTextPage *page,
void djvu_text_page_prepare_search (DjvuTextPage *page,
gboolean case_sensitive);
void djvu_text_page_search (DjvuTextPage *page,
char *text);
DjvuTextPage* djvu_text_page_new (miniexp_t text);
const char *text);
DjvuTextPage* djvu_text_page_new (miniexp_t text);
void djvu_text_page_free (DjvuTextPage *page);
#endif /* __DJVU_TEXT_PAGE_H__ */

View File

@ -1,302 +0,0 @@
/*
* Implements search and copy functionality for Djvu files.
* Copyright (C) 2006 Michael Hofmann <mh21@piware.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <config.h>
#include <string.h>
#include <glib.h>
#include <libdjvu/miniexp.h>
#include "djvu-document-private.h"
#include "djvu-document.h"
#include "djvu-text.h"
#include "djvu-text-page.h"
#include "ev-document-find.h"
#include "ev-document.h"
struct _DjvuText {
DjvuDocument *document;
gboolean case_sensitive;
char *text;
GList **pages;
guint idle;
int start_page;
int search_page;
};
/**
* djvu_text_idle_callback:
* @data: #DjvuText instance
*
* Idle callback that processes one page at a time.
*
* Returns: whether there are more pages to be processed
*/
static gboolean
djvu_text_idle_callback (void *data)
{
DjvuText *djvu_text = (DjvuText *) data;
DjvuDocument *djvu_document = djvu_text->document;
int n_pages;
miniexp_t page_text;
ev_document_doc_mutex_lock ();
while ((page_text =
ddjvu_document_get_pagetext (djvu_document->d_document,
djvu_text->search_page,
"char")) == miniexp_dummy)
djvu_handle_events (djvu_document, TRUE, NULL);
if (page_text != miniexp_nil) {
DjvuTextPage *page = djvu_text_page_new (page_text);
djvu_text_page_prepare_search (page, djvu_text->case_sensitive);
if (page->links->len > 0) {
djvu_text_page_search (page, djvu_text->text);
djvu_text->pages[djvu_text->search_page] = page->results;
ev_document_find_changed (EV_DOCUMENT_FIND
(djvu_document),
djvu_text->search_page);
}
djvu_text_page_free (page);
ddjvu_miniexp_release (djvu_document->d_document,
page_text);
}
ev_document_doc_mutex_unlock ();
n_pages =
djvu_document_get_n_pages (EV_DOCUMENT (djvu_text->document));
djvu_text->search_page += 1;
if (djvu_text->search_page == n_pages) {
/* wrap around */
djvu_text->search_page = 0;
}
if (djvu_text->search_page != djvu_text->start_page)
return TRUE;
/* We're done. */
djvu_text->idle = 0;
/* will return FALSE to remove */
return FALSE;
}
/**
* djvu_text_new:
* @djvu_document: document to search
* @start_page: first page to search
* @case_sensitive: uses g_utf8_case_fold() to enable case-insensitive
* searching
* @text: text to search
*
* Creates a new #DjvuText instance to enable searching. An idle call
* is used to process all pages starting from @start_page.
*
* Returns: newly created instance
*/
DjvuText *
djvu_text_new (DjvuDocument *djvu_document,
int start_page,
gboolean case_sensitive,
const char *text)
{
DjvuText *djvu_text;
int n_pages;
int i;
n_pages = djvu_document_get_n_pages (EV_DOCUMENT (djvu_document));
djvu_text = g_new0 (DjvuText, 1);
if (case_sensitive)
djvu_text->text = g_strdup (text);
else
djvu_text->text = g_utf8_casefold (text, -1);
djvu_text->pages = g_new0 (GList *, n_pages);
for (i = 0; i < n_pages; i++) {
djvu_text->pages[i] = NULL;
}
djvu_text->document = djvu_document;
/* We add at low priority so the progress bar repaints */
djvu_text->idle = g_idle_add_full (G_PRIORITY_LOW,
djvu_text_idle_callback,
djvu_text, NULL);
djvu_text->case_sensitive = case_sensitive;
djvu_text->start_page = start_page;
djvu_text->search_page = start_page;
return djvu_text;
}
/**
* djvu_text_copy:
* @djvu_document: document to search
* @page: page to search
* @rectangle: rectangle to copy
*
* Copies and returns the text in the given rectangle.
*
* Returns: newly allocated text or NULL of none is available
*/
char *
djvu_text_copy (DjvuDocument *djvu_document,
int page,
EvRectangle *rectangle)
{
miniexp_t page_text;
char* text = NULL;
while ((page_text =
ddjvu_document_get_pagetext (djvu_document->d_document,
page, "char")) == miniexp_dummy)
djvu_handle_events (djvu_document, TRUE, NULL);
if (page_text != miniexp_nil) {
DjvuTextPage *page = djvu_text_page_new (page_text);
text = djvu_text_page_copy (page, rectangle);
djvu_text_page_free (page);
ddjvu_miniexp_release (djvu_document->d_document, page_text);
}
return text;
}
/**
* djvu_text_free:
* @djvu_text: instance to free
*
* Frees the given #DjvuText instance.
*/
void djvu_text_free (DjvuText * djvu_text)
{
DjvuDocument *djvu_document = djvu_text->document;
int n_pages;
int i;
if (djvu_text->idle != 0)
g_source_remove (djvu_text->idle);
n_pages = djvu_document_get_n_pages (EV_DOCUMENT (djvu_document));
for (i = 0; i < n_pages; i++) {
g_list_foreach (djvu_text->pages[i], (GFunc) g_free, NULL);
g_list_free (djvu_text->pages[i]);
}
g_free (djvu_text->text);
}
/**
* djvu_text_get_text:
* @djvu_text: #DjvuText instance
*
* Returns the search text. This is mainly to be able to avoid reinstantiation
* for the same search text.
*
* Returns: the text this instance of #DjvuText is looking for
*/
const char *
djvu_text_get_text (DjvuText *djvu_text)
{
return djvu_text->text;
}
/**
* djvu_text_n_results:
* @djvu_text: #DjvuText instance
* @page: page number
*
* Returns the number of search results available for the given page.
*
* Returns: number of search results
*/
int
djvu_text_n_results (DjvuText *djvu_text,
int page)
{
return g_list_length (djvu_text->pages[page]);
}
/**
* djvu_text_has_results:
* @djvu_text: #DjvuText instance
* @page: page number
*
* Returns whether there are search results available for the given page.
* This method executes faster than djvu_text_n_results().
*
* Returns: whether there are search results
*/
int
djvu_text_has_results (DjvuText *djvu_text,
int page)
{
return djvu_text->pages[page] != NULL;
}
/**
* djvu_text_get_result:
* @djvu_text: #DjvuText instance
* @page: page number
* @n_result: result number
*
* Returns the n-th search result of a given page. The coordinates are
* Djvu-specific and need to be processed to be compatible with the Evince
* coordinate system. The result may span several lines!
*
* Returns: the rectangle for the search result
*/
EvRectangle *
djvu_text_get_result (DjvuText *djvu_text,
int page,
int n_result)
{
return (EvRectangle *) g_list_nth_data (djvu_text->pages[page],
n_result);
}
/**
* djvu_text_get_progress:
* @djvu_text: #DjvuText instance
*
* Returns the percentage of pages done searching.
*
* Returns: the progress as value between 0 and 1
*/
double
djvu_text_get_progress (DjvuText *djvu_text)
{
int pages_done;
int n_pages;
n_pages =
djvu_document_get_n_pages (EV_DOCUMENT (djvu_text->document));
if (djvu_text->search_page > djvu_text->start_page) {
pages_done = djvu_text->search_page - djvu_text->start_page + 1;
} else if (djvu_text->search_page == djvu_text->start_page) {
pages_done = n_pages;
} else {
pages_done =
n_pages - djvu_text->start_page + djvu_text->search_page;
}
return pages_done / (double) n_pages;
}

View File

@ -1,46 +0,0 @@
/*
* Copyright (C) 2006 Michael Hofmann <mh21@piware.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __DJVU_TEXT_H__
#define __DJVU_TEXT_H__
#include "ev-document.h"
#include <glib.h>
typedef struct _DjvuText DjvuText;
DjvuText *djvu_text_new (DjvuDocument *djvu_document,
int start_page,
gboolean case_sensitive,
const char *text);
void djvu_text_free (DjvuText *djvu_text);
const char *djvu_text_get_text (DjvuText *djvu_text);
int djvu_text_n_results (DjvuText *djvu_text,
int page);
EvRectangle *djvu_text_get_result (DjvuText *djvu_text,
int page,
int n_result);
int djvu_text_has_results (DjvuText *djvu_text,
int page);
double djvu_text_get_progress (DjvuText *djvu_text);
char *djvu_text_copy (DjvuDocument *djvu_document,
int page,
EvRectangle *rectangle);
#endif /* __DJVU_TEXT_H__ */

View File

@ -1364,195 +1364,42 @@ pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface)
}
static gboolean
pdf_document_search_idle_callback (void *data)
static GList *
pdf_document_find_find_text (EvDocumentFind *document_find,
EvPage *page,
const gchar *text,
gboolean case_sensitive)
{
PdfDocumentSearch *search = (PdfDocumentSearch*) data;
PdfDocument *pdf_document = search->document;
int n_pages;
GList *matches;
PopplerPage *page;
page = poppler_document_get_page (search->document->document,
search->search_page);
ev_document_doc_mutex_lock ();
matches = poppler_page_find_text (page, search->text);
ev_document_doc_mutex_unlock ();
g_object_unref (page);
search->pages[search->search_page] = matches;
ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document),
search->search_page);
n_pages = pdf_document_get_n_pages (EV_DOCUMENT (search->document));
search->search_page += 1;
if (search->search_page == n_pages) {
/* wrap around */
search->search_page = 0;
}
if (search->search_page != search->start_page) {
return TRUE;
}
/* We're done. */
search->idle = 0; /* will return FALSE to remove */
return FALSE;
}
static PdfDocumentSearch *
pdf_document_search_new (PdfDocument *pdf_document,
int start_page,
const char *text)
{
PdfDocumentSearch *search;
int n_pages;
int i;
n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document));
search = g_new0 (PdfDocumentSearch, 1);
search->text = g_strdup (text);
search->pages = g_new0 (GList *, n_pages);
search->document = pdf_document;
/* 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->start_page = start_page;
search->search_page = start_page;
return search;
}
static void
pdf_document_find_begin (EvDocumentFind *document,
int page,
const char *search_string,
gboolean case_sensitive)
{
PdfDocument *pdf_document = PDF_DOCUMENT (document);
/* FIXME handle case_sensitive (right now XPDF
* code is always case insensitive for ASCII
* and case sensitive for all other languaages)
*/
if (pdf_document->search &&
strcmp (search_string, pdf_document->search->text) == 0)
return;
if (pdf_document->search)
pdf_document_search_free (pdf_document->search);
pdf_document->search = pdf_document_search_new (pdf_document,
page,
search_string);
}
static int
pdf_document_find_get_n_results (EvDocumentFind *document_find, int page)
{
PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
if (search) {
return g_list_length (search->pages[page]);
} else {
return 0;
}
}
static gboolean
pdf_document_find_get_result (EvDocumentFind *document_find,
int page,
int n_result,
EvRectangle *rectangle)
{
PdfDocument *pdf_document = PDF_DOCUMENT (document_find);
PdfDocumentSearch *search = pdf_document->search;
GList *matches, *l;
PopplerPage *poppler_page;
PopplerRectangle *r;
double height;
gdouble height;
g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL);
g_return_val_if_fail (text != NULL, NULL);
if (search == NULL)
return FALSE;
poppler_page = POPPLER_PAGE (page->backend_page);
matches = poppler_page_find_text (poppler_page, text);
if (!matches)
return NULL;
r = (PopplerRectangle *) g_list_nth_data (search->pages[page],
n_result);
if (r == NULL)
return FALSE;
poppler_page = poppler_document_get_page (pdf_document->document, page);
poppler_page_get_size (poppler_page, NULL, &height);
rectangle->x1 = r->x1;
rectangle->y1 = height - r->y2;
rectangle->x2 = r->x2;
rectangle->y2 = height - r->y1;
g_object_unref (poppler_page);
return TRUE;
}
for (l = matches; l && l->data; l = g_list_next (l)) {
PopplerRectangle *rect = (PopplerRectangle *)l->data;
gdouble tmp;
static int
pdf_document_find_page_has_results (EvDocumentFind *document_find,
int page)
{
PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search;
return search && search->pages[page] != NULL;
}
static double
pdf_document_find_get_progress (EvDocumentFind *document_find)
{
PdfDocumentSearch *search;
int n_pages, pages_done;
search = PDF_DOCUMENT (document_find)->search;
if (search == NULL) {
return 0;
}
n_pages = pdf_document_get_n_pages (EV_DOCUMENT (document_find));
if (search->search_page > search->start_page) {
pages_done = search->search_page - search->start_page + 1;
} else if (search->search_page == search->start_page) {
pages_done = n_pages;
} else {
pages_done = n_pages - search->start_page + search->search_page;
}
return pages_done / (double) n_pages;
}
static void
pdf_document_find_cancel (EvDocumentFind *document)
{
PdfDocument *pdf_document = PDF_DOCUMENT (document);
if (pdf_document->search) {
pdf_document_search_free (pdf_document->search);
pdf_document->search = NULL;
tmp = rect->y1;
rect->y1 = height - rect->y2;
rect->y2 = height - tmp;
}
return matches;
}
static void
pdf_document_find_iface_init (EvDocumentFindIface *iface)
{
iface->begin = pdf_document_find_begin;
iface->get_n_results = pdf_document_find_get_n_results;
iface->get_result = pdf_document_find_get_result;
iface->page_has_results = pdf_document_find_page_has_results;
iface->get_progress = pdf_document_find_get_progress;
iface->cancel = pdf_document_find_cancel;
iface->find_text = pdf_document_find_find_text;
}
static void

View File

@ -21,9 +21,6 @@
#include "config.h"
#include "ev-document-find.h"
#include "ev-backend-marshalers.h"
static void ev_document_find_base_init (gpointer g_class);
GType
ev_document_find_get_type (void)
@ -35,7 +32,7 @@ ev_document_find_get_type (void)
const GTypeInfo our_info =
{
sizeof (EvDocumentFindIface),
ev_document_find_base_init,
NULL,
NULL,
};
@ -47,80 +44,14 @@ ev_document_find_get_type (void)
return type;
}
static void
ev_document_find_base_init (gpointer g_class)
{
static gboolean initialized = FALSE;
if (!initialized) {
g_signal_new ("find_changed",
EV_TYPE_DOCUMENT_FIND,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EvDocumentFindIface, find_changed),
NULL, NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE, 1,
G_TYPE_INT);
initialized = TRUE;
}
}
void
ev_document_find_begin (EvDocumentFind *document_find,
int page,
const char *search_string,
gboolean case_sensitive)
GList *
ev_document_find_find_text (EvDocumentFind *document_find,
EvPage *page,
const gchar *text,
gboolean case_sensitive)
{
EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find);
g_return_if_fail (search_string != NULL);
iface->begin (document_find, page, search_string, case_sensitive);
return iface->find_text (document_find, page, text, case_sensitive);
}
void
ev_document_find_cancel (EvDocumentFind *document_find)
{
EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find);
iface->cancel (document_find);
}
int
ev_document_find_page_has_results (EvDocumentFind *document_find,
int page)
{
EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find);
return iface->page_has_results (document_find, page);
}
int
ev_document_find_get_n_results (EvDocumentFind *document_find,
int page)
{
EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find);
return iface->get_n_results (document_find, page);
}
gboolean
ev_document_find_get_result (EvDocumentFind *document_find,
int page,
int n_result,
EvRectangle *rectangle)
{
EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find);
return iface->get_result (document_find, page, n_result, rectangle);
}
double
ev_document_find_get_progress (EvDocumentFind *document_find)
{
EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find);
return iface->get_progress (document_find);
}
void
ev_document_find_changed (EvDocumentFind *document_find, int page)
{
g_signal_emit_by_name (document_find, "find_changed", page);
}

View File

@ -24,9 +24,8 @@
#include <glib-object.h>
#include <glib.h>
#include <gdk/gdk.h>
#include "ev-document.h" /* For EvRectangle */
#include "ev-document.h"
G_BEGIN_DECLS
@ -37,62 +36,26 @@ G_BEGIN_DECLS
#define EV_IS_DOCUMENT_FIND_IFACE(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_DOCUMENT_FIND))
#define EV_DOCUMENT_FIND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), EV_TYPE_DOCUMENT_FIND, EvDocumentFindIface))
typedef struct _EvDocumentFind EvDocumentFind;
typedef struct _EvDocumentFindIface EvDocumentFindIface;
typedef struct _EvDocumentFind EvDocumentFind;
typedef struct _EvDocumentFindIface EvDocumentFindIface;
struct _EvDocumentFindIface
{
GTypeInterface base_iface;
/* Methods */
void (* begin) (EvDocumentFind *document_find,
int page,
const char *search_string,
gboolean case_sensitive);
void (* cancel) (EvDocumentFind *document_find);
int (* page_has_results) (EvDocumentFind *document_find,
int page);
int (* get_n_results) (EvDocumentFind *document_find,
int page);
gboolean (* get_result) (EvDocumentFind *document_find,
int page,
int n_result,
EvRectangle *rectangle);
double (* get_progress) (EvDocumentFind *document_find);
/* Signals */
void (* find_changed) (EvDocumentFind *document_find,
int page);
GList *(* find_text) (EvDocumentFind *document_find,
EvPage *page,
const gchar *text,
gboolean case_sensitive);
};
GType ev_document_find_get_type (void);
void ev_document_find_begin (EvDocumentFind *document_find,
int page,
const char *search_string,
gboolean case_sensitive);
void ev_document_find_cancel (EvDocumentFind *document_find);
int ev_document_find_page_has_results (EvDocumentFind *document_find,
int page);
int ev_document_find_get_n_results (EvDocumentFind *document_find,
int page);
gboolean ev_document_find_get_result (EvDocumentFind *document_find,
int page,
int n_result,
EvRectangle *rectangle);
double ev_document_find_get_progress (EvDocumentFind *document_find);
void ev_document_find_changed (EvDocumentFind *document_find,
int page);
/* How this interface works:
*
* begin() begins a new search, canceling any previous search.
*
* cancel() cancels a search if any, otherwise does nothing.
*
*/
GType ev_document_find_get_type (void) G_GNUC_CONST;
GList *ev_document_find_find_text (EvDocumentFind *document_find,
EvPage *page,
const gchar *text,
gboolean case_sensitive);
G_END_DECLS
#endif
#endif /* EV_DOCUMENT_FIND_H */

View File

@ -31,6 +31,7 @@
#include "ev-file-helpers.h"
#include "ev-document-fonts.h"
#include "ev-document-security.h"
#include "ev-document-find.h"
#include "ev-debug.h"
#include <errno.h>
@ -54,6 +55,8 @@ static void ev_job_save_init (EvJobSave *job);
static void ev_job_save_class_init (EvJobSaveClass *class);
static void ev_job_print_init (EvJobPrint *job);
static void ev_job_print_class_init (EvJobPrintClass *class);
static void ev_job_find_init (EvJobFind *job);
static void ev_job_find_class_init (EvJobFindClass *class);
enum {
CANCELLED,
@ -67,13 +70,19 @@ enum {
};
enum {
UPDATED,
FONTS_UPDATED,
FONTS_LAST_SIGNAL
};
enum {
FIND_UPDATED,
FIND_LAST_SIGNAL
};
static guint job_signals[LAST_SIGNAL] = { 0 };
static guint job_render_signals[RENDER_LAST_SIGNAL] = { 0 };
static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 };
static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 };
G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT)
G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB)
@ -84,6 +93,7 @@ G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobSave, ev_job_save, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB)
G_DEFINE_TYPE (EvJobFind, ev_job_find, EV_TYPE_JOB)
/* EvJob */
static void
@ -721,7 +731,7 @@ ev_job_fonts_run (EvJob *job)
#endif
job_fonts->scan_completed = !ev_document_fonts_scan (fonts, 20);
g_signal_emit (job_fonts, job_fonts_signals[UPDATED], 0,
g_signal_emit (job_fonts, job_fonts_signals[FONTS_UPDATED], 0,
ev_document_fonts_get_progress (fonts));
ev_document_fc_mutex_unlock ();
@ -740,7 +750,7 @@ ev_job_fonts_class_init (EvJobFontsClass *class)
job_class->run = ev_job_fonts_run;
job_fonts_signals[UPDATED] =
job_fonts_signals[FONTS_UPDATED] =
g_signal_new ("updated",
EV_TYPE_JOB_FONTS,
G_SIGNAL_RUN_LAST,
@ -1366,3 +1376,163 @@ ev_job_print_new (EvDocument *document,
return EV_JOB (job);
}
/* EvJobFind */
static void
ev_job_find_init (EvJobFind *job)
{
EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP;
}
static void
ev_job_find_dispose (GObject *object)
{
EvJobFind *job = EV_JOB_FIND (object);
ev_debug_message (DEBUG_JOBS, NULL);
if (job->text) {
g_free (job->text);
job->text = NULL;
}
if (job->pages) {
gint i;
for (i = 0; i < job->n_pages; i++) {
g_list_foreach (job->pages[i], (GFunc)g_free, NULL);
g_list_free (job->pages[i]);
}
g_free (job->pages);
job->pages = NULL;
}
(* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
}
static gboolean
ev_job_find_run (EvJob *job)
{
EvJobFind *job_find = EV_JOB_FIND (job);
EvDocumentFind *find = EV_DOCUMENT_FIND (job->document);
EvPage *ev_page;
GList *matches;
ev_debug_message (DEBUG_JOBS, NULL);
/* Do not block the main loop */
if (!ev_document_doc_mutex_trylock ())
return TRUE;
#ifdef EV_ENABLE_DEBUG
/* We use the #ifdef in this case because of the if */
if (job_find->current_page == job_find->start_page)
ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
#endif
ev_page = ev_document_get_page (job->document, job_find->current_page);
matches = ev_document_find_find_text (find, ev_page, job_find->text,
job_find->case_sensitive);
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;
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;
if (job_find->current_page == job_find->start_page) {
ev_job_succeeded (job);
return FALSE;
}
return TRUE;
}
static void
ev_job_find_class_init (EvJobFindClass *class)
{
EvJobClass *job_class = EV_JOB_CLASS (class);
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
job_class->run = ev_job_find_run;
gobject_class->dispose = ev_job_find_dispose;
job_find_signals[FIND_UPDATED] =
g_signal_new ("updated",
EV_TYPE_JOB_FIND,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (EvJobFindClass, updated),
NULL, NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE,
1, G_TYPE_INT);
}
EvJob *
ev_job_find_new (EvDocument *document,
gint start_page,
gint n_pages,
const gchar *text,
gboolean case_sensitive)
{
EvJobFind *job;
ev_debug_message (DEBUG_JOBS, NULL);
job = g_object_new (EV_TYPE_JOB_FIND, NULL);
EV_JOB (job)->document = g_object_ref (document);
job->start_page = start_page;
job->current_page = start_page;
job->n_pages = n_pages;
job->pages = g_new0 (GList *, n_pages);
job->text = g_strdup (text);
job->case_sensitive = case_sensitive;
job->has_results = FALSE;
return EV_JOB (job);
}
gint
ev_job_find_get_n_results (EvJobFind *job,
gint page)
{
return g_list_length (job->pages[page]);
}
gdouble
ev_job_find_get_progress (EvJobFind *job)
{
gint pages_done;
if (ev_job_is_finished (EV_JOB (job)))
return 1.0;
if (job->current_page > job->start_page) {
pages_done = job->current_page - job->start_page + 1;
} else if (job->current_page == job->start_page) {
pages_done = job->n_pages;
} else {
pages_done = job->n_pages - job->start_page + job->current_page;
}
return pages_done / (gdouble) job->n_pages;
}
gboolean
ev_job_find_has_results (EvJobFind *job)
{
return job->has_results;
}
GList **
ev_job_find_get_results (EvJobFind *job)
{
return job->pages;
}

View File

@ -57,6 +57,9 @@ typedef struct _EvJobSaveClass EvJobSaveClass;
typedef struct _EvJobPrint EvJobPrint;
typedef struct _EvJobPrintClass EvJobPrintClass;
typedef struct _EvJobFind EvJobFind;
typedef struct _EvJobFindClass EvJobFindClass;
#define EV_TYPE_JOB (ev_job_get_type())
#define EV_JOB(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB, EvJob))
#define EV_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB, EvJobClass))
@ -103,6 +106,11 @@ typedef struct _EvJobPrintClass EvJobPrintClass;
#define EV_JOB_PRINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_PRINT, EvJobPrintClass))
#define EV_IS_JOB_PRINT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_PRINT))
#define EV_TYPE_JOB_FIND (ev_job_find_get_type())
#define EV_JOB_FIND(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_FIND, EvJobFind))
#define EV_JOB_FIND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_FIND, EvJobFindClass))
#define EV_IS_JOB_FIND(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_FIND))
typedef enum {
EV_JOB_RUN_THREAD,
EV_JOB_RUN_MAIN_LOOP
@ -235,7 +243,8 @@ struct _EvJobFontsClass
EvJobClass parent_class;
/* Signals */
void (* updated) (EvJobFonts *job);
void (* updated) (EvJobFonts *job,
gdouble progress);
};
struct _EvJobLoad
@ -289,6 +298,28 @@ struct _EvJobPrintClass
EvJobClass parent_class;
};
struct _EvJobFind
{
EvJob parent;
gint start_page;
gint current_page;
gint n_pages;
GList **pages;
gchar *text;
gboolean case_sensitive;
gboolean has_results;
};
struct _EvJobFindClass
{
EvJobClass parent_class;
/* Signals */
void (* updated) (EvJobFind *job,
gint page);
};
/* Base job class */
GType ev_job_get_type (void) G_GNUC_CONST;
gboolean ev_job_run (EvJob *job);
@ -370,6 +401,18 @@ EvJob *ev_job_print_new (EvDocument *document,
gint copies,
gdouble collate,
gdouble reverse);
/* EvJobFind */
GType ev_job_find_get_type (void) G_GNUC_CONST;
EvJob *ev_job_find_new (EvDocument *document,
gint start_page,
gint n_pages,
const gchar *text,
gboolean case_sensitive);
gint ev_job_find_get_n_results (EvJobFind *job,
gint pages);
gdouble ev_job_find_get_progress (EvJobFind *job);
gboolean ev_job_find_has_results (EvJobFind *job);
GList **ev_job_find_get_results (EvJobFind *job);
G_END_DECLS

View File

@ -97,8 +97,9 @@ struct _EvView {
EvDocument *document;
char *find_status;
int find_result;
/* Find */
GList **find_pages;
gint find_result;
gboolean jump_to_find_result;
gboolean highlight_find_results;

View File

@ -29,7 +29,6 @@
#include <gdk/gdkkeysyms.h>
#include "ev-application.h"
#include "ev-document-find.h"
#include "ev-document-forms.h"
#include "ev-document-images.h"
#include "ev-document-links.h"
@ -53,7 +52,6 @@
enum {
PROP_0,
PROP_FIND_STATUS,
PROP_CONTINUOUS,
PROP_DUAL_PAGE,
PROP_FULLSCREEN,
@ -228,9 +226,6 @@ static void draw_loading_text (EvView *view,
GdkRectangle *expose_area);
/*** Callbacks ***/
static void find_changed_cb (EvDocument *document,
int page,
EvView *view);
static void job_finished_cb (EvPixbufCache *pixbuf_cache,
GdkRegion *region,
EvView *view);
@ -303,10 +298,11 @@ static void ev_view_handle_cursor_over_xy (EvView *view,
gint y);
/*** Find ***/
static void update_find_status_message (EvView *view,
gboolean this_page);
static void ev_view_set_find_status (EvView *view,
const char *message);
static gint ev_view_find_get_n_results (EvView *view,
gint page);
static EvRectangle *ev_view_find_get_result (EvView *view,
gint page,
gint result);
static void jump_to_find_result (EvView *view);
static void jump_to_find_page (EvView *view,
EvViewFindDirection direction,
@ -2547,7 +2543,7 @@ ev_view_expose_event (GtkWidget *widget,
draw_one_page (view, i, cr, &page_area, &border, &(event->area), &page_ready);
if (page_ready && EV_IS_DOCUMENT_FIND (view->document) && view->highlight_find_results)
if (page_ready && view->find_pages && view->highlight_find_results)
highlight_find_results (view, i);
}
@ -3608,15 +3604,12 @@ draw_rubberband (GtkWidget *widget, GdkWindow *window,
static void
highlight_find_results (EvView *view, int page)
{
EvDocumentFind *find;
int i, results = 0;
gint i, n_results = 0;
find = EV_DOCUMENT_FIND (view->document);
n_results = ev_view_find_get_n_results (view, page);
results = ev_document_find_get_n_results (find, page);
for (i = 0; i < results; i++) {
EvRectangle rectangle;
for (i = 0; i < n_results; i++) {
EvRectangle *rectangle;
GdkRectangle view_rectangle;
guchar alpha;
@ -3626,8 +3619,8 @@ highlight_find_results (EvView *view, int page)
alpha = 0x20;
}
ev_document_find_get_result (find, page, i, &rectangle);
doc_rect_to_view_rect (view, page, &rectangle, &view_rectangle);
rectangle = ev_view_find_get_result (view, page, i);
doc_rect_to_view_rect (view, page, rectangle, &view_rectangle);
draw_rubberband (GTK_WIDGET (view), view->layout.bin_window,
&view_rectangle, alpha);
}
@ -3822,8 +3815,6 @@ ev_view_finalize (GObject *object)
{
EvView *view = EV_VIEW (object);
g_free (view->find_status);
clear_selection (view);
clear_link_selected (view);
@ -3973,9 +3964,6 @@ ev_view_get_property (GObject *object,
EvView *view = EV_VIEW (object);
switch (prop_id) {
case PROP_FIND_STATUS:
g_value_set_string (value, view->find_status);
break;
case PROP_CONTINUOUS:
g_value_set_boolean (value, view->continuous);
break;
@ -4091,14 +4079,6 @@ ev_view_class_init (EvViewClass *class)
G_TYPE_OBJECT);
g_object_class_install_property (object_class,
PROP_FIND_STATUS,
g_param_spec_string ("find-status",
"Find Status Message",
"The find status message",
NULL,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_CONTINUOUS,
g_param_spec_boolean ("continuous",
@ -4223,25 +4203,6 @@ ev_view_init (EvView *view)
/*** Callbacks ***/
static void
find_changed_cb (EvDocument *document, int page, EvView *view)
{
double percent;
int n_pages;
percent = ev_document_find_get_progress
(EV_DOCUMENT_FIND (view->document));
n_pages = ev_page_cache_get_n_pages (view->page_cache);
if (view->jump_to_find_result == TRUE) {
jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0);
jump_to_find_result (view);
}
update_find_status_message (view, percent * n_pages >= n_pages - 1 );
if (view->current_page == page)
gtk_widget_queue_draw (GTK_WIDGET (view));
}
static void
ev_view_change_page (EvView *view,
gint new_page)
@ -4334,10 +4295,7 @@ page_changed_cb (EvPageCache *page_cache,
gtk_widget_queue_draw (GTK_WIDGET (view));
}
if (EV_IS_DOCUMENT_FIND (view->document)) {
view->find_result = 0;
update_find_status_message (view, TRUE);
}
view->find_result = 0;
}
static void
@ -4519,12 +4477,8 @@ ev_view_set_document (EvView *view,
clear_caches (view);
if (view->document) {
g_signal_handlers_disconnect_by_func (view->document,
find_changed_cb,
view);
g_object_unref (view->document);
view->page_cache = NULL;
}
view->document = document;
@ -4532,13 +4486,6 @@ ev_view_set_document (EvView *view,
if (view->document) {
g_object_ref (view->document);
if (EV_IS_DOCUMENT_FIND (view->document)) {
g_signal_connect (view->document,
"find_changed",
G_CALLBACK (find_changed_cb),
view);
}
setup_caches (view);
}
@ -5139,71 +5086,32 @@ ev_view_set_zoom_for_size (EvView *view,
}
/*** Find ***/
static void
update_find_status_message (EvView *view, gboolean this_page)
static gint
ev_view_find_get_n_results (EvView *view, gint page)
{
char *message;
if (this_page) {
int results;
results = ev_document_find_get_n_results
(EV_DOCUMENT_FIND (view->document),
view->current_page);
/* TRANS: Sometimes this could be better translated as
"%d hit(s) on this page". Therefore this string
contains plural cases. */
message = g_strdup_printf (ngettext ("%d found on this page",
"%d found on this page",
results),
results);
} else {
double percent;
percent = ev_document_find_get_progress
(EV_DOCUMENT_FIND (view->document));
message = g_strdup_printf (_("%3d%% remaining to search"),
(int) ((1.0 - percent) * 100));
}
ev_view_set_find_status (view, message);
g_free (message);
return view->find_pages ? g_list_length (view->find_pages[page]) : 0;
}
const char *
ev_view_get_find_status (EvView *view)
static EvRectangle *
ev_view_find_get_result (EvView *view, gint page, gint result)
{
g_return_val_if_fail (EV_IS_VIEW (view), NULL);
return view->find_status;
}
static void
ev_view_set_find_status (EvView *view, const char *message)
{
g_return_if_fail (EV_IS_VIEW (view));
g_free (view->find_status);
view->find_status = g_strdup (message);
g_object_notify (G_OBJECT (view), "find-status");
return view->find_pages ? (EvRectangle *) g_list_nth_data (view->find_pages[page], result) : NULL;
}
static void
jump_to_find_result (EvView *view)
{
EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
EvRectangle rect;
GdkRectangle view_rect;
int n_results;
int page = view->current_page;
gint n_results;
gint page = view->current_page;
n_results = ev_document_find_get_n_results (find, page);
n_results = ev_view_find_get_n_results (view, page);
if (n_results > 0 && view->find_result < n_results) {
ev_document_find_get_result
(find, page, view->find_result, &rect);
if (n_results > 0 && view->find_result < n_results) {
EvRectangle *rect;
GdkRectangle view_rect;
doc_rect_to_view_rect (view, page, &rect, &view_rect);
rect = ev_view_find_get_result (view, page, view->find_result);
doc_rect_to_view_rect (view, page, rect, &view_rect);
ensure_rectangle_is_visible (view, &view_rect);
}
}
@ -5226,7 +5134,6 @@ jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift)
n_pages = ev_page_cache_get_n_pages (view->page_cache);
for (i = 0; i < n_pages; i++) {
int has_results;
int page;
if (direction == EV_VIEW_FIND_NEXT)
@ -5237,53 +5144,39 @@ jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift)
if (page >= n_pages) {
page = page - n_pages;
}
if (page < 0)
} else if (page < 0)
page = page + n_pages;
has_results = ev_document_find_page_has_results
(EV_DOCUMENT_FIND (view->document), page);
if (has_results == -1) {
break;
} else if (has_results == 1) {
if (ev_view_find_get_n_results (view, page) > 0) {
ev_page_cache_set_current_page (view->page_cache, page);
break;
}
}
}
gboolean
ev_view_can_find_next (EvView *view)
void
ev_view_find_changed (EvView *view, GList **results, gint page)
{
if (EV_IS_DOCUMENT_FIND (view->document)) {
EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
int i, n_pages;
n_pages = ev_page_cache_get_n_pages (view->page_cache);
for (i = 0; i < n_pages; i++) {
if (ev_document_find_get_n_results (find, i) > 0) {
return TRUE;
}
}
view->find_pages = results;
if (view->jump_to_find_result == TRUE) {
jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0);
jump_to_find_result (view);
}
return FALSE;
if (view->current_page == page)
gtk_widget_queue_draw (GTK_WIDGET (view));
}
void
ev_view_find_next (EvView *view)
{
int n_results, n_pages;
EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
n_results = ev_document_find_get_n_results (find, view->current_page);
n_pages = ev_page_cache_get_n_pages (view->page_cache);
gint n_results;
n_results = ev_view_find_get_n_results (view, view->current_page);
view->find_result++;
if (view->find_result >= n_results) {
view->find_result = 0;
jump_to_find_page (view, EV_VIEW_FIND_NEXT, 1);
jump_to_find_result (view);
@ -5293,42 +5186,14 @@ ev_view_find_next (EvView *view)
}
}
gboolean
ev_view_can_find_previous (EvView *view)
{
if (EV_IS_DOCUMENT_FIND (view->document)) {
EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
int i, n_pages;
n_pages = ev_page_cache_get_n_pages (view->page_cache);
for (i = n_pages - 1; i >= 0; i--) {
if (ev_document_find_get_n_results (find, i) > 0) {
return TRUE;
}
}
}
return FALSE;
}
void
ev_view_find_previous (EvView *view)
{
int n_results, n_pages;
EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
EvPageCache *page_cache;
page_cache = ev_page_cache_get (view->document);
n_results = ev_document_find_get_n_results (find, view->current_page);
n_pages = ev_page_cache_get_n_pages (page_cache);
view->find_result--;
if (view->find_result < 0) {
jump_to_find_page (view, EV_VIEW_FIND_PREV, -1);
view->find_result = ev_document_find_get_n_results (find, view->current_page) - 1;
view->find_result = ev_view_find_get_n_results (view, view->current_page) - 1;
jump_to_find_result (view);
} else {
jump_to_find_result (view);
@ -5337,14 +5202,15 @@ ev_view_find_previous (EvView *view)
}
void
ev_view_search_changed (EvView *view)
ev_view_find_search_changed (EvView *view)
{
/* search string has changed, focus on new search result */
view->jump_to_find_result = TRUE;
view->find_pages = NULL;
}
void
ev_view_set_highlight_search (EvView *view, gboolean value)
ev_view_find_set_highlight_search (EvView *view, gboolean value)
{
view->highlight_find_results = value;
gtk_widget_queue_draw (GTK_WIDGET (view));
@ -5353,11 +5219,7 @@ ev_view_set_highlight_search (EvView *view, gboolean value)
void
ev_view_find_cancel (EvView *view)
{
if (EV_IS_DOCUMENT_FIND (view->document)) {
EvDocumentFind *find = EV_DOCUMENT_FIND (view->document);
ev_document_find_cancel (find);
}
view->find_pages = NULL;
}
/*** Selections ***/

View File

@ -117,18 +117,15 @@ void ev_view_set_rotation (EvView *view,
int ev_view_get_rotation (EvView *view);
/* Find */
gboolean ev_view_can_find_next (EvView *view);
void ev_view_find_next (EvView *view);
gboolean ev_view_can_find_previous (EvView *view);
void ev_view_find_previous (EvView *view);
void ev_view_search_changed (EvView *view);
void ev_view_set_highlight_search (EvView *view,
gboolean value);
void ev_view_find_cancel (EvView *view);
/* Status */
const char *ev_view_get_status (EvView *view);
const char *ev_view_get_find_status (EvView *view);
void ev_view_find_next (EvView *view);
void ev_view_find_previous (EvView *view);
void ev_view_find_search_changed (EvView *view);
void ev_view_find_set_highlight_search (EvView *view,
gboolean value);
void ev_view_find_changed (EvView *view,
GList **results,
gint page);
void ev_view_find_cancel (EvView *view);
/* Cursor */
void ev_view_hide_cursor (EvView *view);

View File

@ -179,6 +179,7 @@ struct _EvWindowPrivate {
EvJob *thumbnail_job;
EvJob *save_job;
EvJob *print_job;
EvJob *find_job;
/* Printing */
gboolean print_preview;
@ -275,6 +276,7 @@ static void ev_window_cmd_view_page_width (GtkAction *action,
static void view_handle_link_cb (EvView *view,
EvLink *link,
EvWindow *window);
static void ev_window_update_find_status_message (EvWindow *ev_window);
static void ev_window_cmd_edit_find (GtkAction *action,
EvWindow *ev_window);
static void find_bar_search_changed_cb (EggFindBar *find_bar,
@ -396,6 +398,7 @@ ev_window_update_actions (EvWindow *ev_window)
int n_pages = 0, page = -1;
gboolean has_pages = FALSE;
gboolean presentation_mode;
gboolean can_find_in_page = FALSE;
if (ev_window->priv->document && ev_window->priv->page_cache) {
page = ev_page_cache_get_current_page (ev_window->priv->page_cache);
@ -403,13 +406,16 @@ ev_window_update_actions (EvWindow *ev_window)
has_pages = n_pages > 0;
}
can_find_in_page = (ev_window->priv->find_job &&
ev_job_find_has_results (EV_JOB_FIND (ev_window->priv->find_job)));
ev_window_set_action_sensitive (ev_window, "EditCopy",
has_pages &&
ev_view_get_has_selection (view));
ev_window_set_action_sensitive (ev_window, "EditFindNext",
ev_view_can_find_next (view));
has_pages && can_find_in_page);
ev_window_set_action_sensitive (ev_window, "EditFindPrevious",
ev_view_can_find_previous (view));
has_pages && can_find_in_page);
presentation_mode = ev_view_get_presentation (view);
@ -687,19 +693,15 @@ ev_window_warning_message (GtkWindow *window, const gchar *msg)
ev_window_set_message_area (EV_WINDOW (window), area);
}
static void
find_changed_cb (EvDocument *document, int page, EvWindow *ev_window)
{
ev_window_update_actions (ev_window);
}
static void
page_changed_cb (EvPageCache *page_cache,
gint page,
EvWindow *ev_window)
{
ev_window_update_actions (ev_window);
ev_window_update_find_status_message (ev_window);
if (!ev_window_is_empty (ev_window))
ev_metadata_manager_set_int (ev_window->priv->uri, "page", page);
}
@ -1142,13 +1144,6 @@ ev_window_setup_document (EvWindow *ev_window)
ev_window->priv->setup_document_idle = 0;
if (EV_IS_DOCUMENT_FIND (document)) {
g_signal_connect_object (G_OBJECT (document),
"find_changed",
G_CALLBACK (find_changed_cb),
ev_window, 0);
}
ev_window_refresh_window_thumbnail (ev_window, 0);
ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT);
@ -4019,15 +4014,73 @@ attachment_bar_menu_popup_cb (EvSidebarAttachments *attachbar,
}
static void
view_find_status_changed_cb (EvView *view,
GParamSpec *pspec,
EvWindow *ev_window)
ev_window_update_find_status_message (EvWindow *ev_window)
{
const char *text;
gchar *message;
text = ev_view_get_find_status (view);
egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
text);
if (!ev_window->priv->find_job)
return;
if (ev_job_is_finished (ev_window->priv->find_job)) {
gint n_results;
n_results = ev_job_find_get_n_results (EV_JOB_FIND (ev_window->priv->find_job),
ev_page_cache_get_current_page (ev_window->priv->page_cache));
/* TRANS: Sometimes this could be better translated as
"%d hit(s) on this page". Therefore this string
contains plural cases. */
message = g_strdup_printf (ngettext ("%d found on this page",
"%d found on this page",
n_results),
n_results);
} else {
gdouble percent;
percent = ev_job_find_get_progress (EV_JOB_FIND (ev_window->priv->find_job));
message = g_strdup_printf (_("%3d%% remaining to search"),
(gint) ((1.0 - percent) * 100));
}
egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), message);
g_free (message);
}
static void
ev_window_find_job_finished_cb (EvJobFind *job,
EvWindow *ev_window)
{
ev_window_update_find_status_message (ev_window);
}
static void
ev_window_find_job_updated_cb (EvJobFind *job,
gint page,
EvWindow *ev_window)
{
ev_window_update_actions (ev_window);
ev_view_find_changed (EV_VIEW (ev_window->priv->view),
ev_job_find_get_results (job),
page);
ev_window_update_find_status_message (ev_window);
}
static void
ev_window_clear_find_job (EvWindow *ev_window)
{
if (ev_window->priv->find_job != NULL) {
if (!ev_job_is_finished (ev_window->priv->find_job))
ev_job_cancel (ev_window->priv->find_job);
g_signal_handlers_disconnect_by_func (ev_window->priv->find_job,
ev_window_find_job_finished_cb,
ev_window);
g_signal_handlers_disconnect_by_func (ev_window->priv->find_job,
ev_window_find_job_updated_cb,
ev_window);
g_object_unref (ev_window->priv->find_job);
ev_window->priv->find_job = NULL;
}
}
static void
@ -4049,6 +4102,7 @@ find_bar_close_cb (EggFindBar *find_bar,
EvWindow *ev_window)
{
ev_view_find_cancel (EV_VIEW (ev_window->priv->view));
ev_window_clear_find_job (ev_window);
update_chrome_flag (ev_window, EV_CHROME_FINDBAR, FALSE);
update_chrome_visibility (ev_window);
}
@ -4061,39 +4115,42 @@ find_bar_search_changed_cb (EggFindBar *find_bar,
gboolean case_sensitive;
const char *search_string;
if (!ev_window->priv->document || !EV_IS_DOCUMENT_FIND (ev_window->priv->document))
return;
/* Either the string or case sensitivity could have changed. */
case_sensitive = egg_find_bar_get_case_sensitive (find_bar);
search_string = egg_find_bar_get_search_string (find_bar);
ev_view_search_changed (EV_VIEW(ev_window->priv->view));
ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
if (ev_window->priv->document &&
EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
if (search_string && search_string[0]) {
ev_document_doc_mutex_lock ();
ev_document_find_begin (EV_DOCUMENT_FIND (ev_window->priv->document),
ev_page_cache_get_current_page (ev_window->priv->page_cache),
search_string,
case_sensitive);
ev_document_doc_mutex_unlock ();
} else {
ev_document_doc_mutex_lock ();
ev_document_find_cancel (EV_DOCUMENT_FIND (ev_window->priv->document));
ev_document_doc_mutex_unlock ();
ev_window_clear_find_job (ev_window);
ev_window_update_actions (ev_window);
egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
NULL);
gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
}
if (search_string && search_string[0]) {
ev_window->priv->find_job = ev_job_find_new (ev_window->priv->document,
ev_page_cache_get_current_page (ev_window->priv->page_cache),
ev_page_cache_get_n_pages (ev_window->priv->page_cache),
search_string,
case_sensitive);
g_signal_connect (ev_window->priv->find_job, "finished",
G_CALLBACK (ev_window_find_job_finished_cb),
ev_window);
g_signal_connect (ev_window->priv->find_job, "updated",
G_CALLBACK (ev_window_find_job_updated_cb),
ev_window);
ev_job_scheduler_push_job (ev_window->priv->find_job, EV_JOB_PRIORITY_NONE);
} else {
ev_window_update_actions (ev_window);
egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar),
NULL);
gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
}
}
static void
find_bar_visibility_changed_cb (EggFindBar *find_bar,
GParamSpec *param,
EvWindow *ev_window)
GParamSpec *param,
EvWindow *ev_window)
{
gboolean visible;
@ -4101,8 +4158,8 @@ find_bar_visibility_changed_cb (EggFindBar *find_bar,
if (ev_window->priv->document &&
EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
ev_view_set_highlight_search (EV_VIEW (ev_window->priv->view), visible);
ev_view_search_changed (EV_VIEW (ev_window->priv->view));
ev_view_find_set_highlight_search (EV_VIEW (ev_window->priv->view), visible);
ev_view_find_search_changed (EV_VIEW (ev_window->priv->view));
ev_window_update_actions (ev_window);
if (visible)
@ -4115,7 +4172,7 @@ find_bar_visibility_changed_cb (EggFindBar *find_bar,
static void
find_bar_scroll(EggFindBar *find_bar, GtkScrollType scroll, EvWindow* ev_window)
{
ev_view_scroll(EV_VIEW(ev_window->priv->view), scroll, FALSE);
ev_view_scroll (EV_VIEW (ev_window->priv->view), scroll, FALSE);
}
static void
@ -4257,6 +4314,10 @@ ev_window_dispose (GObject *object)
if (priv->thumbnail_job) {
ev_window_clear_thumbnail_job (window);
}
if (priv->find_job) {
ev_window_clear_find_job (window);
}
if (priv->local_uri) {
ev_window_clear_local_uri (window);
@ -5489,10 +5550,6 @@ ev_window_init (EvWindow *ev_window)
gtk_container_add (GTK_CONTAINER (ev_window->priv->scrolled_window),
ev_window->priv->view);
g_signal_connect (ev_window->priv->view,
"notify::find-status",
G_CALLBACK (view_find_status_changed_cb),
ev_window);
g_signal_connect (ev_window->priv->view,
"notify::sizing-mode",
G_CALLBACK (ev_window_sizing_mode_changed_cb),