[evince] libmisc: Add EvSearchBox widget
- From: Carlos Garcia Campos <carlosgc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince] libmisc: Add EvSearchBox widget
- Date: Fri, 10 Apr 2015 11:13:18 +0000 (UTC)
commit 16314cd5901dc3ec00a744feb123fb311056b32b
Author: Carlos Garcia Campos <cgarcia igalia com>
Date: Tue Apr 7 09:31:03 2015 +0200
libmisc: Add EvSearchBox widget
It's a simple search box containing also the evince search logic.
configure.ac | 2 +-
libmisc/Makefile.am | 4 +-
libmisc/ev-search-box.c | 661 +++++++++++++++++++++++++++++++++++++++++++++++
libmisc/ev-search-box.h | 60 +++++
po/POTFILES.in | 1 +
5 files changed, 726 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 702d146..2ead774 100644
--- a/configure.ac
+++ b/configure.ac
@@ -118,7 +118,7 @@ dnl Specify required versions of dependencies
CAIRO_REQUIRED=1.10.0
GLIB_REQUIRED=2.36.0
LIBSECRET_REQUIRED=0.5
-GTK_REQUIRED=3.15.3
+GTK_REQUIRED=3.16.0
NAUTILUS_REQUIRED=2.91.4
AC_SUBST([GLIB_REQUIRED])
diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am
index 5877c5b..498c7d5 100644
--- a/libmisc/Makefile.am
+++ b/libmisc/Makefile.am
@@ -4,7 +4,9 @@ libevmisc_la_SOURCES = \
ev-page-action.c \
ev-page-action.h \
ev-page-action-widget.c \
- ev-page-action-widget.h
+ ev-page-action-widget.h \
+ ev-search-box.c \
+ ev-search-box.h
libevmisc_la_CFLAGS = \
-DEVINCEDATADIR=\"$(pkgdatadir)\" \
diff --git a/libmisc/ev-search-box.c b/libmisc/ev-search-box.c
new file mode 100644
index 0000000..84c3920
--- /dev/null
+++ b/libmisc/ev-search-box.c
@@ -0,0 +1,661 @@
+/* ev-search-box.c
+ * this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "ev-search-box.h"
+
+#include <glib/gi18n.h>
+
+enum {
+ STARTED,
+ UPDATED,
+ FINISHED,
+ CLEARED,
+
+ NEXT,
+ PREVIOUS,
+
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+
+ PROP_DOCUMENT_MODEL,
+ PROP_OPTIONS
+};
+
+struct _EvSearchBoxPrivate {
+ EvDocumentModel *model;
+ EvJob *job;
+ EvFindOptions options;
+ EvFindOptions supported_options;
+
+ GtkWidget *entry;
+ GtkWidget *next_button;
+ GtkWidget *prev_button;
+
+ guint pages_searched;
+};
+
+G_DEFINE_TYPE (EvSearchBox, ev_search_box, GTK_TYPE_BOX)
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+#define FIND_PAGE_RATE_REFRESH 100
+
+static void
+ev_search_box_update_progress (EvSearchBox *box)
+{
+ EvSearchBoxPrivate *priv = box->priv;
+ gdouble fraction;
+
+ fraction = priv->job ? MIN ((gdouble)priv->pages_searched / EV_JOB_FIND (priv->job)->n_pages, 1.) :
0.;
+ gtk_entry_set_progress_fraction (GTK_ENTRY (priv->entry), fraction);
+}
+
+static void
+ev_search_box_clear_job (EvSearchBox *box)
+{
+ EvSearchBoxPrivate *priv = box->priv;
+
+ if (!priv->job)
+ return;
+
+ if (!ev_job_is_finished (priv->job))
+ ev_job_cancel (priv->job);
+
+ g_signal_handlers_disconnect_matched (priv->job, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, box);
+ g_object_unref (priv->job);
+ priv->job = NULL;
+}
+
+static void
+find_job_finished_cb (EvJobFind *job,
+ EvSearchBox *box)
+{
+ g_signal_emit (box, signals[FINISHED], 0);
+ ev_search_box_clear_job (box);
+ ev_search_box_update_progress (box);
+
+ if (!ev_job_find_has_results (job)) {
+ EvSearchBoxPrivate *priv = box->priv;
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (priv->entry),
GTK_STYLE_CLASS_ERROR);
+
+ gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ "face-uncertain-symbolic");
+ if (priv->supported_options != EV_FIND_DEFAULT) {
+ gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ _("Not found, click to change search options"));
+ }
+ }
+}
+
+/**
+ * find_bar_check_refresh_rate:
+ *
+ * Check whether the current page should trigger an status update in the
+ * find bar given its document size and the rate page.
+ *
+ * For documents with less pages than page_rate, it will return TRUE for
+ * every page. For documents with more pages, it will return TRUE every
+ * ((total_pages / page rate) + 1).
+ *
+ * This slow down the update rate in the GUI, making the search more
+ * responsive.
+ */
+static inline gboolean
+find_check_refresh_rate (EvJobFind *job,
+ gint page_rate)
+{
+ return ((job->current_page % (gint)((job->n_pages / page_rate) + 1)) == 0);
+}
+
+static void
+find_job_updated_cb (EvJobFind *job,
+ gint page,
+ EvSearchBox *box)
+{
+ EvSearchBoxPrivate *priv = box->priv;
+
+ priv->pages_searched++;
+
+ /* Adjust the status update when searching for a term according
+ * to the document size in pages. For documents smaller (or equal)
+ * than 100 pages, it will be updated in every page. A value of
+ * 100 is enough to update the find bar every 1%.
+ */
+ if (find_check_refresh_rate (job, FIND_PAGE_RATE_REFRESH)) {
+ gboolean has_results = ev_job_find_has_results (job);
+
+ ev_search_box_update_progress (box);
+ gtk_widget_set_sensitive (priv->next_button, has_results);
+ gtk_widget_set_sensitive (priv->prev_button, has_results);
+ g_signal_emit (box, signals[UPDATED], 0);
+ }
+}
+
+static void
+search_changed_cb (GtkSearchEntry *entry,
+ EvSearchBox *box)
+{
+ const char *search_string;
+ EvSearchBoxPrivate *priv = box->priv;
+
+ ev_search_box_clear_job (box);
+ priv->pages_searched = 0;
+ ev_search_box_update_progress (box);
+
+ gtk_widget_set_sensitive (priv->next_button, FALSE);
+ gtk_widget_set_sensitive (priv->prev_button, FALSE);
+
+ gtk_style_context_remove_class (gtk_widget_get_style_context (priv->entry), GTK_STYLE_CLASS_ERROR);
+ gtk_entry_set_icon_from_icon_name (GTK_ENTRY (priv->entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ "edit-find-symbolic");
+ if (priv->supported_options != EV_FIND_DEFAULT) {
+ gtk_entry_set_icon_tooltip_text (GTK_ENTRY (priv->entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ _("Search options"));
+ }
+
+ search_string = gtk_entry_get_text (GTK_ENTRY (entry));
+ if (search_string && search_string[0]) {
+ EvDocument *doc = ev_document_model_get_document (priv->model);
+
+ priv->job = ev_job_find_new (doc,
+ ev_document_model_get_page (priv->model),
+ ev_document_get_n_pages (doc),
+ search_string,
+ FALSE);
+ ev_job_find_set_options (EV_JOB_FIND (priv->job), priv->options);
+ g_signal_connect (priv->job, "finished",
+ G_CALLBACK (find_job_finished_cb),
+ box);
+ g_signal_connect (priv->job, "updated",
+ G_CALLBACK (find_job_updated_cb),
+ box);
+
+ g_signal_emit (box, signals[STARTED], 0, priv->job);
+ ev_job_scheduler_push_job (priv->job, EV_JOB_PRIORITY_NONE);
+ } else {
+ g_signal_emit (box, signals[CLEARED], 0);
+ }
+}
+
+static void
+previous_clicked_cb (GtkButton *button,
+ EvSearchBox *box)
+{
+ g_signal_emit (box, signals[PREVIOUS], 0);
+}
+
+static void
+next_clicked_cb (GtkButton *button,
+ EvSearchBox *box)
+{
+ g_signal_emit (box, signals[NEXT], 0);
+}
+
+static void
+ev_search_box_set_supported_options (EvSearchBox *box,
+ EvFindOptions options)
+{
+ EvSearchBoxPrivate *priv = box->priv;
+ gboolean enable_search_options;
+
+ if (priv->supported_options == options)
+ return;
+
+ priv->supported_options = options;
+ enable_search_options = options != EV_FIND_DEFAULT;
+ g_object_set (priv->entry,
+ "primary-icon-activatable", enable_search_options,
+ "primary-icon-sensitive", enable_search_options,
+ "primary-icon-tooltip-text", enable_search_options ? _("Search options") : NULL,
+ NULL);
+}
+
+static void
+ev_search_box_setup_document (EvSearchBox *box,
+ EvDocument *document)
+{
+ if (!document || !EV_IS_DOCUMENT_FIND (document)) {
+ ev_search_box_set_supported_options (box, EV_FIND_DEFAULT);
+ gtk_widget_set_sensitive (GTK_WIDGET (box), FALSE);
+ return;
+ }
+
+ ev_search_box_set_supported_options (box, ev_document_find_get_supported_options (EV_DOCUMENT_FIND
(document)));
+ gtk_widget_set_sensitive (GTK_WIDGET (box), ev_document_get_n_pages (document) > 0);
+}
+
+static void
+document_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvSearchBox *box)
+{
+ ev_search_box_setup_document (box, ev_document_model_get_document (model));
+}
+
+static void
+ev_search_box_set_options (EvSearchBox *box,
+ EvFindOptions options)
+{
+ EvSearchBoxPrivate *priv = box->priv;
+
+ if (priv->options == options)
+ return;
+
+ priv->options = options;
+ search_changed_cb (GTK_SEARCH_ENTRY (priv->entry), box);
+}
+
+static void
+whole_words_only_toggled_cb (GtkCheckMenuItem *menu_item,
+ EvSearchBox *box)
+{
+ EvFindOptions options = box->priv->options;
+
+ if (gtk_check_menu_item_get_active (menu_item))
+ options |= EV_FIND_WHOLE_WORDS_ONLY;
+ else
+ options &= ~EV_FIND_WHOLE_WORDS_ONLY;
+ ev_search_box_set_options (box, options);
+}
+
+static void
+case_sensitive_toggled_cb (GtkCheckMenuItem *menu_item,
+ EvSearchBox *box)
+{
+ EvFindOptions options = box->priv->options;
+
+ if (gtk_check_menu_item_get_active (menu_item))
+ options |= EV_FIND_CASE_SENSITIVE;
+ else
+ options &= ~EV_FIND_CASE_SENSITIVE;
+ ev_search_box_set_options (box, options);
+}
+
+static void
+ev_search_box_entry_populate_popup (EvSearchBox *box,
+ GtkWidget *menu)
+{
+ EvSearchBoxPrivate *priv = box->priv;
+
+ if (priv->supported_options & EV_FIND_WHOLE_WORDS_ONLY) {
+ GtkWidget *menu_item;
+
+ menu_item = gtk_check_menu_item_new_with_mnemonic (_("_Whole Words Only"));
+ g_signal_connect (menu_item, "toggled",
+ G_CALLBACK (whole_words_only_toggled_cb),
+ box);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item),
+ priv->options & EV_FIND_WHOLE_WORDS_ONLY);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
+ gtk_widget_show (menu_item);
+ }
+
+ if (priv->supported_options & EV_FIND_CASE_SENSITIVE) {
+ GtkWidget *menu_item;
+
+ menu_item = gtk_check_menu_item_new_with_mnemonic (_("C_ase Sensitive"));
+ g_signal_connect (menu_item, "toggled",
+ G_CALLBACK (case_sensitive_toggled_cb),
+ box);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item),
+ priv->options & EV_FIND_CASE_SENSITIVE);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item);
+ gtk_widget_show (menu_item);
+ }
+}
+
+static void
+entry_icon_release_cb (GtkEntry *entry,
+ GtkEntryIconPosition icon_pos,
+ GdkEventButton *event,
+ EvSearchBox *box)
+{
+ GtkWidget *menu;
+
+ if (event->button != GDK_BUTTON_PRIMARY)
+ return;
+
+ if (icon_pos == GTK_ENTRY_ICON_SECONDARY)
+ return;
+
+ menu = gtk_menu_new ();
+ ev_search_box_entry_populate_popup (box, menu);
+ gtk_widget_show (menu);
+
+ gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
+ event->button, event->time);
+}
+
+static void
+entry_populate_popup_cb (GtkEntry *entry,
+ GtkMenu *menu,
+ EvSearchBox *box)
+{
+ EvSearchBoxPrivate *priv = box->priv;
+ GtkWidget *separator;
+
+ if (priv->supported_options == EV_FIND_DEFAULT)
+ return;
+
+ separator = gtk_separator_menu_item_new ();
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), separator);
+ gtk_widget_show (separator);
+ ev_search_box_entry_populate_popup (box, GTK_WIDGET (menu));
+}
+
+static void
+entry_activate_cb (GtkEntry *entry,
+ EvSearchBox *box)
+{
+ g_signal_emit (box, signals[NEXT], 0);
+}
+
+static void
+entry_next_match_cb (GtkSearchEntry *entry,
+ EvSearchBox *box)
+{
+ g_signal_emit (box, signals[NEXT], 0);
+}
+
+static void
+entry_previous_match_cb (GtkSearchEntry *entry,
+ EvSearchBox *box)
+{
+ g_signal_emit (box, signals[PREVIOUS], 0);
+}
+
+static void
+ev_search_box_finalize (GObject *object)
+{
+ EvSearchBox *box = EV_SEARCH_BOX (object);
+
+ if (box->priv->model) {
+ g_object_remove_weak_pointer (G_OBJECT (box->priv->model),
+ (gpointer)&box->priv->model);
+ }
+
+ G_OBJECT_CLASS (ev_search_box_parent_class)->finalize (object);
+}
+
+static void
+ev_search_box_dispose (GObject *object)
+{
+ EvSearchBox *box = EV_SEARCH_BOX (object);
+
+ ev_search_box_clear_job (box);
+
+ G_OBJECT_CLASS (ev_search_box_parent_class)->dispose (object);
+}
+
+static void
+ev_search_box_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EvSearchBox *box = EV_SEARCH_BOX (object);
+
+ switch (prop_id) {
+ case PROP_DOCUMENT_MODEL:
+ box->priv->model = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ev_search_box_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EvSearchBox *box = EV_SEARCH_BOX (object);
+
+ switch (prop_id) {
+ case PROP_OPTIONS:
+ g_value_set_flags (value, box->priv->options);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ev_search_box_constructed (GObject *object)
+{
+ EvSearchBox *box = EV_SEARCH_BOX (object);
+
+ G_OBJECT_CLASS (ev_search_box_parent_class)->constructed (object);
+
+ g_object_add_weak_pointer (G_OBJECT (box->priv->model),
+ (gpointer)&box->priv->model);
+
+ ev_search_box_setup_document (box, ev_document_model_get_document (box->priv->model));
+ g_signal_connect_object (box->priv->model, "notify::document",
+ G_CALLBACK (document_changed_cb),
+ box, 0);
+}
+
+static void
+ev_search_box_grab_focus (GtkWidget *widget)
+{
+ EvSearchBox *box = EV_SEARCH_BOX (widget);
+
+ gtk_widget_grab_focus (box->priv->entry);
+}
+
+static void
+ev_search_box_class_init (EvSearchBoxClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkBindingSet *binding_set;
+
+ object_class->finalize = ev_search_box_finalize;
+ object_class->dispose = ev_search_box_dispose;
+ object_class->constructed = ev_search_box_constructed;
+ object_class->set_property = ev_search_box_set_property;
+ object_class->get_property = ev_search_box_get_property;
+
+ widget_class->grab_focus = ev_search_box_grab_focus;
+
+ g_object_class_install_property (object_class,
+ PROP_DOCUMENT_MODEL,
+ g_param_spec_object ("document-model",
+ "DocumentModel",
+ "The document model",
+ EV_TYPE_DOCUMENT_MODEL,
+ G_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class,
+ PROP_OPTIONS,
+ g_param_spec_flags ("options",
+ "Search options",
+ "The search options",
+ EV_TYPE_FIND_OPTIONS,
+ EV_FIND_DEFAULT,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ signals[STARTED] =
+ g_signal_new ("started",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ EV_TYPE_JOB_FIND);
+
+ signals[UPDATED] =
+ g_signal_new ("updated",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1,
+ G_TYPE_INT);
+ signals[FINISHED] =
+ g_signal_new ("finished",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[CLEARED] =
+ g_signal_new ("cleared",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[NEXT] =
+ g_signal_new ("next",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[PREVIOUS] =
+ g_signal_new ("previous",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (object_class, sizeof (EvSearchBoxPrivate));
+
+ binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, GDK_SHIFT_MASK,
+ "previous", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, GDK_SHIFT_MASK,
+ "previous", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, GDK_SHIFT_MASK,
+ "previous", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Up, GDK_CONTROL_MASK,
+ "previous", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Down, GDK_CONTROL_MASK,
+ "next", 0);
+}
+
+static void
+ev_search_box_init (EvSearchBox *box)
+{
+ EvSearchBoxPrivate *priv;
+ GtkStyleContext *style_context;
+
+ box->priv = G_TYPE_INSTANCE_GET_PRIVATE (box, EV_TYPE_SEARCH_BOX, EvSearchBoxPrivate);
+ priv = box->priv;
+
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (box), GTK_ORIENTATION_HORIZONTAL);
+ style_context = gtk_widget_get_style_context (GTK_WIDGET (box));
+ gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_LINKED);
+ gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_RAISED);
+
+ priv->entry = gtk_search_entry_new ();
+
+ gtk_box_pack_start (GTK_BOX (box), priv->entry, TRUE, TRUE, 0);
+ gtk_widget_show (priv->entry);
+
+ priv->prev_button = gtk_button_new_from_icon_name ("go-up-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_widget_set_tooltip_text (priv->prev_button, _("Find previous occurrence of the search string"));
+ gtk_widget_set_can_focus (priv->prev_button, FALSE);
+ gtk_widget_set_sensitive (priv->prev_button, FALSE);
+ gtk_container_add (GTK_CONTAINER (box), priv->prev_button);
+ gtk_widget_show (priv->prev_button);
+
+ priv->next_button = gtk_button_new_from_icon_name ("go-down-symbolic", GTK_ICON_SIZE_MENU);
+ gtk_widget_set_tooltip_text (priv->next_button, _("Find next occurrence of the search string"));
+ gtk_widget_set_can_focus (priv->next_button, FALSE);
+ gtk_widget_set_sensitive (priv->next_button, FALSE);
+ gtk_container_add (GTK_CONTAINER (box), priv->next_button);
+ gtk_widget_show (priv->next_button);
+
+ g_signal_connect (priv->entry, "search-changed",
+ G_CALLBACK (search_changed_cb),
+ box);
+ g_signal_connect (priv->entry, "icon-release",
+ G_CALLBACK (entry_icon_release_cb),
+ box);
+ g_signal_connect (priv->entry, "populate-popup",
+ G_CALLBACK (entry_populate_popup_cb),
+ box);
+ g_signal_connect (priv->entry, "activate",
+ G_CALLBACK (entry_activate_cb),
+ box);
+ g_signal_connect (priv->entry, "next-match",
+ G_CALLBACK (entry_next_match_cb),
+ box);
+ g_signal_connect (priv->entry, "previous-match",
+ G_CALLBACK (entry_previous_match_cb),
+ box);
+ g_signal_connect (priv->prev_button, "clicked",
+ G_CALLBACK (previous_clicked_cb),
+ box);
+ g_signal_connect (priv->next_button, "clicked",
+ G_CALLBACK (next_clicked_cb),
+ box);
+}
+
+GtkWidget *
+ev_search_box_new (EvDocumentModel *model)
+{
+ g_return_val_if_fail (EV_IS_DOCUMENT_MODEL (model), NULL);
+
+ return GTK_WIDGET (g_object_new (EV_TYPE_SEARCH_BOX,
+ "document-model", model,
+ NULL));
+}
+
+GtkSearchEntry *
+ev_search_box_get_entry (EvSearchBox *box)
+{
+ g_return_val_if_fail (EV_IS_SEARCH_BOX (box), NULL);
+
+ return GTK_SEARCH_ENTRY (box->priv->entry);
+}
+
+gboolean
+ev_search_box_has_results (EvSearchBox *box)
+{
+ g_return_val_if_fail (EV_IS_SEARCH_BOX (box), FALSE);
+
+ return gtk_widget_get_sensitive (box->priv->next_button);
+}
+
+void
+ev_search_box_restart (EvSearchBox *box)
+{
+ g_return_if_fail (EV_IS_SEARCH_BOX (box));
+
+ search_changed_cb (GTK_SEARCH_ENTRY (box->priv->entry), box);
+}
diff --git a/libmisc/ev-search-box.h b/libmisc/ev-search-box.h
new file mode 100644
index 0000000..d925390
--- /dev/null
+++ b/libmisc/ev-search-box.h
@@ -0,0 +1,60 @@
+/* ev-search-box.h
+ * this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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_SEARCH_BOX_H
+#define EV_SEARCH_BOX_H
+
+#include <gtk/gtk.h>
+#include <evince-document.h>
+#include <evince-view.h>
+
+G_BEGIN_DECLS
+
+#define EV_TYPE_SEARCH_BOX (ev_search_box_get_type ())
+#define EV_SEARCH_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_SEARCH_BOX, EvSearchBox))
+#define EV_IS_SEARCH_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_SEARCH_BOX))
+#define EV_SEARCH_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_SEARCH_BOX,
EvSearchBoxClass))
+#define EV_IS_SEARCH_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EV_TYPE_SEARCH_BOX))
+#define EV_SEARCH_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EV_TYPE_SEARCH_BOX,
EvSearchBoxClass))
+
+typedef struct _EvSearchBox EvSearchBox;
+typedef struct _EvSearchBoxClass EvSearchBoxClass;
+typedef struct _EvSearchBoxPrivate EvSearchBoxPrivate;
+
+struct _EvSearchBox {
+ GtkBox parent;
+
+ EvSearchBoxPrivate *priv;
+};
+
+struct _EvSearchBoxClass {
+ GtkBoxClass parent_class;
+};
+
+GType ev_search_box_get_type (void);
+
+GtkWidget *ev_search_box_new (EvDocumentModel *model);
+GtkSearchEntry *ev_search_box_get_entry (EvSearchBox *box);
+gboolean ev_search_box_has_results (EvSearchBox *box);
+void ev_search_box_restart (EvSearchBox *box);
+
+G_END_DECLS
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 873676d..68d3a6c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -30,6 +30,7 @@ libdocument/ev-document-factory.c
libdocument/ev-file-helpers.c
libmisc/ev-page-action.c
libmisc/ev-page-action-widget.c
+libmisc/ev-search-box.c
libview/ev-jobs.c
libview/ev-print-operation.c
libview/ev-view-accessible.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]