Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0376d06670 |
7 changed files with 919 additions and 113 deletions
|
|
@ -7509,6 +7509,14 @@ ev_view_find_previous (EvView *view)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ev_view_find_set_result (EvView *view, gint page, gint result)
|
||||
{
|
||||
ev_document_model_set_page (view->model, page);
|
||||
view->find_result = result;
|
||||
jump_to_find_result (view);
|
||||
}
|
||||
|
||||
void
|
||||
ev_view_find_search_changed (EvView *view)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ void ev_view_zoom (EvView *view,
|
|||
/* Find */
|
||||
void ev_view_find_next (EvView *view);
|
||||
void ev_view_find_previous (EvView *view);
|
||||
void ev_view_find_set_result (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);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ atril_SOURCES= \
|
|||
ev-bookmark-action.c \
|
||||
ev-application.c \
|
||||
ev-application.h \
|
||||
ev-find-sidebar.h \
|
||||
ev-find-sidebar.c \
|
||||
ev-file-monitor.h \
|
||||
ev-file-monitor.c \
|
||||
ev-history.c \
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ struct _EggFindBarPrivate
|
|||
GtkWidget *find_entry;
|
||||
GtkWidget *status_label;
|
||||
|
||||
gulong set_focus_handler;
|
||||
guint case_sensitive : 1;
|
||||
};
|
||||
|
||||
|
|
@ -91,9 +90,6 @@ egg_find_bar_class_init (EggFindBarClass *klass)
|
|||
|
||||
object_class->finalize = egg_find_bar_finalize;
|
||||
|
||||
widget_class->show = egg_find_bar_show;
|
||||
widget_class->hide = egg_find_bar_hide;
|
||||
|
||||
widget_class->grab_focus = egg_find_bar_grab_focus;
|
||||
|
||||
find_bar_signals[NEXT] =
|
||||
|
|
@ -256,27 +252,6 @@ entry_changed_callback (GtkEntry *entry,
|
|||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
set_focus_cb (GtkWidget *window,
|
||||
GtkWidget *widget,
|
||||
EggFindBar *bar)
|
||||
{
|
||||
GtkWidget *wbar = GTK_WIDGET (bar);
|
||||
|
||||
while (widget != NULL && widget != wbar)
|
||||
{
|
||||
widget = gtk_widget_get_parent (widget);
|
||||
}
|
||||
|
||||
/* if widget == bar, the new focus widget is in the bar, so we
|
||||
* don't deactivate.
|
||||
*/
|
||||
if (widget != wbar)
|
||||
{
|
||||
g_signal_emit (bar, find_bar_signals[CLOSE], 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
egg_find_bar_init (EggFindBar *find_bar)
|
||||
{
|
||||
|
|
@ -443,46 +418,6 @@ egg_find_bar_get_property (GObject *object,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
egg_find_bar_show (GtkWidget *widget)
|
||||
{
|
||||
EggFindBar *bar = EGG_FIND_BAR (widget);
|
||||
EggFindBarPrivate *priv = bar->priv;
|
||||
|
||||
GTK_WIDGET_CLASS (egg_find_bar_parent_class)->show (widget);
|
||||
|
||||
if (priv->set_focus_handler == 0)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
|
||||
priv->set_focus_handler =
|
||||
g_signal_connect (toplevel, "set-focus",
|
||||
G_CALLBACK (set_focus_cb), bar);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
egg_find_bar_hide (GtkWidget *widget)
|
||||
{
|
||||
EggFindBar *bar = EGG_FIND_BAR (widget);
|
||||
EggFindBarPrivate *priv = bar->priv;
|
||||
|
||||
if (priv->set_focus_handler != 0)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
|
||||
g_signal_handlers_disconnect_by_func
|
||||
(toplevel, (void (*)) G_CALLBACK (set_focus_cb), bar);
|
||||
priv->set_focus_handler = 0;
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (egg_find_bar_parent_class)->hide (widget);
|
||||
}
|
||||
|
||||
void
|
||||
egg_find_bar_grab_focus (GtkWidget *widget)
|
||||
{
|
||||
|
|
|
|||
681
shell/ev-find-sidebar.c
Normal file
681
shell/ev-find-sidebar.c
Normal file
|
|
@ -0,0 +1,681 @@
|
|||
/* ev-find-sidebar.c
|
||||
* this file is part of evince, a gnome document viewer
|
||||
*
|
||||
* Copyright (C) 2013 Carlos Garcia Campos <carlosgc@gnome.org>
|
||||
* Copyright (C) 2008 Sergey Pushkin <pushkinsv@gmail.com >
|
||||
*
|
||||
* Evince 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Evince 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "ev-find-sidebar.h"
|
||||
|
||||
#include "ev-document-text.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
GtkWidget *tree_view;
|
||||
|
||||
guint selection_id;
|
||||
guint process_matches_idle_id;
|
||||
|
||||
GtkTreePath *highlighted_result;
|
||||
gint first_match_page;
|
||||
|
||||
EvJobFind *job;
|
||||
gint job_current_page;
|
||||
gint current_page;
|
||||
gint insert_position;
|
||||
} EvFindSidebarPrivate;
|
||||
|
||||
enum {
|
||||
TEXT_COLUMN,
|
||||
PAGE_LABEL_COLUMN,
|
||||
PAGE_COLUMN,
|
||||
RESULT_COLUMN,
|
||||
|
||||
N_COLUMNS
|
||||
};
|
||||
|
||||
enum {
|
||||
RESULT_ACTIVATED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS];
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EvFindSidebar, ev_find_sidebar, GTK_TYPE_BOX)
|
||||
|
||||
#define GET_PRIVATE(o) ev_find_sidebar_get_instance_private (o)
|
||||
|
||||
static void
|
||||
ev_find_sidebar_cancel (EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
|
||||
if (priv->process_matches_idle_id > 0) {
|
||||
g_source_remove (priv->process_matches_idle_id);
|
||||
priv->process_matches_idle_id = 0;
|
||||
}
|
||||
g_clear_object (&priv->job);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_find_sidebar_dispose (GObject *object)
|
||||
{
|
||||
EvFindSidebar *sidebar = EV_FIND_SIDEBAR (object);
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
|
||||
ev_find_sidebar_cancel (sidebar);
|
||||
g_clear_pointer (&(priv->highlighted_result), gtk_tree_path_free);
|
||||
|
||||
G_OBJECT_CLASS (ev_find_sidebar_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_find_sidebar_class_init (EvFindSidebarClass *find_sidebar_class)
|
||||
{
|
||||
GObjectClass *g_object_class = G_OBJECT_CLASS (find_sidebar_class);
|
||||
|
||||
g_object_class->dispose = ev_find_sidebar_dispose;
|
||||
|
||||
signals[RESULT_ACTIVATED] =
|
||||
g_signal_new ("result-activated",
|
||||
G_TYPE_FROM_CLASS (g_object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_generic,
|
||||
G_TYPE_NONE, 2,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_INT);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_find_sidebar_activate_result_at_iter (EvFindSidebar *sidebar,
|
||||
GtkTreeModel *model,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
gint page;
|
||||
gint result;
|
||||
|
||||
|
||||
if (priv->highlighted_result)
|
||||
gtk_tree_path_free (priv->highlighted_result);
|
||||
priv->highlighted_result = gtk_tree_model_get_path (model, iter);
|
||||
|
||||
gtk_tree_model_get (model, iter,
|
||||
PAGE_COLUMN, &page,
|
||||
RESULT_COLUMN, &result,
|
||||
-1);
|
||||
g_signal_emit (sidebar, signals[RESULT_ACTIVATED], 0, page - 1, result);
|
||||
}
|
||||
|
||||
static void
|
||||
selection_changed_callback (GtkTreeSelection *selection,
|
||||
EvFindSidebar *sidebar)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (gtk_tree_selection_get_selected (selection, &model, &iter))
|
||||
ev_find_sidebar_activate_result_at_iter (sidebar, model, &iter);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sidebar_tree_button_press_cb (GtkTreeView *view,
|
||||
GdkEventButton *event,
|
||||
EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
GtkTreeModel *model;
|
||||
GtkTreePath *path;
|
||||
GtkTreeIter iter;
|
||||
|
||||
gtk_tree_view_get_path_at_pos (view, event->x, event->y, &path,
|
||||
NULL, NULL, NULL);
|
||||
if (!path)
|
||||
return FALSE;
|
||||
|
||||
if (priv->highlighted_result &&
|
||||
gtk_tree_path_compare (priv->highlighted_result, path) != 0) {
|
||||
gtk_tree_path_free (path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
model = gtk_tree_view_get_model (view);
|
||||
gtk_tree_model_get_iter (model, &iter, path);
|
||||
gtk_tree_path_free (path);
|
||||
|
||||
ev_find_sidebar_activate_result_at_iter (sidebar, model, &iter);
|
||||
|
||||
/* Always return FALSE so the tree view gets the event and can update
|
||||
* the selection etc.
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ev_find_sidebar_reset_model (EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
GtkListStore *model;
|
||||
|
||||
model = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
|
||||
gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view),
|
||||
GTK_TREE_MODEL (model));
|
||||
g_object_unref (model);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_find_sidebar_init (EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv;
|
||||
GtkWidget *swindow;
|
||||
GtkTreeViewColumn *column;
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
priv = GET_PRIVATE (sidebar);
|
||||
|
||||
swindow = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
|
||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
|
||||
priv->tree_view = gtk_tree_view_new ();
|
||||
ev_find_sidebar_reset_model (sidebar);
|
||||
|
||||
gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->tree_view), -1);
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
|
||||
gtk_container_add (GTK_CONTAINER (swindow), priv->tree_view);
|
||||
gtk_widget_show (priv->tree_view);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (sidebar), swindow, TRUE, TRUE, 0);
|
||||
gtk_widget_show (swindow);
|
||||
|
||||
column = gtk_tree_view_column_new ();
|
||||
gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), column);
|
||||
|
||||
renderer = (GtkCellRenderer *)g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
|
||||
"ellipsize",
|
||||
PANGO_ELLIPSIZE_END,
|
||||
NULL);
|
||||
gtk_tree_view_column_pack_start (GTK_TREE_VIEW_COLUMN (column), renderer, TRUE);
|
||||
gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer,
|
||||
"markup", TEXT_COLUMN,
|
||||
NULL);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_end (GTK_TREE_VIEW_COLUMN (column), renderer, FALSE);
|
||||
gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer,
|
||||
"text", PAGE_LABEL_COLUMN,
|
||||
NULL);
|
||||
g_object_set (G_OBJECT (renderer), "style", PANGO_STYLE_ITALIC, NULL);
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
|
||||
priv->selection_id = g_signal_connect (selection, "changed",
|
||||
G_CALLBACK (selection_changed_callback),
|
||||
sidebar);
|
||||
g_signal_connect (priv->tree_view, "button-press-event",
|
||||
G_CALLBACK (sidebar_tree_button_press_cb),
|
||||
sidebar);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
ev_find_sidebar_new (void)
|
||||
{
|
||||
return g_object_new (EV_TYPE_FIND_SIDEBAR,
|
||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_find_sidebar_select_highlighted_result (EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
GtkTreeSelection *selection;
|
||||
|
||||
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
|
||||
|
||||
g_signal_handler_block (selection, priv->selection_id);
|
||||
gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->tree_view), priv->highlighted_result, NULL, FALSE);
|
||||
g_signal_handler_unblock (selection, priv->selection_id);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_find_sidebar_highlight_first_match_of_page (EvFindSidebar *sidebar,
|
||||
gint page)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
gint index = 0;
|
||||
gint i;
|
||||
|
||||
if (!priv->job)
|
||||
return;
|
||||
|
||||
for (i = 0; i < page; i++)
|
||||
index += ev_job_find_get_n_results (priv->job, i);
|
||||
|
||||
if (priv->highlighted_result)
|
||||
gtk_tree_path_free (priv->highlighted_result);
|
||||
priv->highlighted_result = gtk_tree_path_new_from_indices (index, -1);
|
||||
ev_find_sidebar_select_highlighted_result (sidebar);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
sanitized_substring (const gchar *text,
|
||||
gint start,
|
||||
gint end)
|
||||
{
|
||||
const gchar *p;
|
||||
const gchar *start_ptr;
|
||||
const gchar *end_ptr;
|
||||
guint len = 0;
|
||||
gchar *retval;
|
||||
|
||||
if (end - start <= 0)
|
||||
return NULL;
|
||||
|
||||
start_ptr = g_utf8_offset_to_pointer (text, start);
|
||||
end_ptr = g_utf8_offset_to_pointer (start_ptr, end - start);
|
||||
|
||||
retval = g_malloc (end_ptr - start_ptr + 1);
|
||||
p = start_ptr;
|
||||
|
||||
while (p != end_ptr) {
|
||||
const gchar *next;
|
||||
|
||||
next = g_utf8_next_char (p);
|
||||
|
||||
if (next != end_ptr) {
|
||||
GUnicodeBreakType break_type;
|
||||
|
||||
break_type = g_unichar_break_type (g_utf8_get_char (p));
|
||||
if (break_type == G_UNICODE_BREAK_HYPHEN && *next == '\n') {
|
||||
p = g_utf8_next_char (next);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p != '\n') {
|
||||
strncpy (retval + len, p, next - p);
|
||||
len += next - p;
|
||||
} else {
|
||||
*(retval + len) = ' ';
|
||||
len++;
|
||||
}
|
||||
|
||||
p = next;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
g_free (retval);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval[len] = 0;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_surrounding_text_markup (const gchar *text,
|
||||
const gchar *find_text,
|
||||
gboolean case_sensitive,
|
||||
PangoLogAttr *log_attrs,
|
||||
gint log_attrs_length,
|
||||
gint offset)
|
||||
{
|
||||
gint iter;
|
||||
gchar *prec = NULL;
|
||||
gchar *succ = NULL;
|
||||
gchar *match = NULL;
|
||||
gchar *markup;
|
||||
gint max_chars;
|
||||
|
||||
iter = MAX (0, offset - 1);
|
||||
while (!log_attrs[iter].is_word_start && iter > 0)
|
||||
iter--;
|
||||
|
||||
prec = sanitized_substring (text, iter, offset);
|
||||
|
||||
iter = offset;
|
||||
offset += g_utf8_strlen (find_text, -1);
|
||||
if (!case_sensitive)
|
||||
match = g_utf8_substring (text, iter, offset);
|
||||
|
||||
iter = MIN (log_attrs_length, offset + 1);
|
||||
max_chars = MIN (log_attrs_length - 1, iter + 100);
|
||||
while (TRUE) {
|
||||
gint word = iter;
|
||||
|
||||
while (!log_attrs[word].is_word_end && word < max_chars)
|
||||
word++;
|
||||
|
||||
if (word > max_chars)
|
||||
break;
|
||||
|
||||
iter = word + 1;
|
||||
}
|
||||
|
||||
succ = sanitized_substring (text, offset, iter);
|
||||
|
||||
markup = g_markup_printf_escaped ("%s<span weight=\"bold\">%s</span>%s",
|
||||
prec ? prec : "", match ? match : find_text, succ ? succ : "");
|
||||
g_free (prec);
|
||||
g_free (succ);
|
||||
g_free (match);
|
||||
|
||||
return markup;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_page_text (EvDocument *document,
|
||||
EvPage *page,
|
||||
EvRectangle **areas,
|
||||
guint *n_areas)
|
||||
{
|
||||
gchar *text;
|
||||
gboolean success;
|
||||
|
||||
ev_document_doc_mutex_lock ();
|
||||
text = ev_document_text_get_text (EV_DOCUMENT_TEXT (document), page);
|
||||
success = ev_document_text_get_text_layout (EV_DOCUMENT_TEXT (document), page, areas, n_areas);
|
||||
ev_document_doc_mutex_unlock ();
|
||||
|
||||
if (!success) {
|
||||
g_free (text);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
static gint
|
||||
get_match_offset (EvRectangle *areas,
|
||||
guint n_areas,
|
||||
EvRectangle *match,
|
||||
gint offset)
|
||||
{
|
||||
gdouble x, y;
|
||||
gint i;
|
||||
|
||||
x = match->x1;
|
||||
y = (match->y1 + match->y2) / 2;
|
||||
|
||||
i = offset;
|
||||
|
||||
do {
|
||||
EvRectangle *area = areas + i;
|
||||
|
||||
if (x >= area->x1 && x < area->x2 &&
|
||||
y >= area->y1 && y <= area->y2) {
|
||||
return i;
|
||||
}
|
||||
|
||||
i = (i + 1) % n_areas;
|
||||
} while (i != offset);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_matches_idle (EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
GtkTreeModel *model;
|
||||
gint current_page;
|
||||
EvDocument *document;
|
||||
|
||||
priv->process_matches_idle_id = 0;
|
||||
|
||||
if (!ev_job_find_has_results (priv->job)) {
|
||||
if (ev_job_is_finished (EV_JOB (priv->job)))
|
||||
g_clear_object (&priv->job);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
document = EV_JOB (priv->job)->document;
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
|
||||
|
||||
do {
|
||||
GList *matches, *l;
|
||||
EvPage *page;
|
||||
gint result;
|
||||
gchar *page_label;
|
||||
gchar *page_text;
|
||||
EvRectangle *areas = NULL;
|
||||
guint n_areas;
|
||||
PangoLogAttr *text_log_attrs;
|
||||
gulong text_log_attrs_length;
|
||||
gint offset;
|
||||
|
||||
current_page = priv->current_page;
|
||||
priv->current_page = (priv->current_page + 1) % priv->job->n_pages;
|
||||
|
||||
matches = priv->job->pages[current_page];
|
||||
if (!matches)
|
||||
continue;
|
||||
|
||||
page = ev_document_get_page (document, current_page);
|
||||
page_label = ev_document_get_page_label (document, current_page);
|
||||
page_text = get_page_text (document, page, &areas, &n_areas);
|
||||
g_object_unref (page);
|
||||
if (!page_text)
|
||||
continue;
|
||||
|
||||
text_log_attrs_length = g_utf8_strlen (page_text, -1);
|
||||
text_log_attrs = g_new0 (PangoLogAttr, text_log_attrs_length + 1);
|
||||
pango_get_log_attrs (page_text, -1, -1, NULL, text_log_attrs, text_log_attrs_length + 1);
|
||||
|
||||
if (priv->first_match_page == -1)
|
||||
priv->first_match_page = current_page;
|
||||
|
||||
offset = 0;
|
||||
|
||||
for (l = matches, result = 0; l; l = g_list_next (l), result++) {
|
||||
EvRectangle *match = (EvRectangle *)l->data;
|
||||
gchar *markup;
|
||||
GtkTreeIter iter;
|
||||
gint new_offset;
|
||||
|
||||
new_offset = get_match_offset (areas, n_areas, match, offset);
|
||||
if (new_offset == -1) {
|
||||
g_warning ("No offset found for match \"%s\" at page %d after processing %d results\n",
|
||||
priv->job->text, current_page, result);
|
||||
/* It may happen that a vertical text match has no corresponding text area, skip
|
||||
* that but keep iterating to show any other matches in page (issue #1545) */
|
||||
continue;
|
||||
}
|
||||
offset = new_offset;
|
||||
|
||||
if (current_page >= priv->job->start_page) {
|
||||
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
|
||||
} else {
|
||||
gtk_list_store_insert (GTK_LIST_STORE (model), &iter,
|
||||
priv->insert_position);
|
||||
priv->insert_position++;
|
||||
}
|
||||
|
||||
markup = get_surrounding_text_markup (page_text,
|
||||
priv->job->text,
|
||||
priv->job->case_sensitive,
|
||||
text_log_attrs,
|
||||
text_log_attrs_length,
|
||||
offset);
|
||||
|
||||
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
|
||||
TEXT_COLUMN, markup,
|
||||
PAGE_LABEL_COLUMN, page_label,
|
||||
PAGE_COLUMN, current_page + 1,
|
||||
RESULT_COLUMN, result,
|
||||
-1);
|
||||
g_free (markup);
|
||||
}
|
||||
|
||||
g_free (page_label);
|
||||
g_free (page_text);
|
||||
g_free (text_log_attrs);
|
||||
g_free (areas);
|
||||
} while (current_page != priv->job_current_page);
|
||||
|
||||
if (ev_job_is_finished (EV_JOB (priv->job)) && priv->current_page == priv->job->start_page)
|
||||
ev_find_sidebar_highlight_first_match_of_page (sidebar, priv->first_match_page);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
find_job_updated_cb (EvJobFind *job,
|
||||
gint page,
|
||||
EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
|
||||
priv->job_current_page = page;
|
||||
}
|
||||
|
||||
static void
|
||||
find_job_cancelled_cb (EvJob *job,
|
||||
EvFindSidebar *sidebar)
|
||||
{
|
||||
ev_find_sidebar_cancel (sidebar);
|
||||
}
|
||||
|
||||
void
|
||||
ev_find_sidebar_start (EvFindSidebar *sidebar,
|
||||
EvJobFind *job)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
|
||||
if (priv->job == job)
|
||||
return;
|
||||
|
||||
ev_find_sidebar_clear (sidebar);
|
||||
priv->job = g_object_ref (job);
|
||||
g_signal_connect_object (job, "updated",
|
||||
G_CALLBACK (find_job_updated_cb),
|
||||
sidebar, 0);
|
||||
g_signal_connect_object (job, "cancelled",
|
||||
G_CALLBACK (find_job_cancelled_cb),
|
||||
sidebar, 0);
|
||||
priv->job_current_page = -1;
|
||||
priv->first_match_page = -1;
|
||||
priv->current_page = job->start_page;
|
||||
priv->insert_position = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ev_find_sidebar_restart (EvFindSidebar *sidebar,
|
||||
gint page)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
gint first_match_page = -1;
|
||||
gint i;
|
||||
|
||||
if (!priv->job)
|
||||
return;
|
||||
|
||||
for (i = 0; i < priv->job->n_pages; i++) {
|
||||
int index;
|
||||
|
||||
index = page + i;
|
||||
|
||||
if (index >= priv->job->n_pages)
|
||||
index -= priv->job->n_pages;
|
||||
|
||||
if (priv->job->pages[index]) {
|
||||
first_match_page = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first_match_page != -1)
|
||||
ev_find_sidebar_highlight_first_match_of_page (sidebar, first_match_page);
|
||||
}
|
||||
|
||||
void
|
||||
ev_find_sidebar_update (EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
|
||||
if (!priv->job)
|
||||
return;
|
||||
|
||||
if (priv->process_matches_idle_id == 0)
|
||||
priv->process_matches_idle_id = g_idle_add ((GSourceFunc)process_matches_idle, sidebar);
|
||||
}
|
||||
|
||||
void
|
||||
ev_find_sidebar_clear (EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
|
||||
ev_find_sidebar_cancel (sidebar);
|
||||
|
||||
/* It seems it's more efficient to set a new model in the tree view instead of
|
||||
* clearing the model that would emit row-deleted signal for every row in the model
|
||||
*/
|
||||
ev_find_sidebar_reset_model (sidebar);
|
||||
g_clear_pointer (&priv->highlighted_result, gtk_tree_path_free);
|
||||
}
|
||||
|
||||
void
|
||||
ev_find_sidebar_previous (EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
|
||||
if (!priv->highlighted_result)
|
||||
return;
|
||||
|
||||
if (!gtk_tree_path_prev (priv->highlighted_result)) {
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
|
||||
gtk_tree_model_get_iter (model, &iter, priv->highlighted_result);
|
||||
while (gtk_tree_model_iter_next (model, &iter))
|
||||
gtk_tree_path_next (priv->highlighted_result);
|
||||
}
|
||||
ev_find_sidebar_select_highlighted_result (sidebar);
|
||||
}
|
||||
|
||||
void
|
||||
ev_find_sidebar_next (EvFindSidebar *sidebar)
|
||||
{
|
||||
EvFindSidebarPrivate *priv = GET_PRIVATE (sidebar);
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (!priv->highlighted_result)
|
||||
return;
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
|
||||
gtk_tree_model_get_iter (model, &iter, priv->highlighted_result);
|
||||
if (gtk_tree_model_iter_next (model, &iter)) {
|
||||
gtk_tree_path_next (priv->highlighted_result);
|
||||
} else {
|
||||
gtk_tree_path_free (priv->highlighted_result);
|
||||
priv->highlighted_result = gtk_tree_path_new_first ();
|
||||
}
|
||||
ev_find_sidebar_select_highlighted_result (sidebar);
|
||||
}
|
||||
|
||||
63
shell/ev-find-sidebar.h
Normal file
63
shell/ev-find-sidebar.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* ev-find-sidebar.h
|
||||
* this file is part of evince, a gnome document viewer
|
||||
*
|
||||
* Copyright (C) 2013 Carlos Garcia Campos <carlosgc@gnome.org>
|
||||
* Copyright (C) 2008 Sergey Pushkin <pushkinsv@gmail.com >
|
||||
*
|
||||
* Evince 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 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Evince 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef EV_FIND_SIDEBAR_H
|
||||
#define EV_FIND_SIDEBAR_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "ev-jobs.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define EV_TYPE_FIND_SIDEBAR (ev_find_sidebar_get_type ())
|
||||
#define EV_FIND_SIDEBAR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), EV_TYPE_FIND_SIDEBAR, EvFindSidebar))
|
||||
#define EV_IS_FIND_SIDEBAR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), EV_TYPE_FIND_SIDEBAR))
|
||||
#define EV_FIND_SIDEBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_FIND_SIDEBAR, EvFindSidebarClass))
|
||||
#define EV_IS_FIND_SIDEBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_FIND_SIDEBAR))
|
||||
#define EV_FIND_SIDEBAR_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), EV_TYPE_FIND_SIDEBAR, EvFindSidebarClass))
|
||||
|
||||
typedef struct _EvFindSidebar EvFindSidebar;
|
||||
typedef struct _EvFindSidebarClass EvFindSidebarClass;
|
||||
|
||||
struct _EvFindSidebar {
|
||||
GtkBox base_instance;
|
||||
};
|
||||
|
||||
struct _EvFindSidebarClass {
|
||||
GtkBoxClass base_class;
|
||||
};
|
||||
|
||||
GType ev_find_sidebar_get_type (void);
|
||||
GtkWidget *ev_find_sidebar_new (void);
|
||||
|
||||
void ev_find_sidebar_start (EvFindSidebar *find_sidebar,
|
||||
EvJobFind *job);
|
||||
void ev_find_sidebar_restart (EvFindSidebar *find_sidebar,
|
||||
gint page);
|
||||
void ev_find_sidebar_update (EvFindSidebar *find_sidebar);
|
||||
void ev_find_sidebar_clear (EvFindSidebar *find_sidebar);
|
||||
void ev_find_sidebar_previous (EvFindSidebar *find_sidebar);
|
||||
void ev_find_sidebar_next (EvFindSidebar *find_sidebar);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* EV_FIND_SIDEBAR_H */
|
||||
|
|
@ -47,6 +47,7 @@
|
|||
#include "egg-toolbars-model.h"
|
||||
|
||||
#include "eggfindbar.h"
|
||||
#include "ev-find-sidebar.h"
|
||||
|
||||
#include "ephy-zoom-action.h"
|
||||
#include "ephy-zoom.h"
|
||||
|
|
@ -144,6 +145,7 @@ struct _EvWindowPrivate {
|
|||
GtkWidget *password_view;
|
||||
GtkWidget *sidebar_thumbs;
|
||||
GtkWidget *sidebar_links;
|
||||
GtkWidget *find_sidebar;
|
||||
GtkWidget *sidebar_attachments;
|
||||
GtkWidget *sidebar_layers;
|
||||
GtkWidget *sidebar_annots;
|
||||
|
|
@ -384,6 +386,9 @@ static void zoom_control_changed_cb (EphyZoomAction *action,
|
|||
float zoom,
|
||||
EvWindow *ev_window);
|
||||
|
||||
static void ev_window_show_find_bar (EvWindow *ev_window);
|
||||
static void ev_window_close_find_bar (EvWindow *ev_window);
|
||||
|
||||
static gchar *caja_sendto = NULL;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (EvWindow, ev_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||
|
|
@ -1733,7 +1738,7 @@ ev_window_setup_document (EvWindow *ev_window)
|
|||
if (EV_IS_DOCUMENT_FIND (document)) {
|
||||
if (ev_window->priv->search_string &&
|
||||
!EV_WINDOW_IS_PRESENTATION (ev_window)) {
|
||||
ev_window_cmd_edit_find (NULL, ev_window);
|
||||
ev_window_show_find_bar (ev_window);
|
||||
egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar), ev_window->priv->search_string);
|
||||
}
|
||||
|
||||
|
|
@ -2487,7 +2492,7 @@ ev_window_open_document (EvWindow *ev_window,
|
|||
|
||||
if (search_string && EV_IS_DOCUMENT_FIND (document) &&
|
||||
mode != EV_WINDOW_MODE_PRESENTATION) {
|
||||
ev_window_cmd_edit_find (NULL, ev_window);
|
||||
ev_window_show_find_bar (ev_window);
|
||||
egg_find_bar_set_search_string (EGG_FIND_BAR (ev_window->priv->find_bar),
|
||||
search_string);
|
||||
}
|
||||
|
|
@ -4183,33 +4188,62 @@ ev_window_cmd_edit_select_all (GtkAction *action, EvWindow *ev_window)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ev_window_cmd_toggle_find (GtkAction *action, EvWindow *ev_window)
|
||||
{
|
||||
gboolean show_find_bar;
|
||||
|
||||
show_find_bar = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
|
||||
if (show_find_bar)
|
||||
ev_window_show_find_bar (ev_window);
|
||||
else
|
||||
ev_window_close_find_bar (ev_window);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window)
|
||||
{
|
||||
if (ev_window->priv->document == NULL || !EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
|
||||
g_error ("Find action should be insensitive since document doesn't support find");
|
||||
return;
|
||||
}
|
||||
ev_window_show_find_bar (ev_window);
|
||||
}
|
||||
|
||||
if (EV_WINDOW_IS_PRESENTATION (ev_window))
|
||||
return;
|
||||
static void
|
||||
ev_window_find_previous (EvWindow *ev_window)
|
||||
{
|
||||
ev_view_find_previous (EV_VIEW (ev_window->priv->view));
|
||||
ev_find_sidebar_previous (EV_FIND_SIDEBAR (ev_window->priv->find_sidebar));
|
||||
}
|
||||
|
||||
update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
|
||||
update_chrome_visibility (ev_window);
|
||||
gtk_widget_grab_focus (ev_window->priv->find_bar);
|
||||
static void
|
||||
ev_window_find_next (EvWindow *ev_window)
|
||||
{
|
||||
ev_view_find_next (EV_VIEW (ev_window->priv->view));
|
||||
ev_find_sidebar_next (EV_FIND_SIDEBAR (ev_window->priv->find_sidebar));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_next_idle_cb (EvWindow *ev_window)
|
||||
{
|
||||
ev_window_find_next (ev_window);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ev_window_cmd_edit_find_next (GtkAction *action, EvWindow *ev_window)
|
||||
{
|
||||
gboolean find_bar_hidden;
|
||||
|
||||
if (EV_WINDOW_IS_PRESENTATION (ev_window))
|
||||
return;
|
||||
|
||||
update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
|
||||
update_chrome_visibility (ev_window);
|
||||
gtk_widget_grab_focus (ev_window->priv->find_bar);
|
||||
find_bar_hidden = !gtk_widget_get_visible (ev_window->priv->find_bar);
|
||||
ev_window_show_find_bar (ev_window);
|
||||
|
||||
if (ev_window->priv->document && ev_window->priv->document->iswebdocument == FALSE) {
|
||||
ev_view_find_next (EV_VIEW (ev_window->priv->view));
|
||||
/* Use idle to make sure view allocation happens before find */
|
||||
if (find_bar_hidden)
|
||||
g_idle_add ((GSourceFunc)find_next_idle_cb, ev_window);
|
||||
else
|
||||
ev_window_find_next (ev_window);
|
||||
}
|
||||
#if ENABLE_EPUB
|
||||
else {
|
||||
|
|
@ -4218,17 +4252,30 @@ ev_window_cmd_edit_find_next (GtkAction *action, EvWindow *ev_window)
|
|||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_previous_idle_cb (EvWindow *ev_window)
|
||||
{
|
||||
ev_window_find_previous (ev_window);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ev_window_cmd_edit_find_previous (GtkAction *action, EvWindow *ev_window)
|
||||
{
|
||||
gboolean find_bar_hidden;
|
||||
|
||||
if (EV_WINDOW_IS_PRESENTATION (ev_window))
|
||||
return;
|
||||
|
||||
update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
|
||||
update_chrome_visibility (ev_window);
|
||||
gtk_widget_grab_focus (ev_window->priv->find_bar);
|
||||
find_bar_hidden = !gtk_widget_get_visible (ev_window->priv->find_bar);
|
||||
ev_window_show_find_bar (ev_window);
|
||||
|
||||
if (ev_window->priv->document && ev_window->priv->document->iswebdocument == FALSE) {
|
||||
ev_view_find_previous (EV_VIEW (ev_window->priv->view));
|
||||
/* Use idle to make sure view allocation happens before find */
|
||||
if (find_bar_hidden)
|
||||
g_idle_add ((GSourceFunc)find_previous_idle_cb, ev_window);
|
||||
else
|
||||
ev_window_find_previous (ev_window);
|
||||
}
|
||||
#if ENABLE_EPUB
|
||||
else {
|
||||
|
|
@ -5140,14 +5187,9 @@ ev_window_cmd_escape (GtkAction *action, EvWindow *window)
|
|||
|
||||
widget = gtk_window_get_focus (GTK_WINDOW (window));
|
||||
if (widget && gtk_widget_get_ancestor (widget, EGG_TYPE_FIND_BAR)) {
|
||||
update_chrome_flag (window, EV_CHROME_FINDBAR, FALSE);
|
||||
update_chrome_visibility (window);
|
||||
|
||||
if (window->priv->view)
|
||||
gtk_widget_grab_focus (window->priv->view);
|
||||
ev_window_close_find_bar (window);
|
||||
#if ENABLE_EPUB
|
||||
else
|
||||
gtk_widget_grab_focus (window->priv->webview);
|
||||
gtk_widget_grab_focus (window->priv->webview);
|
||||
#endif
|
||||
} else {
|
||||
gboolean fullscreen;
|
||||
|
|
@ -5729,6 +5771,15 @@ attachment_bar_menu_popup_cb (EvSidebarAttachments *attachbar,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
find_sidebar_result_activated_cb (EvFindSidebar *find_sidebar,
|
||||
gint page,
|
||||
gint result,
|
||||
EvWindow *window)
|
||||
{
|
||||
ev_view_find_set_result (EV_VIEW (window->priv->view), page, result);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_window_update_find_status_message (EvWindow *ev_window)
|
||||
{
|
||||
|
|
@ -5794,6 +5845,7 @@ ev_window_find_job_updated_cb (EvJobFind *job,
|
|||
page);
|
||||
}
|
||||
ev_window_update_find_status_message (ev_window);
|
||||
ev_find_sidebar_update (EV_FIND_SIDEBAR (ev_window->priv->find_sidebar));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -5821,10 +5873,10 @@ find_bar_previous_cb (EggFindBar *find_bar,
|
|||
#if ENABLE_EPUB
|
||||
if (ev_window->priv->document && ev_window->priv->document->iswebdocument == TRUE ) {
|
||||
ev_web_view_find_previous(EV_WEB_VIEW(ev_window->priv->webview));
|
||||
}else
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ev_view_find_previous (EV_VIEW (ev_window->priv->view));
|
||||
ev_window_find_previous (ev_window);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5838,7 +5890,7 @@ find_bar_next_cb (EggFindBar *find_bar,
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
ev_view_find_next (EV_VIEW (ev_window->priv->view));
|
||||
ev_window_find_next (ev_window);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5850,14 +5902,8 @@ find_bar_close_cb (EggFindBar *find_bar,
|
|||
if (ev_window->priv->document && ev_window->priv->document->iswebdocument == TRUE ) {
|
||||
ev_web_view_find_cancel(EV_WEB_VIEW(ev_window->priv->webview));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
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);
|
||||
ev_window_close_find_bar (ev_window);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -5880,6 +5926,9 @@ ev_window_search_start (EvWindow *ev_window)
|
|||
search_string,
|
||||
egg_find_bar_get_case_sensitive (find_bar));
|
||||
|
||||
ev_find_sidebar_start (EV_FIND_SIDEBAR (ev_window->priv->find_sidebar),
|
||||
EV_JOB_FIND (ev_window->priv->find_job));
|
||||
|
||||
g_signal_connect (ev_window->priv->find_job, "finished",
|
||||
G_CALLBACK (ev_window_find_job_finished_cb),
|
||||
ev_window);
|
||||
|
|
@ -5890,6 +5939,7 @@ ev_window_search_start (EvWindow *ev_window)
|
|||
} else {
|
||||
ev_window_update_actions (ev_window);
|
||||
egg_find_bar_set_status_text (find_bar, NULL);
|
||||
ev_find_sidebar_clear (EV_FIND_SIDEBAR (ev_window->priv->find_sidebar));
|
||||
if (ev_window->priv->document->iswebdocument == FALSE) {
|
||||
gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view));
|
||||
}
|
||||
|
|
@ -5936,13 +5986,70 @@ find_bar_visibility_changed_cb (EggFindBar *find_bar,
|
|||
#endif
|
||||
ev_window_update_actions (ev_window);
|
||||
|
||||
if (visible)
|
||||
ev_window_search_start (ev_window);
|
||||
else
|
||||
if (!visible)
|
||||
egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_toggle_find_action (EvWindow *ev_window,
|
||||
gboolean active)
|
||||
{
|
||||
GtkAction *action;
|
||||
|
||||
action = gtk_action_group_get_action (ev_window->priv->action_group, "EditFind");
|
||||
if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)) == active)
|
||||
return;
|
||||
|
||||
g_signal_handlers_block_by_func (action, G_CALLBACK (ev_window_cmd_toggle_find), ev_window);
|
||||
gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
|
||||
g_signal_handlers_unblock_by_func (action, G_CALLBACK (ev_window_cmd_toggle_find), ev_window);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_window_show_find_bar (EvWindow *ev_window)
|
||||
{
|
||||
if (gtk_widget_get_visible (ev_window->priv->find_bar))
|
||||
return;
|
||||
|
||||
if (ev_window->priv->document == NULL || !EV_IS_DOCUMENT_FIND (ev_window->priv->document)) {
|
||||
g_error ("Find action should be insensitive since document doesn't support find");
|
||||
return;
|
||||
}
|
||||
|
||||
if (EV_WINDOW_IS_PRESENTATION (ev_window))
|
||||
return;
|
||||
|
||||
g_object_ref (ev_window->priv->sidebar);
|
||||
gtk_container_remove (GTK_CONTAINER (ev_window->priv->hpaned), ev_window->priv->sidebar);
|
||||
gtk_paned_pack1 (GTK_PANED (ev_window->priv->hpaned),
|
||||
ev_window->priv->find_sidebar, FALSE, FALSE);
|
||||
gtk_widget_show (ev_window->priv->find_sidebar);
|
||||
|
||||
update_chrome_flag (ev_window, EV_CHROME_FINDBAR, TRUE);
|
||||
update_chrome_visibility (ev_window);
|
||||
gtk_widget_grab_focus (ev_window->priv->find_bar);
|
||||
update_toggle_find_action (ev_window, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
ev_window_close_find_bar (EvWindow *ev_window)
|
||||
{
|
||||
if (!gtk_widget_get_visible (ev_window->priv->find_bar))
|
||||
return;
|
||||
|
||||
g_object_ref (ev_window->priv->find_sidebar);
|
||||
gtk_container_remove (GTK_CONTAINER (ev_window->priv->hpaned),
|
||||
ev_window->priv->find_sidebar);
|
||||
gtk_paned_pack1 (GTK_PANED (ev_window->priv->hpaned),
|
||||
ev_window->priv->sidebar, FALSE, FALSE);
|
||||
|
||||
update_chrome_flag (ev_window, EV_CHROME_FINDBAR, FALSE);
|
||||
update_chrome_visibility (ev_window);
|
||||
gtk_widget_grab_focus (ev_window->priv->view);
|
||||
update_toggle_find_action (ev_window, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
zoom_control_changed_cb (EphyZoomAction *action,
|
||||
float zoom,
|
||||
|
|
@ -6467,9 +6574,6 @@ static const GtkActionEntry entries[] = {
|
|||
G_CALLBACK (ev_window_cmd_edit_copy) },
|
||||
{ "EditSelectAll", "edit-select-all", N_("Select _All"), "<control>A", NULL,
|
||||
G_CALLBACK (ev_window_cmd_edit_select_all) },
|
||||
{ "EditFind", "edit-find", N_("_Find…"), "<control>F",
|
||||
N_("Find a word or phrase in the document"),
|
||||
G_CALLBACK (ev_window_cmd_edit_find) },
|
||||
{ "EditFindNext", NULL, N_("Find Ne_xt"), "<control>G", NULL,
|
||||
G_CALLBACK (ev_window_cmd_edit_find_next) },
|
||||
{ "EditFindPrevious", NULL, N_("Find Pre_vious"), "<shift><control>G", NULL,
|
||||
|
|
@ -6624,6 +6728,9 @@ static const GtkToggleActionEntry toggle_entries[] = {
|
|||
N_("Activate or disable caret-navigation"),
|
||||
G_CALLBACK (ev_window_cmd_view_toggle_caret_navigation) },
|
||||
|
||||
{ "EditFind", GTK_STOCK_FIND, N_("_Find…"), "<control>F",
|
||||
N_("Find a word or phrase in the document"),
|
||||
G_CALLBACK (ev_window_cmd_toggle_find) },
|
||||
};
|
||||
|
||||
/* Popups specific items */
|
||||
|
|
@ -7116,7 +7223,7 @@ do_action_named (EvWindow *window, EvLinkAction *action)
|
|||
} else if (g_ascii_strcasecmp (name, "GoToPage") == 0) {
|
||||
ev_window_cmd_focus_page_selector (NULL, window);
|
||||
} else if (g_ascii_strcasecmp (name, "Find") == 0) {
|
||||
ev_window_cmd_edit_find (NULL, window);
|
||||
ev_window_show_find_bar (window);
|
||||
} else if (g_ascii_strcasecmp (name, "Close") == 0) {
|
||||
ev_window_cmd_file_close_window (NULL, window);
|
||||
} else if (g_ascii_strcasecmp (name, "Print") == 0) {
|
||||
|
|
@ -7966,6 +8073,12 @@ ev_window_init (EvWindow *ev_window)
|
|||
FALSE, FALSE, 0);
|
||||
gtk_widget_show (ev_window->priv->toolbar);
|
||||
|
||||
/* Find Bar */
|
||||
ev_window->priv->find_bar = egg_find_bar_new ();
|
||||
gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
|
||||
ev_window->priv->find_bar,
|
||||
FALSE, TRUE, 0);
|
||||
|
||||
/* Add the main area */
|
||||
ev_window->priv->hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
|
||||
g_signal_connect (ev_window->priv->hpaned,
|
||||
|
|
@ -8142,11 +8255,12 @@ ev_window_init (EvWindow *ev_window)
|
|||
gtk_widget_show (ev_window->priv->view);
|
||||
gtk_widget_show (ev_window->priv->password_view);
|
||||
|
||||
/* Find Bar */
|
||||
ev_window->priv->find_bar = egg_find_bar_new ();
|
||||
gtk_box_pack_end (GTK_BOX (ev_window->priv->main_box),
|
||||
ev_window->priv->find_bar,
|
||||
FALSE, TRUE, 0);
|
||||
/* Find results sidebar */
|
||||
ev_window->priv->find_sidebar = ev_find_sidebar_new ();
|
||||
g_signal_connect (ev_window->priv->find_sidebar,
|
||||
"result-activated",
|
||||
G_CALLBACK (find_sidebar_result_activated_cb),
|
||||
ev_window);
|
||||
|
||||
/* We own a ref on these widgets, as we can swap them in and out */
|
||||
g_object_ref (ev_window->priv->view);
|
||||
|
|
|
|||
Loading…
Reference in a new issue