balsa r7839 - in trunk: . libbalsa src
- From: PeterB svn gnome org
- To: svn-commits-list gnome org
- Subject: balsa r7839 - in trunk: . libbalsa src
- Date: Fri, 8 Feb 2008 03:57:27 +0000 (GMT)
Author: PeterB
Date: Fri Feb 8 03:57:27 2008
New Revision: 7839
URL: http://svn.gnome.org/viewvc/balsa?rev=7839&view=rev
Log:
find in message
Modified:
trunk/ChangeLog
trunk/libbalsa/libbalsa.c
trunk/src/balsa-message.c
trunk/src/balsa-message.h
trunk/src/main-window.c
Modified: trunk/libbalsa/libbalsa.c
==============================================================================
--- trunk/libbalsa/libbalsa.c (original)
+++ trunk/libbalsa/libbalsa.c Fri Feb 8 03:57:27 2008
@@ -750,7 +750,9 @@
self = pthread_self();
if (libbalsa_threads_lock == 0 || self != libbalsa_threads_id) {
- g_warning("Not holding gdk lock!!!");
+#if WARN_ABOUT_THREADS_ERRORS
+ g_warning("%s: Not holding gdk lock!!!", __func__);
+#endif /* WARN_ABOUT_THREADS_ERRORS */
return;
}
Modified: trunk/src/balsa-message.c
==============================================================================
--- trunk/src/balsa-message.c (original)
+++ trunk/src/balsa-message.c Fri Feb 8 03:57:27 2008
@@ -368,9 +368,246 @@
gtk_container_foreach (GTK_CONTAINER(widget), balsa_mime_widget_image_resize_all, NULL);
}
+/*
+ * Callbacks and helpers for the find bar.
+ */
+
+static void
+bm_scroll_to_iter(BalsaMessage * bm, GtkTextView * text_view,
+ GtkTextIter * iter)
+{
+ GtkAdjustment *adj = GTK_VIEWPORT(bm->cont_viewport)->vadjustment;
+ GdkRectangle location;
+ gdouble y;
+
+ gtk_text_view_get_iter_location(text_view, iter, &location);
+ gtk_text_view_buffer_to_window_coords(text_view,
+ GTK_TEXT_WINDOW_WIDGET,
+ location.x, location.y,
+ NULL, &location.y);
+ gtk_widget_translate_coordinates(GTK_WIDGET(text_view),
+ bm->bm_widget->widget,
+ location.x, location.y,
+ NULL, &location.y);
+
+ y = location.y;
+ gtk_adjustment_clamp_page(adj, y - adj->step_increment,
+ y + adj->step_increment);
+}
+
+static void
+bm_find_entry_changed_cb(GtkEditable * editable, gpointer data)
+{
+ GtkEntry *entry = GTK_ENTRY(editable);
+ const gchar *text = gtk_entry_get_text(entry);
+ BalsaMessage *bm = data;
+ GtkWidget *w = bm->current_part->mime_widget->widget;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer((GtkTextView *) w);
+ GtkTextIter match_begin, match_end;
+ gboolean found;
+
+ if (bm->find_forward) {
+ found = gtk_text_iter_forward_search(&bm->find_iter, text, 0,
+ &match_begin, &match_end,
+ NULL);
+ if (!found) {
+ /* Silently wrap to the top. */
+ gtk_text_buffer_get_start_iter(buffer, &bm->find_iter);
+ found = gtk_text_iter_forward_search(&bm->find_iter, text, 0,
+ &match_begin, &match_end,
+ NULL);
+ gdk_threads_enter(); /* Just a guess! */
+ }
+ } else {
+ found = gtk_text_iter_backward_search(&bm->find_iter, text, 0,
+ &match_begin, &match_end,
+ NULL);
+ if (!found) {
+ /* Silently wrap to the bottom. */
+ gtk_text_buffer_get_end_iter(buffer, &bm->find_iter);
+ found = gtk_text_iter_backward_search(&bm->find_iter, text, 0,
+ &match_begin, &match_end,
+ NULL);
+ gdk_threads_enter(); /* Just a guess! */
+ }
+ }
+
+ if (found) {
+ gtk_widget_hide(bm->find_sep);
+ gtk_widget_hide(bm->find_label);
+ gtk_widget_set_sensitive(bm->find_prev, TRUE);
+ gtk_widget_set_sensitive(bm->find_next, TRUE);
+ gtk_text_buffer_select_range(buffer, &match_begin, &match_end);
+ bm_scroll_to_iter(bm, (GtkTextView *) w, &match_begin);
+ bm->find_iter = match_begin;
+ } else {
+ gtk_label_set_text(GTK_LABEL(bm->find_label), _("Not found"));
+ gtk_widget_show(bm->find_sep);
+ gtk_widget_show(bm->find_label);
+ gtk_widget_set_sensitive(bm->find_prev, FALSE);
+ gtk_widget_set_sensitive(bm->find_next, FALSE);
+ }
+}
+
+static void
+bm_find_again(BalsaMessage * bm, gboolean find_forward)
+{
+ const gchar *text = gtk_entry_get_text(GTK_ENTRY(bm->find_entry));
+ GtkTextIter match_begin, match_end;
+ GtkWidget *w = bm->current_part->mime_widget->widget;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer((GtkTextView *) w);
+ gboolean found;
+
+ if (find_forward) {
+ gtk_text_iter_forward_char(&bm->find_iter);
+ found = gtk_text_iter_forward_search(&bm->find_iter, text, 0,
+ &match_begin, &match_end,
+ NULL);
+ } else {
+ gtk_text_iter_backward_char(&bm->find_iter);
+ found = gtk_text_iter_backward_search(&bm->find_iter, text, 0,
+ &match_begin, &match_end,
+ NULL);
+ }
+
+ if (found) {
+ gtk_widget_hide(bm->find_sep);
+ gtk_widget_hide(bm->find_label);
+ } else {
+ if (find_forward) {
+ gtk_text_buffer_get_start_iter(buffer, &bm->find_iter);
+ gtk_text_iter_forward_search(&bm->find_iter, text, 0,
+ &match_begin, &match_end, NULL);
+ } else {
+ gtk_text_buffer_get_end_iter(buffer, &bm->find_iter);
+ gtk_text_iter_backward_search(&bm->find_iter, text, 0,
+ &match_begin, &match_end, NULL);
+ }
+ gtk_label_set_text(GTK_LABEL(bm->find_label),
+ _("Wrapped"));
+ gtk_widget_show(bm->find_sep);
+ gtk_widget_show(bm->find_label);
+ gdk_threads_enter(); /* Just a guess! */
+ }
+
+ gtk_text_buffer_select_range(buffer, &match_begin, &match_end);
+ bm_scroll_to_iter(bm, (GtkTextView *) w, &match_begin);
+ bm->find_iter = match_begin;
+ bm->find_forward = find_forward;
+}
+
+static void
+bm_find_prev_cb(GtkToolButton * prev_button, gpointer data)
+{
+ bm_find_again((BalsaMessage *) data, FALSE);
+}
+
+static void
+bm_find_next_cb(GtkToolButton * prev_button, gpointer data)
+{
+ bm_find_again((BalsaMessage *) data, TRUE);
+}
+
+static GtkWidget *
+bm_find_bar_new(BalsaMessage * bm)
+{
+ GtkWidget *toolbar;
+ GtkWidget *hbox;
+ GtkToolItem *tool_item;
+
+ toolbar = gtk_toolbar_new();
+ gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH_HORIZ);
+
+ hbox = gtk_hbox_new(FALSE, 6);
+ gtk_box_pack_start(GTK_BOX(hbox), gtk_label_new(_("Find:")),
+ FALSE, FALSE, 0);
+ bm->find_entry = gtk_entry_new();
+ g_signal_connect(bm->find_entry, "changed",
+ G_CALLBACK(bm_find_entry_changed_cb), bm);
+ gtk_box_pack_start(GTK_BOX(hbox), bm->find_entry, FALSE, FALSE, 0);
+
+ tool_item = gtk_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(tool_item), hbox);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1);
+
+ tool_item =
+ gtk_tool_button_new(gtk_arrow_new(GTK_ARROW_LEFT, GTK_SHADOW_NONE),
+ _("Previous"));
+ bm->find_prev = GTK_WIDGET(tool_item);
+ gtk_tool_item_set_is_important(tool_item, TRUE);
+ g_signal_connect(tool_item, "clicked", G_CALLBACK(bm_find_prev_cb), bm);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1);
+
+ tool_item =
+ gtk_tool_button_new(gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE),
+ _("Next"));
+ bm->find_next = GTK_WIDGET(tool_item);
+ gtk_tool_item_set_is_important(tool_item, TRUE);
+ g_signal_connect(tool_item, "clicked", G_CALLBACK(bm_find_next_cb), bm);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1);
+
+ bm->find_sep = GTK_WIDGET(gtk_separator_tool_item_new());
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(bm->find_sep), -1);
+
+ bm->find_label = gtk_label_new("");
+ tool_item = gtk_tool_item_new();
+ gtk_container_add(GTK_CONTAINER(tool_item), bm->find_label);
+ gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1);
+
+ gtk_widget_hide(toolbar);
+
+ return toolbar;
+}
+
+static gboolean bm_disable_find_entry(BalsaMessage * bm);
+
+static gboolean
+bm_pass_to_find_entry(BalsaMessage * bm, GdkEventKey * event)
+{
+ gboolean res = TRUE;
+
+ switch (event->keyval) {
+ case GDK_Escape:
+ case GDK_Return:
+ case GDK_KP_Enter:
+ bm_disable_find_entry(bm);
+ return res;
+ case GDK_g:
+ if (event->state == GDK_CONTROL_MASK) {
+ bm_find_again(bm, bm->find_forward);
+ return res;
+ }
+ default:
+ break;
+ }
+
+ res = FALSE;
+ if (GTK_WIDGET_HAS_FOCUS(bm->find_entry))
+ g_signal_emit_by_name(bm->find_entry, "key-press-event", event,
+ &res, NULL);
+
+ return res;
+}
+
+static gboolean
+bm_disable_find_entry(BalsaMessage * bm)
+{
+ g_signal_handlers_disconnect_by_func
+ (gtk_widget_get_toplevel(GTK_WIDGET(bm)),
+ G_CALLBACK(bm_pass_to_find_entry), bm);
+ gtk_widget_hide(bm->find_bar);
+
+ return FALSE;
+}
+
+/*
+ * End of callbacks and helpers for the find bar.
+ */
+
static void
balsa_message_init(BalsaMessage * bm)
{
+ GtkWidget *vbox;
GtkWidget *scroll;
GtkWidget *label;
GtkTreeStore *model;
@@ -379,6 +616,11 @@
gtk_notebook_set_show_border(GTK_NOTEBOOK(bm), FALSE);
+ /* Box to hold the scrolled window and the find bar */
+ vbox = gtk_vbox_new(FALSE, 0);
+ label = gtk_label_new(_("Content"));
+ gtk_notebook_append_page(GTK_NOTEBOOK(bm), vbox, label);
+
/* scrolled window for the contents */
bm->scroll = scroll = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
@@ -386,8 +628,7 @@
GTK_POLICY_AUTOMATIC);
g_signal_connect(scroll, "key_press_event",
G_CALLBACK(balsa_mime_widget_key_press_event), bm);
- label = gtk_label_new(_("Content"));
- gtk_notebook_append_page(GTK_NOTEBOOK(bm), scroll, label);
+ gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0);
bm->cont_viewport = gtk_viewport_new(NULL, NULL);
gtk_container_add(GTK_CONTAINER(scroll), bm->cont_viewport);
gtk_widget_show_all(scroll);
@@ -396,6 +637,10 @@
g_signal_connect(bm->cont_viewport, "size-allocate",
G_CALLBACK(on_content_size_alloc), NULL);
+ /* Find-in-message toolbar */
+ bm->find_bar = bm_find_bar_new(bm);
+ gtk_box_pack_start(GTK_BOX(vbox), bm->find_bar, FALSE, FALSE, 0);
+
/* Widget to hold headers */
bm->bm_widget = balsa_mime_widget_new_message_tl(bm, bm_header_tl_buttons(bm));
@@ -480,6 +725,9 @@
bm->shown_headers = balsa_app.shown_headers;
bm->show_all_headers = FALSE;
bm->close_with_msg = FALSE;
+
+ gtk_widget_show_all(GTK_WIDGET(bm));
+ gtk_widget_hide(bm->find_bar);
}
static void
@@ -778,6 +1026,7 @@
g_return_val_if_fail(bm != NULL, FALSE);
gtk_widget_hide(GTK_WIDGET(bm));
+ bm_disable_find_entry(bm);
select_part(bm, NULL);
if (bm->message != NULL) {
libbalsa_message_body_unref(bm->message);
@@ -2857,3 +3106,35 @@
}
#endif /* HAVE_GPGME */
+
+/*
+ * Public method for find-in-message.
+ */
+
+void
+balsa_message_find_in_message(BalsaMessage * bm)
+{
+ GtkWidget *w;
+
+ if (bm->current_part
+ && (w = bm->current_part->mime_widget->widget)
+ && GTK_IS_TEXT_VIEW(w)) {
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer((GtkTextView *) w);
+
+ bm->find_forward = TRUE;
+ gtk_text_buffer_get_start_iter(buffer, &bm->find_iter);
+ gtk_entry_set_text(GTK_ENTRY(bm->find_entry), "");
+ g_signal_connect_swapped(gtk_widget_get_toplevel(GTK_WIDGET(bm)),
+ "key-press-event",
+ G_CALLBACK(bm_pass_to_find_entry), bm);
+
+ gtk_widget_hide(bm->find_sep);
+ gtk_widget_hide(bm->find_label);
+
+ gtk_widget_set_sensitive(bm->find_prev, FALSE);
+ gtk_widget_set_sensitive(bm->find_next, FALSE);
+
+ gtk_widget_show(bm->find_bar);
+ gtk_widget_grab_focus(bm->find_entry);
+ }
+}
Modified: trunk/src/balsa-message.h
==============================================================================
--- trunk/src/balsa-message.h (original)
+++ trunk/src/balsa-message.h Fri Feb 8 03:57:27 2008
@@ -80,6 +80,16 @@
gboolean close_with_msg;
BalsaMessageFocusState focus_state;
+
+ /* Find-in-message stuff */
+ GtkWidget *find_bar;
+ GtkWidget *find_entry;
+ GtkWidget *find_next;
+ GtkWidget *find_prev;
+ GtkWidget *find_sep;
+ GtkWidget *find_label;
+ GtkTextIter find_iter;
+ gboolean find_forward;
};
struct _BalsaMessageClass {
@@ -125,6 +135,8 @@
guint max_ref);
#endif
+void balsa_message_find_in_message (BalsaMessage * bm);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: trunk/src/main-window.c
==============================================================================
--- trunk/src/main-window.c (original)
+++ trunk/src/main-window.c Fri Feb 8 03:57:27 2008
@@ -194,6 +194,7 @@
#if !defined(ENABLE_TOUCH_UI)
static void bw_message_copy_cb (GtkAction * action, gpointer data);
static void bw_message_select_all_cb (GtkAction * action, gpointer data);
+static void bw_find_in_message_cb (GtkAction * action, gpointer data);
#endif /* ENABLE_TOUCH_UI */
static void bw_mark_all_cb (GtkAction * action, gpointer data);
@@ -521,7 +522,10 @@
{"CopyMessage", GTK_STOCK_COPY, N_("_Copy"), "<control>C",
N_("Copy message"), G_CALLBACK(bw_message_copy_cb)},
{"SelectText", NULL, N_("_Select Text"), NULL,
- N_("Select entire mail"), G_CALLBACK(bw_message_select_all_cb)}
+ N_("Select entire mail"), G_CALLBACK(bw_message_select_all_cb)},
+ {"FindInMessage", NULL, N_("_Find in message"), "slash",
+ N_("Find a string in this message"),
+ G_CALLBACK(bw_find_in_message_cb)}
#endif /* ENABLE_TOUCH_UI */
};
@@ -669,6 +673,7 @@
" <separator/>"
" <menuitem action='Find'/>"
" <menuitem action='FindNext'/>"
+" <menuitem action='FindInMessage'/>"
" <separator/>"
" <menuitem action='Filters'/>"
" <menuitem action='ExportFilters'/>"
@@ -1510,6 +1515,7 @@
window = g_object_new(BALSA_TYPE_WINDOW, NULL);
window->vbox = gtk_vbox_new(FALSE, 0);
+ gtk_widget_show(window->vbox);
gtk_container_add(GTK_CONTAINER(window), window->vbox);
gtk_window_set_title(GTK_WINDOW(window), "Balsa");
@@ -1558,6 +1564,7 @@
G_CALLBACK(bw_window_state_event_cb),
window->statusbar);
gtk_box_pack_start(GTK_BOX(hbox), window->statusbar, TRUE, TRUE, 0);
+ gtk_widget_show_all(hbox);
#if 0
gnome_app_install_appbar_menu_hints(GNOME_APPBAR(balsa_app.appbar),
@@ -1696,7 +1703,7 @@
G_CALLBACK(bw_cancel_new_mail_notification), NULL);
#endif
- gtk_widget_show_all(GTK_WIDGET(window));
+ gtk_widget_show(GTK_WIDGET(window));
return GTK_WIDGET(window);
}
@@ -4168,6 +4175,14 @@
}
static void
+bw_find_in_message_cb(GtkAction * action,gpointer data)
+{
+ BalsaWindow *window = data;
+ if (balsa_app.previewpane)
+ balsa_message_find_in_message(BALSA_MESSAGE(window->preview));
+}
+
+static void
bw_filter_dlg_cb(GtkAction * action, gpointer data)
{
filters_edit_dialog();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]