aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-05-21 06:09:34 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-05-21 06:09:34 +0800
commit5d12f06367a0939387381f66cea77766a873aea6 (patch)
tree221b29a45e7e52481a4638d12cdf8e8253bb9ce1 /mail
parent23f58b3f17ce7ba08a8bd3f6066f62f0f454bacf (diff)
downloadgsoc2013-evolution-5d12f06367a0939387381f66cea77766a873aea6.tar
gsoc2013-evolution-5d12f06367a0939387381f66cea77766a873aea6.tar.gz
gsoc2013-evolution-5d12f06367a0939387381f66cea77766a873aea6.tar.bz2
gsoc2013-evolution-5d12f06367a0939387381f66cea77766a873aea6.tar.lz
gsoc2013-evolution-5d12f06367a0939387381f66cea77766a873aea6.tar.xz
gsoc2013-evolution-5d12f06367a0939387381f66cea77766a873aea6.tar.zst
gsoc2013-evolution-5d12f06367a0939387381f66cea77766a873aea6.zip
Bug 580925 – Better search bar for word searches
Make the word search bar more like Firefox and get rid of the "Current Message" search scope in the folder search bar. Shift+Ctrl+F now activates the word search bar.
Diffstat (limited to 'mail')
-rw-r--r--mail/Makefile.am2
-rw-r--r--mail/e-mail-search-bar.c774
-rw-r--r--mail/e-mail-search-bar.h85
-rw-r--r--mail/e-searching-tokenizer.c4
-rw-r--r--mail/e-searching-tokenizer.h2
-rw-r--r--mail/em-folder-browser.c75
-rw-r--r--mail/em-folder-view.c24
-rw-r--r--mail/em-folder-view.h3
-rw-r--r--mail/em-format-html-display.c338
-rw-r--r--mail/em-format-html-display.h2
-rw-r--r--mail/em-format.c38
-rw-r--r--mail/em-format.h10
-rw-r--r--mail/em-message-browser.c38
-rw-r--r--mail/em-utils.c2
14 files changed, 997 insertions, 400 deletions
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 96ed893007..793d5c3a1e 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -55,6 +55,7 @@ idl_DATA = $(MAIL_IDL)
mailinclude_HEADERS = \
$(MAIL_IDL_GENERATED_H) \
e-mail-attachment-bar.h \
+ e-mail-search-bar.h \
em-composer-utils.h \
em-config.h \
em-event.h \
@@ -97,6 +98,7 @@ libevolution_mail_la_SOURCES = \
e-attachment-handler-mail.c \
e-attachment-handler-mail.h \
e-mail-attachment-bar.c \
+ e-mail-search-bar.c \
e-searching-tokenizer.c \
e-searching-tokenizer.h \
em-account-editor.c \
diff --git a/mail/e-mail-search-bar.c b/mail/e-mail-search-bar.c
new file mode 100644
index 0000000000..4d555857ca
--- /dev/null
+++ b/mail/e-mail-search-bar.c
@@ -0,0 +1,774 @@
+/*
+ * e-mail-search-bar.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-mail-search-bar.h"
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtkhtml/gtkhtml-search.h>
+
+#include "e-util/e-binding.h"
+
+#define E_MAIL_SEARCH_BAR_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBarPrivate))
+
+struct _EMailSearchBarPrivate {
+ GtkHTML *html;
+ GtkWidget *entry;
+ GtkWidget *case_sensitive_button;
+ GtkWidget *wrapped_next_box;
+ GtkWidget *wrapped_prev_box;
+ GtkWidget *matches_label;
+
+ ESearchingTokenizer *tokenizer;
+ gchar *active_search;
+
+ guint rerun_search : 1;
+};
+
+enum {
+ PROP_0,
+ PROP_CASE_SENSITIVE,
+ PROP_HTML,
+ PROP_TEXT
+};
+
+enum {
+ CHANGED,
+ CLEAR,
+ LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static void
+mail_search_bar_update_matches (EMailSearchBar *search_bar)
+{
+ ESearchingTokenizer *tokenizer;
+ GtkWidget *matches_label;
+ gint matches;
+ gchar *text;
+
+ tokenizer = e_mail_search_bar_get_tokenizer (search_bar);
+ matches_label = search_bar->priv->matches_label;
+
+ matches = e_searching_tokenizer_match_count (tokenizer);
+ text = g_strdup_printf (_("Matches: %d"), matches);
+
+ gtk_label_set_text (GTK_LABEL (matches_label), text);
+ gtk_widget_show (matches_label);
+
+ g_free (text);
+}
+
+static void
+mail_search_bar_update_tokenizer (EMailSearchBar *search_bar)
+{
+ ESearchingTokenizer *tokenizer;
+ gboolean case_sensitive;
+ gchar *active_search;
+
+ tokenizer = e_mail_search_bar_get_tokenizer (search_bar);
+ case_sensitive = e_mail_search_bar_get_case_sensitive (search_bar);
+
+ if (GTK_WIDGET_VISIBLE (search_bar))
+ active_search = search_bar->priv->active_search;
+ else
+ active_search = NULL;
+
+ e_searching_tokenizer_set_primary_case_sensitivity (
+ tokenizer, case_sensitive);
+ e_searching_tokenizer_set_primary_search_string (
+ tokenizer, active_search);
+
+ e_mail_search_bar_changed (search_bar);
+}
+
+static void
+mail_search_bar_find (EMailSearchBar *search_bar,
+ gboolean search_forward)
+{
+ GtkHTML *html;
+ GtkWidget *widget;
+ gboolean case_sensitive;
+ gboolean new_search;
+ gboolean wrapped = FALSE;
+ gchar *text;
+
+ html = e_mail_search_bar_get_html (search_bar);
+ case_sensitive = e_mail_search_bar_get_case_sensitive (search_bar);
+ text = e_mail_search_bar_get_text (search_bar);
+
+ if (text == NULL || *text == '\0')
+ gtk_widget_hide (search_bar->priv->matches_label);
+
+ new_search =
+ (search_bar->priv->active_search == NULL) ||
+ (g_strcmp0 (text, search_bar->priv->active_search) != 0);
+
+ /* XXX On a new search, the HTMLEngine's search state gets
+ * destroyed when we redraw the message with highlighted
+ * matches (EMHTMLStream's write() method triggers this,
+ * but it's really GtkHtml's fault). That's why the first
+ * match isn't selected automatically. It also causes
+ * gtk_html_engine_search_next() to return FALSE, which we
+ * assume to mean the search wrapped.
+ *
+ * So to avoid mistakenly thinking the search wrapped when
+ * it hasn't, we have to trap the first button click after a
+ * search and re-run the search to recreate the HTMLEngine's
+ * search state, so that gtk_html_engine_search_next() will
+ * succeed. */
+ if (new_search) {
+ g_free (search_bar->priv->active_search);
+ search_bar->priv->active_search = text;
+ search_bar->priv->rerun_search = TRUE;
+ mail_search_bar_update_tokenizer (search_bar);
+ } else if (search_bar->priv->rerun_search) {
+ gtk_html_engine_search (
+ html, search_bar->priv->active_search,
+ case_sensitive, search_forward, FALSE);
+ search_bar->priv->rerun_search = FALSE;
+ g_free (text);
+ } else {
+ gtk_html_engine_search_set_forward (html, search_forward);
+ if (!gtk_html_engine_search_next (html))
+ wrapped = TRUE;
+ g_free (text);
+ }
+
+ if (new_search || wrapped)
+ gtk_html_engine_search (
+ html, search_bar->priv->active_search,
+ case_sensitive, search_forward, FALSE);
+
+ /* Update wrapped label visibility. */
+
+ widget = search_bar->priv->wrapped_next_box;
+
+ if (wrapped && search_forward)
+ gtk_widget_show (widget);
+ else
+ gtk_widget_hide (widget);
+
+ widget = search_bar->priv->wrapped_prev_box;
+
+ if (wrapped && !search_forward)
+ gtk_widget_show (widget);
+ else
+ gtk_widget_hide (widget);
+}
+
+static void
+mail_search_bar_changed_cb (EMailSearchBar *search_bar)
+{
+ g_object_notify (G_OBJECT (search_bar), "text");
+}
+
+static void
+mail_search_bar_find_next_cb (EMailSearchBar *search_bar)
+{
+ mail_search_bar_find (search_bar, TRUE);
+}
+
+static void
+mail_search_bar_find_previous_cb (EMailSearchBar *search_bar)
+{
+ mail_search_bar_find (search_bar, FALSE);
+}
+
+static void
+mail_search_bar_icon_release_cb (EMailSearchBar *search_bar,
+ GtkEntryIconPosition icon_pos,
+ GdkEvent *event)
+{
+ g_return_if_fail (icon_pos == GTK_ENTRY_ICON_SECONDARY);
+
+ e_mail_search_bar_clear (search_bar);
+ gtk_widget_grab_focus (search_bar->priv->entry);
+}
+
+static void
+mail_search_bar_toggled_cb (EMailSearchBar *search_bar)
+{
+ g_free (search_bar->priv->active_search);
+ search_bar->priv->active_search = NULL;
+
+ g_object_notify (G_OBJECT (search_bar), "case-sensitive");
+}
+
+static void
+mail_search_bar_set_html (EMailSearchBar *search_bar,
+ GtkHTML *html)
+{
+ ESearchingTokenizer *tokenizer;
+
+ g_return_if_fail (search_bar->priv->html == NULL);
+
+ search_bar->priv->html = g_object_ref (html);
+
+ tokenizer = e_mail_search_bar_get_tokenizer (search_bar);
+ gtk_html_set_tokenizer (html, HTML_TOKENIZER (tokenizer));
+}
+
+static void
+mail_search_bar_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CASE_SENSITIVE:
+ e_mail_search_bar_set_case_sensitive (
+ E_MAIL_SEARCH_BAR (object),
+ g_value_get_boolean (value));
+ return;
+
+ case PROP_HTML:
+ mail_search_bar_set_html (
+ E_MAIL_SEARCH_BAR (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_TEXT:
+ e_mail_search_bar_set_text (
+ E_MAIL_SEARCH_BAR (object),
+ g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_search_bar_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_CASE_SENSITIVE:
+ g_value_set_boolean (
+ value, e_mail_search_bar_get_case_sensitive (
+ E_MAIL_SEARCH_BAR (object)));
+ return;
+
+ case PROP_HTML:
+ g_value_set_object (
+ value, e_mail_search_bar_get_html (
+ E_MAIL_SEARCH_BAR (object)));
+ return;
+
+ case PROP_TEXT:
+ g_value_take_string (
+ value, e_mail_search_bar_get_text (
+ E_MAIL_SEARCH_BAR (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_search_bar_dispose (GObject *object)
+{
+ EMailSearchBarPrivate *priv;
+
+ priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (object);
+
+ if (priv->html != NULL) {
+ g_object_unref (priv->html);
+ priv->html = NULL;
+ }
+
+ if (priv->entry != NULL) {
+ g_object_unref (priv->entry);
+ priv->entry = NULL;
+ }
+
+ if (priv->case_sensitive_button != NULL) {
+ g_object_unref (priv->case_sensitive_button);
+ priv->case_sensitive_button = NULL;
+ }
+
+ if (priv->wrapped_next_box != NULL) {
+ g_object_unref (priv->wrapped_next_box);
+ priv->wrapped_next_box = NULL;
+ }
+
+ if (priv->wrapped_prev_box != NULL) {
+ g_object_unref (priv->wrapped_prev_box);
+ priv->wrapped_prev_box = NULL;
+ }
+
+ if (priv->matches_label != NULL) {
+ g_object_unref (priv->matches_label);
+ priv->matches_label = NULL;
+ }
+
+ if (priv->tokenizer != NULL) {
+ g_object_unref (priv->tokenizer);
+ priv->tokenizer = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+mail_search_bar_finalize (GObject *object)
+{
+ EMailSearchBarPrivate *priv;
+
+ priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (object);
+
+ g_free (priv->active_search);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+mail_search_bar_constructed (GObject *object)
+{
+ EMailSearchBarPrivate *priv;
+
+ priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (object);
+
+ e_mutual_binding_new (
+ G_OBJECT (object), "case-sensitive",
+ G_OBJECT (priv->case_sensitive_button), "active");
+}
+
+static void
+mail_search_bar_show (GtkWidget *widget)
+{
+ EMailSearchBar *search_bar;
+
+ search_bar = E_MAIL_SEARCH_BAR (widget);
+
+ /* Chain up to parent's show() method. */
+ GTK_WIDGET_CLASS (parent_class)->show (widget);
+
+ gtk_widget_grab_focus (search_bar->priv->entry);
+
+ mail_search_bar_update_tokenizer (search_bar);
+}
+
+static void
+mail_search_bar_hide (GtkWidget *widget)
+{
+ EMailSearchBar *search_bar;
+
+ search_bar = E_MAIL_SEARCH_BAR (widget);
+
+ /* Chain up to parent's hide() method. */
+ GTK_WIDGET_CLASS (parent_class)->hide (widget);
+
+ mail_search_bar_update_tokenizer (search_bar);
+}
+
+static gboolean
+mail_search_bar_key_press_event (GtkWidget *widget,
+ GdkEventKey *event)
+{
+ if (event->keyval == GDK_Escape) {
+ gtk_widget_hide (widget);
+ return TRUE;
+ }
+
+ /* Chain up to parent's key_press_event() method. */
+ return GTK_WIDGET_CLASS (parent_class)->
+ key_press_event (widget, event);
+}
+
+static void
+mail_search_bar_clear (EMailSearchBar *search_bar)
+{
+ g_free (search_bar->priv->active_search);
+ search_bar->priv->active_search = NULL;
+
+ gtk_widget_hide (search_bar->priv->wrapped_next_box);
+ gtk_widget_hide (search_bar->priv->wrapped_prev_box);
+ gtk_widget_hide (search_bar->priv->matches_label);
+
+ mail_search_bar_update_tokenizer (search_bar);
+}
+
+static void
+mail_search_bar_class_init (EMailSearchBarClass *class)
+{
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (EMailSearchBarPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = mail_search_bar_set_property;
+ object_class->get_property = mail_search_bar_get_property;
+ object_class->dispose = mail_search_bar_dispose;
+ object_class->finalize = mail_search_bar_finalize;
+ object_class->constructed = mail_search_bar_constructed;
+
+ widget_class = GTK_WIDGET_CLASS (class);
+ widget_class->show = mail_search_bar_show;
+ widget_class->hide = mail_search_bar_hide;
+ widget_class->key_press_event = mail_search_bar_key_press_event;
+
+ class->clear = mail_search_bar_clear;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_CASE_SENSITIVE,
+ g_param_spec_boolean (
+ "case-sensitive",
+ "Case Sensitive",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_HTML,
+ g_param_spec_object (
+ "html",
+ "HTML Display",
+ NULL,
+ GTK_TYPE_HTML,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_TEXT,
+ g_param_spec_string (
+ "text",
+ "Search Text",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE));
+
+ signals[CHANGED] = g_signal_new (
+ "changed",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EMailSearchBarClass, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[CLEAR] = g_signal_new (
+ "clear",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (EMailSearchBarClass, clear),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+mail_search_bar_init (EMailSearchBar *search_bar)
+{
+ GtkWidget *label;
+ GtkWidget *widget;
+ GtkWidget *container;
+
+ search_bar->priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (search_bar);
+ search_bar->priv->tokenizer = e_searching_tokenizer_new ();
+
+ g_signal_connect_swapped (
+ search_bar->priv->tokenizer, "match",
+ G_CALLBACK (mail_search_bar_update_matches), search_bar);
+
+ gtk_box_set_spacing (GTK_BOX (search_bar), 12);
+
+ container = GTK_WIDGET (search_bar);
+
+ widget = gtk_hbox_new (FALSE, 1);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ container = widget;
+
+ widget = gtk_button_new ();
+ gtk_button_set_image (
+ GTK_BUTTON (widget), gtk_image_new_from_stock (
+ GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU));
+ gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text (widget, _("Close the find bar"));
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (gtk_widget_hide), search_bar);
+
+ widget = gtk_label_new_with_mnemonic (_("Fin_d:"));
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 3);
+ gtk_widget_show (widget);
+
+ label = widget;
+
+ widget = gtk_entry_new ();
+ gtk_entry_set_icon_from_stock (
+ GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY,
+ GTK_STOCK_CLEAR);
+ gtk_entry_set_icon_tooltip_text (
+ GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY,
+ _("Clear the search"));
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+ gtk_widget_set_size_request (widget, 200, -1);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ search_bar->priv->entry = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "activate",
+ G_CALLBACK (mail_search_bar_find_next_cb), search_bar);
+
+ g_signal_connect_swapped (
+ widget, "changed",
+ G_CALLBACK (mail_search_bar_changed_cb), search_bar);
+
+ g_signal_connect_swapped (
+ widget, "icon-release",
+ G_CALLBACK (mail_search_bar_icon_release_cb), search_bar);
+
+ widget = gtk_button_new_with_mnemonic (_("_Previous"));
+ gtk_button_set_image (
+ GTK_BUTTON (widget), gtk_image_new_from_stock (
+ GTK_STOCK_GO_BACK, GTK_ICON_SIZE_MENU));
+ gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text (
+ widget, _("Find the previous occurrence of the phrase"));
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (mail_search_bar_find_previous_cb), search_bar);
+
+ widget = gtk_button_new_with_mnemonic (_("_Next"));
+ gtk_button_set_image (
+ GTK_BUTTON (widget), gtk_image_new_from_stock (
+ GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU));
+ gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text (
+ widget, _("Find the next occurrence of the phrase"));
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "clicked",
+ G_CALLBACK (mail_search_bar_find_next_cb), search_bar);
+
+ widget = gtk_check_button_new_with_mnemonic (_("Mat_ch case"));
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ search_bar->priv->case_sensitive_button = g_object_ref (widget);
+ gtk_widget_show (widget);
+
+ g_signal_connect_swapped (
+ widget, "toggled",
+ G_CALLBACK (mail_search_bar_toggled_cb), search_bar);
+
+ g_signal_connect_swapped (
+ widget, "toggled",
+ G_CALLBACK (mail_search_bar_find_next_cb), search_bar);
+
+ container = GTK_WIDGET (search_bar);
+
+ widget = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ search_bar->priv->wrapped_next_box = g_object_ref (widget);
+ gtk_widget_hide (widget);
+
+ container = widget;
+
+ widget = gtk_image_new_from_icon_name (
+ "wrapped", GTK_ICON_SIZE_MENU);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new (
+ _("Reached bottom of page, continued from top"));
+ gtk_label_set_ellipsize (
+ GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ container = GTK_WIDGET (search_bar);
+
+ widget = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ search_bar->priv->wrapped_prev_box = g_object_ref (widget);
+ gtk_widget_hide (widget);
+
+ container = widget;
+
+ widget = gtk_image_new_from_icon_name (
+ "wrapped", GTK_ICON_SIZE_MENU);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ gtk_widget_show (widget);
+
+ widget = gtk_label_new (
+ _("Reached top of page, continued from bottom"));
+ gtk_label_set_ellipsize (
+ GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+ gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+ gtk_widget_show (widget);
+
+ container = GTK_WIDGET (search_bar);
+
+ widget = gtk_label_new (NULL);
+ gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 12);
+ search_bar->priv->matches_label = g_object_ref (widget);
+ gtk_widget_show (widget);
+}
+
+GType
+e_mail_search_bar_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo type_info = {
+ sizeof (EMailSearchBarClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) mail_search_bar_class_init,
+ (GClassFinalizeFunc) NULL,
+ NULL, /* class_data */
+ sizeof (EMailSearchBar),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) mail_search_bar_init,
+ NULL /* value_table */
+ };
+
+ type = g_type_register_static (
+ GTK_TYPE_HBOX, "EMailSearchBar", &type_info, 0);
+ }
+
+ return type;
+}
+
+GtkWidget *
+e_mail_search_bar_new (GtkHTML *html)
+{
+ g_return_val_if_fail (GTK_IS_HTML (html), NULL);
+
+ return g_object_new (E_TYPE_MAIL_SEARCH_BAR, "html", html, NULL);
+}
+
+void
+e_mail_search_bar_clear (EMailSearchBar *search_bar)
+{
+ g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar));
+
+ g_signal_emit (search_bar, signals[CLEAR], 0);
+}
+
+void
+e_mail_search_bar_changed (EMailSearchBar *search_bar)
+{
+ g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar));
+
+ g_signal_emit (search_bar, signals[CHANGED], 0);
+}
+
+GtkHTML *
+e_mail_search_bar_get_html (EMailSearchBar *search_bar)
+{
+ g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), NULL);
+
+ return search_bar->priv->html;
+}
+
+ESearchingTokenizer *
+e_mail_search_bar_get_tokenizer (EMailSearchBar *search_bar)
+{
+ g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), NULL);
+
+ return search_bar->priv->tokenizer;
+}
+
+gboolean
+e_mail_search_bar_get_case_sensitive (EMailSearchBar *search_bar)
+{
+ GtkToggleButton *button;
+
+ g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), FALSE);
+
+ button = GTK_TOGGLE_BUTTON (search_bar->priv->case_sensitive_button);
+
+ return gtk_toggle_button_get_active (button);
+}
+
+void
+e_mail_search_bar_set_case_sensitive (EMailSearchBar *search_bar,
+ gboolean case_sensitive)
+{
+ GtkToggleButton *button;
+
+ g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar));
+
+ button = GTK_TOGGLE_BUTTON (search_bar->priv->case_sensitive_button);
+
+ gtk_toggle_button_set_active (button, case_sensitive);
+
+ g_object_notify (G_OBJECT (search_bar), "case-sensitive");
+}
+
+gchar *
+e_mail_search_bar_get_text (EMailSearchBar *search_bar)
+{
+ GtkEntry *entry;
+ const gchar *text;
+
+ g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), NULL);
+
+ entry = GTK_ENTRY (search_bar->priv->entry);
+ text = gtk_entry_get_text (entry);
+
+ return g_strstrip (g_strdup (text));
+}
+
+void
+e_mail_search_bar_set_text (EMailSearchBar *search_bar,
+ const gchar *text)
+{
+ GtkEntry *entry;
+
+ g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar));
+
+ entry = GTK_ENTRY (search_bar->priv->entry);
+
+ if (text == NULL)
+ text = "";
+
+ /* This will trigger a "notify::text" signal. */
+ gtk_entry_set_text (entry, text);
+}
diff --git a/mail/e-mail-search-bar.h b/mail/e-mail-search-bar.h
new file mode 100644
index 0000000000..7f19e176b7
--- /dev/null
+++ b/mail/e-mail-search-bar.h
@@ -0,0 +1,85 @@
+/*
+ * e-mail-search-bar.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_MAIL_SEARCH_BAR_H
+#define E_MAIL_SEARCH_BAR_H
+
+#include <gtk/gtk.h>
+#include <gtkhtml/gtkhtml.h>
+#include <mail/e-searching-tokenizer.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_SEARCH_BAR \
+ (e_mail_search_bar_get_type ())
+#define E_MAIL_SEARCH_BAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBar))
+#define E_MAIL_SEARCH_BAR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBarClass))
+#define E_IS_MAIL_SEARCH_BAR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_MAIL_SEARCH_BAR))
+#define E_IS_MAIL_SEARCH_BAR_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_MAIL_SEARCH_BAR))
+#define E_MAIL_SEARCH_BAR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBarClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailSearchBar EMailSearchBar;
+typedef struct _EMailSearchBarClass EMailSearchBarClass;
+typedef struct _EMailSearchBarPrivate EMailSearchBarPrivate;
+
+struct _EMailSearchBar {
+ GtkHBox parent;
+ EMailSearchBarPrivate *priv;
+};
+
+struct _EMailSearchBarClass {
+ GtkHBoxClass parent_class;
+
+ /* Signals */
+ void (*changed) (EMailSearchBar *search_bar);
+ void (*clear) (EMailSearchBar *search_bar);
+};
+
+GType e_mail_search_bar_get_type (void);
+GtkWidget * e_mail_search_bar_new (GtkHTML *html);
+void e_mail_search_bar_clear (EMailSearchBar *search_bar);
+void e_mail_search_bar_changed (EMailSearchBar *search_bar);
+GtkHTML * e_mail_search_bar_get_html (EMailSearchBar *search_bar);
+ESearchingTokenizer *
+ e_mail_search_bar_get_tokenizer (EMailSearchBar *search_bar);
+gboolean e_mail_search_bar_get_case_sensitive
+ (EMailSearchBar *search_bar);
+void e_mail_search_bar_set_case_sensitive
+ (EMailSearchBar *search_bar,
+ gboolean case_sensitive);
+gchar * e_mail_search_bar_get_text (EMailSearchBar *search_bar);
+void e_mail_search_bar_set_text (EMailSearchBar *search_bar,
+ const gchar *text);
+
+G_END_DECLS
+
+#endif /* E_MAIL_SEARCH_BAR_H */
diff --git a/mail/e-searching-tokenizer.c b/mail/e-searching-tokenizer.c
index 9704ebb96d..3d98cdeb4f 100644
--- a/mail/e-searching-tokenizer.c
+++ b/mail/e-searching-tokenizer.c
@@ -1052,10 +1052,10 @@ e_searching_tokenizer_get_type (void)
return type;
}
-HTMLTokenizer *
+ESearchingTokenizer *
e_searching_tokenizer_new (void)
{
- return (HTMLTokenizer *) g_object_new (E_TYPE_SEARCHING_TOKENIZER, NULL);
+ return g_object_new (E_TYPE_SEARCHING_TOKENIZER, NULL);
}
/** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
diff --git a/mail/e-searching-tokenizer.h b/mail/e-searching-tokenizer.h
index ecc914dab7..37a0048c0c 100644
--- a/mail/e-searching-tokenizer.h
+++ b/mail/e-searching-tokenizer.h
@@ -52,7 +52,7 @@ struct _ESearchingTokenizerClass {
GType e_searching_tokenizer_get_type (void);
-HTMLTokenizer *e_searching_tokenizer_new (void);
+ESearchingTokenizer *e_searching_tokenizer_new (void);
/* For now, just a simple API */
diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c
index 9a80a0c254..0aba4c1045 100644
--- a/mail/em-folder-browser.c
+++ b/mail/em-folder-browser.c
@@ -79,6 +79,7 @@
#include "e-util/e-error.h"
#include "e-util/e-util-private.h"
#include "e-util/e-util-labels.h"
+#include "e-mail-search-bar.h"
#include "em-utils.h"
#include "em-composer-utils.h"
#include "em-format-html-display.h"
@@ -106,6 +107,7 @@ CamelStore *vfolder_store; /* the 1 static vfolder store */
struct _EMFolderBrowserPrivate {
GtkWidget *preview; /* container for message display */
GtkWidget *scroll;
+ GtkWidget *search_bar;
GtkWidget *subscribe_editor;
@@ -239,7 +241,6 @@ static ESearchBarItem emfb_search_scope_items[] = {
E_FILTERBAR_CURRENT_FOLDER,
E_FILTERBAR_CURRENT_ACCOUNT,
E_FILTERBAR_ALL_ACCOUNTS,
- E_FILTERBAR_CURRENT_MESSAGE,
{ NULL, -1, 0 }
};
@@ -485,6 +486,7 @@ emfb_init(GObject *o)
EMFolderBrowser *emfb = (EMFolderBrowser *)o;
RuleContext *search_context = mail_component_peek_search_context (mail_component_peek ());
struct _EMFolderBrowserPrivate *p;
+ GtkWidget *html;
EMEvent *eme;
EMEventTargetFolderBrowser *target;
@@ -527,7 +529,6 @@ emfb_init(GObject *o)
efb->account_search_cancel = NULL;
e_search_bar_set_menu ((ESearchBar *)emfb->search, emfb_search_items);
e_search_bar_set_scopeoption ((ESearchBar *)emfb->search, emfb_search_scope_items);
- e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, FALSE);
emfb->priv->scope_restricted = TRUE;
g_signal_connect(emfb, "realize", G_CALLBACK(emfb_realize), NULL);
gtk_widget_show((GtkWidget *)emfb->search);
@@ -561,14 +562,21 @@ emfb_init(GObject *o)
gtk_scrolled_window_set_shadow_type((GtkScrolledWindow *)p->scroll, GTK_SHADOW_IN);
gtk_widget_show(p->scroll);
- p->preview = gtk_vbox_new (FALSE, 6);
- gtk_container_add((GtkContainer *)p->scroll, (GtkWidget *)emfb->view.preview->formathtml.html);
- gtk_widget_show((GtkWidget *)emfb->view.preview->formathtml.html);
+ html = GTK_WIDGET (emfb->view.preview->formathtml.html);
+
+ p->preview = gtk_vbox_new (FALSE, 1);
+ p->search_bar = e_mail_search_bar_new (GTK_HTML (html));
+ gtk_container_add((GtkContainer *)p->scroll, html);
+ gtk_widget_show(html);
gtk_box_pack_start ((GtkBox *)p->preview, p->scroll, TRUE, TRUE, 0);
- gtk_box_pack_start ((GtkBox *)p->preview, em_format_html_get_search_dialog (emfb->view.preview), FALSE, FALSE, 0);
+ gtk_box_pack_start ((GtkBox *)p->preview, p->search_bar, FALSE, FALSE, 0);
gtk_paned_pack2 (GTK_PANED (emfb->vpane), p->preview, TRUE, FALSE);
gtk_widget_show(p->preview);
+ g_signal_connect_swapped (
+ p->search_bar, "changed",
+ G_CALLBACK (em_format_redraw), emfb->view.preview);
+
/** @HookPoint-EMFolderBrower: Folder Browser
* @Id: emfb.created
* @Class: org.gnome.evolution.mail.events:1.0
@@ -638,6 +646,14 @@ emfb_destroy(GtkObject *o)
}
static void
+emfb_show_search_bar (EMFolderView *folder_view)
+{
+ EMFolderBrowser *browser = (EMFolderBrowser *) folder_view;
+
+ gtk_widget_show (browser->priv->search_bar);
+}
+
+static void
emfb_class_init(GObjectClass *klass)
{
klass->finalize = emfb_finalise;
@@ -666,6 +682,7 @@ emfb_class_init(GObjectClass *klass)
((GtkObjectClass *)klass)->destroy = emfb_destroy;
((EMFolderViewClass *)klass)->set_folder = emfb_set_folder;
((EMFolderViewClass *)klass)->activate = emfb_activate;
+ ((EMFolderViewClass *)klass)->show_search_bar = emfb_show_search_bar;
}
GType
@@ -711,7 +728,6 @@ void em_folder_browser_show_preview(EMFolderBrowser *emfb, gboolean state)
if ((emfb->view.preview_active ^ state) == 0
|| emfb->view.list == NULL) {
if (state && emfb->priv->scope_restricted && emfb->view.list->cursor_uid && *(emfb->view.list->cursor_uid)) {
- e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, TRUE);
emfb->priv->scope_restricted = FALSE;
}
@@ -733,7 +749,6 @@ void em_folder_browser_show_preview(EMFolderBrowser *emfb, gboolean state)
if (emfb->view.list->cursor_uid) {
char *uid = g_alloca(strlen(emfb->view.list->cursor_uid)+1);
- e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, TRUE);
emfb->priv->scope_restricted = FALSE;
strcpy(uid, emfb->view.list->cursor_uid);
em_folder_view_set_message(&emfb->view, uid, FALSE);
@@ -749,7 +764,6 @@ void em_folder_browser_show_preview(EMFolderBrowser *emfb, gboolean state)
emfb->view.displayed_uid = NULL;
gtk_widget_hide(emfb->priv->preview);
- e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, FALSE);
emfb->priv->scope_restricted = TRUE;
/*
mail_display_set_message (emfb->mail_display, NULL, NULL, NULL);
@@ -841,6 +855,8 @@ static void
emfb_search_config_search(EFilterBar *efb, FilterRule *rule, int id, const char *query, void *data)
{
EMFolderBrowser *emfb = data;
+ EMailSearchBar *search_bar;
+ ESearchingTokenizer *tokenizer;
GList *partl;
struct _camel_search_words *words;
int i;
@@ -877,15 +893,26 @@ emfb_search_config_search(EFilterBar *efb, FilterRule *rule, int id, const char
partl = partl->next;
}
- em_format_html_display_set_search(emfb->view.preview,
- EM_FORMAT_HTML_DISPLAY_SEARCH_SECONDARY|EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE,
- strings);
- while (strings) {
- GSList *n = strings->next;
- g_free(strings->data);
- g_slist_free_1(strings);
- strings = n;
+ search_bar = E_MAIL_SEARCH_BAR (emfb->priv->search_bar);
+
+ /* XXX This is a hack, but this code is on its way out anyway.
+ * Function is called once before the search bar is created. */
+ if (!E_IS_MAIL_SEARCH_BAR (search_bar))
+ return;
+
+ tokenizer = e_mail_search_bar_get_tokenizer (search_bar);
+
+ e_searching_tokenizer_set_secondary_case_sensitivity (tokenizer, FALSE);
+ e_searching_tokenizer_set_secondary_search_string (tokenizer, NULL);
+
+ while (strings != NULL) {
+ e_searching_tokenizer_add_secondary_search_string (
+ tokenizer, strings->data);
+ g_free (strings->data);
+ strings = g_slist_delete_link (strings, strings);
}
+
+ e_mail_search_bar_changed (search_bar);
}
static char *
@@ -1125,18 +1152,6 @@ emfb_search_search_activated(ESearchBar *esb, EMFolderBrowser *emfb)
id = e_search_bar_get_search_scope (esb);
switch (id) {
- case E_FILTERBAR_CURRENT_MESSAGE_ID:
- word = e_search_bar_get_text (esb);
- if ( word && *word ) {
- gtk_widget_set_sensitive (esb->option_button, FALSE);
- em_format_html_display_search_with (emfb->view.preview, word);
- } else {
- em_format_html_display_search_close (emfb->view.preview);
- }
- g_free (word);
- return;
- break;
-
case E_FILTERBAR_CURRENT_FOLDER_ID:
g_object_get (esb, "query", &search_word, NULL);
break;
@@ -1386,10 +1401,8 @@ emfb_list_message_selected (MessageList *ml, const char *uid, EMFolderBrowser *e
return;
if (uid && *uid && emfb->priv->scope_restricted && emfb->view.preview_active) {
- e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, TRUE);
emfb->priv->scope_restricted = FALSE;
} else if ( !(uid && *uid) && !emfb->priv->scope_restricted) {
- e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, FALSE);
emfb->priv->scope_restricted = TRUE;
}
diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c
index e31d8d727c..62bab8a48f 100644
--- a/mail/em-folder-view.c
+++ b/mail/em-folder-view.c
@@ -956,7 +956,7 @@ emfv_popup_flag_completed(EPopup *ep, EPopupItem *pitem, void *data)
em_utils_flag_for_followup_completed((GtkWidget *)emfv, emfv->folder, uids);
if (emfv->preview)
- em_format_redraw (emfv->preview);
+ em_format_redraw (EM_FORMAT (emfv->preview));
}
static void
@@ -968,7 +968,7 @@ emfv_popup_flag_clear(EPopup *ep, EPopupItem *pitem, void *data)
em_utils_flag_for_followup_clear((GtkWidget *)emfv, emfv->folder, uids);
if (emfv->preview)
- em_format_redraw (emfv->preview);
+ em_format_redraw (EM_FORMAT (emfv->preview));
}
static void
@@ -1808,13 +1808,7 @@ emfv_message_search(BonoboUIComponent *uic, void *data, const char *path)
{
EMFolderView *emfv = data;
- if (!emfv->list_active) /* We are in new mail window */
- em_format_html_display_search(emfv->preview);
- else {
- /* We are in top level. Just grab focus to Search Bar */
- gtk_widget_grab_focus (((ESearchBar *)((EMFolderBrowser *) emfv)->search)->entry);
- gtk_option_menu_set_history (GTK_OPTION_MENU (((ESearchBar *)((EMFolderBrowser *) emfv)->search)->scopeoption), 3);
- }
+ em_folder_view_show_search_bar (emfv);
}
static void
@@ -3271,3 +3265,15 @@ emfv_on_html_button_released_cb (GtkHTML *html, GdkEventButton *button, EMFolder
return FALSE;
}
+void
+em_folder_view_show_search_bar (EMFolderView *emfv)
+{
+ EMFolderViewClass *class;
+
+ g_return_if_fail (EM_IS_FOLDER_VIEW (emfv));
+
+ class = EM_FOLDER_VIEW_GET_CLASS (emfv);
+ g_return_if_fail (class->show_search_bar != NULL);
+
+ class->show_search_bar (emfv);
+}
diff --git a/mail/em-folder-view.h b/mail/em-folder-view.h
index 4af4760cac..b69a4a1a05 100644
--- a/mail/em-folder-view.h
+++ b/mail/em-folder-view.h
@@ -124,6 +124,8 @@ struct _EMFolderViewClass {
void (*set_folder)(EMFolderView *emfv, struct _CamelFolder *folder, const char *uri);
void (*set_message)(EMFolderView *emfv, const char *uid, int nomarkseen);
+ void (*show_search_bar)(EMFolderView *emfv);
+
/* Signals */
void (*on_url)(EMFolderView *emfv, const char *uri, const char *nice_uri);
@@ -153,6 +155,7 @@ guint32 em_folder_view_disable_mask(EMFolderView *emfv);
void em_folder_view_set_statusbar(EMFolderView *emfv, gboolean statusbar);
void em_folder_view_set_hide_deleted(EMFolderView *emfv, gboolean status);
void em_folder_view_setup_view_instance (EMFolderView *emfv);
+void em_folder_view_show_search_bar (EMFolderView *emfv);
G_END_DECLS
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index aba9c64069..cf1626ecd0 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -40,7 +40,6 @@
#include <gtkhtml/gtkhtml.h>
#include <gtkhtml/gtkhtml-embedded.h>
-#include <gtkhtml/gtkhtml-search.h>
#include <glade/glade.h>
@@ -76,7 +75,6 @@
#include "e-mail-attachment-bar.h"
#include "em-format-html-display.h"
-#include "e-searching-tokenizer.h"
#include "em-icon-stream.h"
#include "em-utils.h"
#include "em-popup.h"
@@ -97,17 +95,6 @@
#define d(x)
struct _EMFormatHTMLDisplayPrivate {
- /* For the interactive search dialogue */
- /* TODO: Should this be more subtle, like the mozilla one? */
- GtkHBox *search_dialog;
- GtkWidget *search_entry;
- GtkWidget *search_entry_box;
- GtkWidget *search_matches_label;
- GtkWidget *search_case_check;
- char *search_text;
- int search_wrap; /* are we doing a wrap search */
- gboolean search_active; /* if the search is active */
-
GtkWidget *attachment_view; /* weak reference */
};
@@ -167,7 +154,6 @@ static void efhd_format_source(EMFormat *, CamelStream *, CamelMimePart *);
static void efhd_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *);
static void efhd_format_optional(EMFormat *, CamelStream *, CamelMimePart *, CamelStream *);
static void efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid);
-static void efhd_complete(EMFormat *);
static void efhd_builtin_init(EMFormatHTMLDisplayClass *efhc);
@@ -246,9 +232,6 @@ efhd_init(GObject *o)
efhd->priv = g_malloc0(sizeof(*efhd->priv));
- efhd->search_tok = (ESearchingTokenizer *)e_searching_tokenizer_new();
- gtk_html_set_tokenizer (efh->html, (HTMLTokenizer *)efhd->search_tok);
-
g_signal_connect(efh->html, "realize", G_CALLBACK(efhd_gtkhtml_realise), o);
g_signal_connect(efh->html, "style-set", G_CALLBACK(efhd_gtkhtml_style_set), o);
/* we want to convert url's etc */
@@ -265,7 +248,6 @@ efhd_finalise(GObject *o)
/* check pending stuff */
- g_free(efhd->priv->search_text);
g_free(efhd->priv);
((GObjectClass *)efhd_parent)->finalize(o);
@@ -291,7 +273,6 @@ efhd_class_init(GObjectClass *klass)
((EMFormatClass *)klass)->format_attachment = efhd_format_attachment;
((EMFormatClass *)klass)->format_optional = efhd_format_optional;
((EMFormatClass *)klass)->format_secure = efhd_format_secure;
- ((EMFormatClass *)klass)->complete = efhd_complete;
klass->finalize = efhd_finalise;
@@ -401,316 +382,6 @@ void em_format_html_display_set_caret_mode(EMFormatHTMLDisplay *efhd, gboolean s
}
void
-em_format_html_display_set_search(EMFormatHTMLDisplay *efhd, int type, GSList *strings)
-{
- switch(type&3) {
- case EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY:
- e_searching_tokenizer_set_primary_case_sensitivity(efhd->search_tok, (type&EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE) == 0);
- e_searching_tokenizer_set_primary_search_string(efhd->search_tok, NULL);
- while (strings) {
- e_searching_tokenizer_add_primary_search_string(efhd->search_tok, strings->data);
- strings = strings->next;
- }
- break;
- case EM_FORMAT_HTML_DISPLAY_SEARCH_SECONDARY:
- default:
- e_searching_tokenizer_set_secondary_case_sensitivity(efhd->search_tok, (type&EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE) == 0);
- e_searching_tokenizer_set_secondary_search_string(efhd->search_tok, NULL);
- while (strings) {
- e_searching_tokenizer_add_secondary_search_string(efhd->search_tok, strings->data);
- strings = strings->next;
- }
- break;
- }
-
- d(printf("redrawing with search\n"));
- em_format_redraw((EMFormat *)efhd);
-}
-
-static void
-efhd_update_matches(EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
- char *str;
- /* message-search popup match count string */
- char *fmt = _("Matches: %d");
-
- if (p->search_dialog) {
- str = alloca(strlen(fmt)+32);
- sprintf(str, fmt, e_searching_tokenizer_match_count(efhd->search_tok));
- gtk_label_set_text((GtkLabel *)p->search_matches_label, str);
- }
- gtk_widget_show((GtkWidget *)p->search_matches_label);
-
-}
-
-static void
-efhd_update_search(EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
- GSList *words = NULL;
- int flags = 0;
-
- if (!gtk_toggle_button_get_active((GtkToggleButton *)p->search_case_check))
- flags = EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE | EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY;
- else
- flags = EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY;
-
- if (p->search_text)
- words = g_slist_append(words, p->search_text);
-
- em_format_html_display_set_search(efhd, flags, words);
- g_slist_free(words);
-}
-
-static void
-efhd_search_response(GtkWidget *w, EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
- char *txt = g_strdup(gtk_entry_get_text((GtkEntry *)p->search_entry));
-
- g_strstrip(txt);
- if (p->search_text && strcmp(p->search_text, txt) == 0 && !p->search_wrap) {
- gtk_html_engine_search_set_forward (((EMFormatHTML *)efhd)->html, TRUE);
- if (!gtk_html_engine_search_next(((EMFormatHTML *)efhd)->html))
- p->search_wrap = TRUE;
- g_free(txt);
- } else {
- g_free(p->search_text);
- p->search_text = txt;
- if (!p->search_wrap)
- efhd_update_search(efhd);
- p->search_wrap = FALSE;
- gtk_html_engine_search(((EMFormatHTML *)efhd)->html, txt,
- gtk_toggle_button_get_active((GtkToggleButton *)p->search_case_check),
- TRUE, FALSE);
- }
-}
-
-
-static void
-efhd_search_response_back (GtkWidget *w, EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
- char *txt = g_strdup(gtk_entry_get_text((GtkEntry *)p->search_entry));
-
- g_strstrip(txt);
- if (p->search_text && strcmp(p->search_text, txt) == 0 && !p->search_wrap) {
- gtk_html_engine_search_set_forward (((EMFormatHTML *)efhd)->html, FALSE);
- if (!gtk_html_engine_search_next(((EMFormatHTML *)efhd)->html))
- p->search_wrap = TRUE;
- g_free(txt);
- } else {
- g_free(p->search_text);
- p->search_text = txt;
- if (!p->search_wrap)
- efhd_update_search(efhd);
- p->search_wrap = FALSE;
- gtk_html_engine_search(((EMFormatHTML *)efhd)->html, txt,
- gtk_toggle_button_get_active((GtkToggleButton *)p->search_case_check),
- FALSE, FALSE);
- }
-}
-
-
-static void
-efhd_search_destroy(GtkWidget *w, EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
- g_free(p->search_text);
- p->search_text = NULL;
- gtk_widget_hide((GtkWidget *)p->search_dialog);
- em_format_html_display_set_search(efhd, EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY, NULL);
- p->search_active = FALSE;
-}
-
-static void
-efhd_search_case_toggled(GtkWidget *w, EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
- g_free(p->search_text);
- p->search_text = NULL;
- efhd_search_response(w, efhd);
-}
-
-static gboolean
-efhd_key_pressed (GtkWidget *w, GdkEventKey *event, EMFormatHTMLDisplay *efhd)
-{
- if (event->keyval == GDK_Escape){
- efhd_search_destroy (w, efhd);
- return TRUE;
- }
- return FALSE;
-}
-
-static void
-clear_button_clicked_cb (GtkWidget *widget, gpointer dummy, EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
- gtk_entry_set_text (GTK_ENTRY (p->search_entry), "");
-
- g_signal_emit_by_name (p->search_entry, "activate", efhd);
-}
-
-/* Controlls the visibility of icon_entry's visibility */
-static void
-icon_entry_changed_cb (GtkWidget *widget, GtkWidget *clear_button)
-{
- const char *text = gtk_entry_get_text (GTK_ENTRY (widget));
-
- if (text && *text)
- gtk_widget_show (clear_button);
- else
- gtk_widget_hide (clear_button);
-}
-
-GtkWidget *
-em_format_html_get_search_dialog (EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
- GtkWidget *hbox2, *button3, *button2, *label1;
- GtkWidget *icon_entry, *clear_button;
-
- p->search_entry_box = gtk_hbox_new (FALSE, 0);
-
- label1 = gtk_label_new_with_mnemonic (_("Fin_d:"));
- gtk_widget_show (label1);
- gtk_box_pack_start ((GtkBox *)(p->search_entry_box), label1, FALSE, FALSE, 5);
-
- /* Icon entry */
- icon_entry = e_icon_entry_new ();
- p->search_entry = e_icon_entry_get_entry (E_ICON_ENTRY (icon_entry));
- gtk_label_set_mnemonic_widget (GTK_LABEL (label1), p->search_entry);
- gtk_widget_show (p->search_entry);
- clear_button = e_icon_entry_create_button ("gtk-clear");
- e_icon_entry_pack_widget (E_ICON_ENTRY (icon_entry), clear_button, FALSE);
- gtk_widget_show_all (icon_entry);
- gtk_widget_hide (clear_button);
-
- g_signal_connect (G_OBJECT (clear_button), "button-press-event", (GCallback) clear_button_clicked_cb, efhd);
- g_signal_connect (G_OBJECT (p->search_entry), "changed", (GCallback) icon_entry_changed_cb, clear_button);
-
- gtk_box_pack_start ((GtkBox *)(p->search_entry_box), icon_entry, FALSE, FALSE, 0);
- /* gtk_box_pack_start ((GtkBox *)(p->search_entry_box), icon_entry, TRUE, TRUE, 0); */
-
- hbox2 = gtk_hbox_new (FALSE, 0);
- gtk_box_pack_start ((GtkBox *)(hbox2), p->search_entry_box, FALSE, FALSE, 5);
- /* gtk_box_pack_start ((GtkBox *)(hbox2), p->search_entry_box, TRUE, TRUE, 5); */
-
- button3 = gtk_button_new_with_mnemonic (_("_Previous"));
- gtk_button_set_image (GTK_BUTTON (button3), GTK_WIDGET(gtk_image_new_from_stock(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON)));
- gtk_widget_show (button3);
- gtk_box_pack_start (GTK_BOX (hbox2), button3, FALSE, FALSE, 5);
-
- button2 = gtk_button_new_with_mnemonic (_("_Next"));
- gtk_button_set_image (GTK_BUTTON (button2), gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON));
- gtk_widget_show (button2);
- gtk_box_pack_start (GTK_BOX (hbox2), button2, FALSE, FALSE, 5);
-
- p->search_case_check = gtk_check_button_new_with_mnemonic (_("M_atch case"));
- gtk_widget_show (p->search_case_check);
- gtk_box_pack_start (GTK_BOX (hbox2), p->search_case_check, FALSE, FALSE, 0);
-
- p->search_matches_label = gtk_label_new ("");
- gtk_widget_show (p->search_matches_label);
- gtk_box_pack_start (GTK_BOX (hbox2), p->search_matches_label, TRUE, TRUE, 0);
- p->search_dialog = GTK_HBOX (hbox2);
-
- p->search_wrap = FALSE;
-
- g_signal_connect (p->search_entry, "activate", G_CALLBACK(efhd_search_response), efhd);
- g_signal_connect (p->search_entry, "key-press-event", G_CALLBACK(efhd_key_pressed), efhd);
- g_signal_connect (p->search_case_check, "toggled", G_CALLBACK(efhd_search_case_toggled), efhd);
- g_signal_connect (button2, "clicked", G_CALLBACK(efhd_search_response), efhd);
- g_signal_connect (button3, "clicked", G_CALLBACK(efhd_search_response_back), efhd);
-
- p->search_active = FALSE;
-
- efhd_update_matches(efhd);
-
- return (GtkWidget *)p->search_dialog;
-
-}
-
-static void
-set_focus_cb (GtkWidget *window, GtkWidget *widget, EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
- GtkWidget *sbar = GTK_WIDGET (p->search_dialog);
-
- while (widget != NULL && widget != sbar) {
- widget = widget->parent;
- }
-
- if (widget != sbar)
- efhd_search_destroy(widget, efhd);
-}
-
-/**
- * em_format_html_display_search:
- * @efhd:
- *
- * Run an interactive search dialogue.
- **/
-void
-em_format_html_display_search(EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
- if (p->search_dialog){
- GtkWidget *toplevel;
-
- gtk_widget_show (GTK_WIDGET (p->search_dialog));
- gtk_widget_grab_focus (p->search_entry);
- gtk_widget_show (p->search_entry_box);
-
- p->search_active = TRUE;
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (p->search_dialog));
-
- g_signal_connect (toplevel, "set-focus",
- G_CALLBACK (set_focus_cb), efhd);
- }
-
-}
-/**
- * em_format_html_display_search_with:
- * @efhd:
- *
- * Run an interactive search dialogue.
- **/
-void
-em_format_html_display_search_with (EMFormatHTMLDisplay *efhd, char *word)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
- if (p->search_dialog){
- gtk_widget_show (GTK_WIDGET (p->search_dialog));
- p->search_active = TRUE;
-
- /* Set the query */
- gtk_entry_set_text (GTK_ENTRY (p->search_entry), word);
- gtk_widget_hide (p->search_entry_box);
-
- /* Trigger the search */
- g_signal_emit_by_name (p->search_entry, "activate", efhd);
- }
-}
-
-void
-em_format_html_display_search_close (EMFormatHTMLDisplay *efhd)
-{
- struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
- if (p->search_dialog && p->search_active)
- efhd_search_destroy(GTK_WIDGET (p->search_dialog), efhd);
-}
-
-void
em_format_html_display_cut (EMFormatHTMLDisplay *efhd)
{
gtk_html_cut (((EMFormatHTML *) efhd)->html);
@@ -889,15 +560,6 @@ efhd_html_on_url (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd)
g_signal_emit((GObject *)efhd, efhd_signals[EFHD_ON_URL], 0, url);
}
-static void
-efhd_complete(EMFormat *emf)
-{
- EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)emf;
-
- if (efhd->priv->search_dialog && efhd->priv->search_active)
- efhd_update_matches(efhd);
-}
-
/* ********************************************************************** */
/* TODO: move the dialogue elsehwere */
diff --git a/mail/em-format-html-display.h b/mail/em-format-html-display.h
index 10a379d7f6..99234e9c1e 100644
--- a/mail/em-format-html-display.h
+++ b/mail/em-format-html-display.h
@@ -105,8 +105,6 @@ void em_format_html_display_search_with
void em_format_html_display_search_close
(EMFormatHTMLDisplay *efhd);
-GtkWidget * em_format_html_get_search_dialog(EMFormatHTMLDisplay *efhd);
-
void em_format_html_display_cut (EMFormatHTMLDisplay *efhd);
void em_format_html_display_copy (EMFormatHTMLDisplay *efhd);
void em_format_html_display_paste (EMFormatHTMLDisplay *efhd);
diff --git a/mail/em-format.c b/mail/em-format.c
index 1d5570be96..826ef11b63 100644
--- a/mail/em-format.c
+++ b/mail/em-format.c
@@ -772,7 +772,43 @@ emf_busy(EMFormat *emf)
* a display refresh, or it can be used to generate an identical layout,
* e.g. to print what the user has shown inline.
**/
-/* e_format_format_clone is a macro */
+void
+em_format_format_clone (EMFormat *emf,
+ CamelFolder *folder,
+ const gchar *uid,
+ CamelMimeMessage *message,
+ EMFormat *source)
+{
+ EMFormatClass *class;
+
+ g_return_if_fail (EM_IS_FORMAT (emf));
+ g_return_if_fail (folder == NULL || CAMEL_IS_FOLDER (folder));
+ g_return_if_fail (message == NULL || CAMEL_IS_MIME_MESSAGE (message));
+ g_return_if_fail (source == NULL || EM_IS_FORMAT (source));
+
+ class = EM_FORMAT_GET_CLASS (emf);
+ g_return_if_fail (class->format_clone != NULL);
+ class->format_clone (emf, folder, uid, message, source);
+}
+
+void
+em_format_format (EMFormat *emf,
+ CamelFolder *folder,
+ const gchar *uid,
+ CamelMimeMessage *message)
+{
+ /* em_format_format_clone() will check the arguments. */
+ em_format_format_clone (emf, folder, uid, message, NULL);
+}
+
+void
+em_format_redraw (EMFormat *emf)
+{
+ g_return_if_fail (EM_IS_FORMAT (emf));
+
+ em_format_format_clone (
+ emf, emf->folder, emf->uid, emf->message, emf);
+}
/**
* em_format_set_session:
diff --git a/mail/em-format.h b/mail/em-format.h
index 92c6b3dddf..f11e73937a 100644
--- a/mail/em-format.h
+++ b/mail/em-format.h
@@ -324,14 +324,10 @@ void em_format_push_level(EMFormat *emf);
void em_format_pull_level(EMFormat *emf);
/* clones inline state/view and format, or use to redraw */
-#define em_format_format_clone(emf, folder, uid, msg, src) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_clone((emf), (folder), (uid), (msg), (src))
+void em_format_format_clone (EMFormat *emf, CamelFolder *folder, const gchar *uid, CamelMimeMessage *message, EMFormat *source);
/* formats a new message */
-#define em_format_format(emf, folder, uid, msg) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_clone((emf), (folder), (uid), (msg), NULL)
-#define em_format_redraw(emf) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_clone((EMFormat *)(emf), \
- ((EMFormat *)(emf))->folder, \
- ((EMFormat *)(emf))->uid, \
- ((EMFormat *)(emf))->message, \
- (EMFormat *)(emf))
+void em_format_format(EMFormat *emf, CamelFolder *folder, const gchar *uid, CamelMimeMessage *message);
+void em_format_redraw(EMFormat *emf);
void em_format_format_error(EMFormat *emf, CamelStream *stream, const char *fmt, ...);
#define em_format_format_attachment(emf, stream, msg, type, info) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_attachment((emf), (stream), (msg), (type), (info))
#define em_format_format_source(emf, stream, msg) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_source((emf), (stream), (msg))
diff --git a/mail/em-message-browser.c b/mail/em-message-browser.c
index 728b27ec43..973708bc2b 100644
--- a/mail/em-message-browser.c
+++ b/mail/em-message-browser.c
@@ -48,6 +48,7 @@
#include "e-util/e-util-private.h"
+#include "e-mail-search-bar.h"
#include "em-format-html-display.h"
#include "em-message-browser.h"
#include "em-menu.h"
@@ -63,6 +64,7 @@
struct _EMMessageBrowserPrivate {
GtkWidget *preview; /* container for message display */
+ GtkWidget *search_bar;
};
static gpointer parent_class;
@@ -225,6 +227,14 @@ emmb_destroy (GtkObject *gtk_object)
}
static void
+emmb_show_search_bar (EMFolderView *folder_view)
+{
+ EMMessageBrowser *browser = EM_MESSAGE_BROWSER (folder_view);
+
+ gtk_widget_show (browser->priv->search_bar);
+}
+
+static void
emmb_class_init (EMMessageBrowserClass *class)
{
GtkObjectClass *gtk_object_class;
@@ -240,12 +250,14 @@ emmb_class_init (EMMessageBrowserClass *class)
folder_view_class->update_message_style = FALSE;
folder_view_class->set_message = emmb_set_message;
folder_view_class->activate = emmb_activate;
+ folder_view_class->show_search_bar = emmb_show_search_bar;
}
static void
emmb_init (EMMessageBrowser *emmb)
{
EMFolderView *emfv = EM_FOLDER_VIEW (emmb);
+ GtkWidget *container;
GtkWidget *widget;
gchar *filename;
@@ -265,25 +277,35 @@ emmb_init (EMMessageBrowser *emmb)
EVOLUTION_UIDIR, "evolution-mail-message.xml", NULL);
emfv->ui_files = g_slist_append (emfv->ui_files, filename);
+ gtk_box_set_spacing (GTK_BOX (emmb), 1);
+
+ container = GTK_WIDGET (emmb);
+
widget = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (
GTK_SCROLLED_WINDOW (widget),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type (
GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
- gtk_widget_show (widget);
+ gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
emmb->priv->preview = widget;
+ gtk_widget_show (widget);
+
+ widget = e_mail_search_bar_new (emfv->preview->formathtml.html);
+ gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+ emmb->priv->search_bar = widget;
+ gtk_widget_hide (widget);
+
+ g_signal_connect_swapped (
+ widget, "changed",
+ G_CALLBACK (em_format_redraw), emfv->preview);
+
+ container = emmb->priv->preview;
widget = GTK_WIDGET (emfv->preview->formathtml.html);
- gtk_container_add (GTK_CONTAINER (emmb->priv->preview), widget);
+ gtk_container_add (GTK_CONTAINER (container), widget);
gtk_widget_show (widget);
- gtk_box_pack_start (
- GTK_BOX (emmb), emmb->priv->preview, TRUE, TRUE, 0);
- gtk_box_pack_start(
- GTK_BOX (emmb), em_format_html_get_search_dialog (
- emfv->preview), FALSE, FALSE, 0);
-
/** @HookPoint-EMMenu: Standalone Message View Menu
* @Id: org.gnome.evolution.mail.messagebrowser
* @Class: org.gnome.evolution.mail.bonobomenu:1.0
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 7685e76845..958864647d 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -804,7 +804,7 @@ tag_editor_response (GtkWidget *dialog, int button, struct ted_t *ted)
camel_tag_list_free (&tags);
if (ted->emfv->preview)
- em_format_redraw(ted->emfv->preview);
+ em_format_redraw (EM_FORMAT (ted->emfv->preview));
}
gtk_widget_destroy (dialog);