balsa r7872 - in branches/mailbox-gsequence: . libbalsa src
- From: PeterB svn gnome org
- To: svn-commits-list gnome org
- Subject: balsa r7872 - in branches/mailbox-gsequence: . libbalsa src
- Date: Thu, 28 Feb 2008 02:41:52 +0000 (GMT)
Author: PeterB
Date: Thu Feb 28 02:41:51 2008
New Revision: 7872
URL: http://svn.gnome.org/viewvc/balsa?rev=7872&view=rev
Log:
port changes from trunk
Modified:
branches/mailbox-gsequence/configure.in
branches/mailbox-gsequence/libbalsa/filter-funcs.c
branches/mailbox-gsequence/libbalsa/identity.c
branches/mailbox-gsequence/libbalsa/identity.h
branches/mailbox-gsequence/libbalsa/libbalsa.c
branches/mailbox-gsequence/libbalsa/libbalsa_private.h
branches/mailbox-gsequence/libbalsa/mailbox.c
branches/mailbox-gsequence/libbalsa/mailbox.h
branches/mailbox-gsequence/libbalsa/rfc3156.c
branches/mailbox-gsequence/libbalsa/rfc3156.h
branches/mailbox-gsequence/src/balsa-index.c
branches/mailbox-gsequence/src/balsa-mblist.c
branches/mailbox-gsequence/src/balsa-mblist.h
branches/mailbox-gsequence/src/balsa-message.c
branches/mailbox-gsequence/src/balsa-message.h
branches/mailbox-gsequence/src/filter-edit-callbacks.c
branches/mailbox-gsequence/src/mailbox-conf.c
branches/mailbox-gsequence/src/mailbox-node.c
branches/mailbox-gsequence/src/main-window.c
branches/mailbox-gsequence/src/message-window.c
branches/mailbox-gsequence/src/save-restore.c
branches/mailbox-gsequence/src/save-restore.h
branches/mailbox-gsequence/src/sendmsg-window.c
Modified: branches/mailbox-gsequence/configure.in
==============================================================================
--- branches/mailbox-gsequence/configure.in (original)
+++ branches/mailbox-gsequence/configure.in Thu Feb 28 02:41:51 2008
@@ -766,6 +766,8 @@
if test -d "${srcdir}/.svn" ; then
BALSA_FROM_SVN=yes
BALSA_CFLAGS="$BALSA_CFLAGS -Wall -Werror"
+ BALSA_CFLAGS="$BALSA_CFLAGS -pg"
+ BALSA_LIBS="$BALSA_LIBS -pg"
else
BALSA_FROM_SVN=no
fi
Modified: branches/mailbox-gsequence/libbalsa/filter-funcs.c
==============================================================================
--- branches/mailbox-gsequence/libbalsa/filter-funcs.c (original)
+++ branches/mailbox-gsequence/libbalsa/filter-funcs.c Thu Feb 28 02:41:51 2008
@@ -481,12 +481,20 @@
/* Helper to compare conditions, a bit obscure at first glance
but we have to compare complex structure, so we must check
all fields.
+ NULL conditions are OK, and compare equal only if both are NULL.
*/
gboolean
libbalsa_condition_compare(LibBalsaCondition *c1,LibBalsaCondition *c2)
{
gboolean res = FALSE;
+
+ if (c1 == c2)
+ return TRUE;
+
+ if (c1 == NULL || c2 == NULL)
+ return FALSE;
+
switch (c1->type) {
case CONDITION_STRING:
res = (c2->type == CONDITION_STRING ||
Modified: branches/mailbox-gsequence/libbalsa/identity.c
==============================================================================
--- branches/mailbox-gsequence/libbalsa/identity.c (original)
+++ branches/mailbox-gsequence/libbalsa/identity.c Thu Feb 28 02:41:51 2008
@@ -113,6 +113,7 @@
ident->gpg_sign = FALSE;
ident->gpg_encrypt = FALSE;
ident->always_trust = FALSE;
+ ident->warn_send_plain = TRUE;
ident->crypt_protocol = LIBBALSA_PROTECT_OPENPGP;
#endif
ident->request_mdn = FALSE;
@@ -1037,7 +1038,7 @@
#endif
/* create the "Security" tab */
table =
- append_ident_notebook_page(notebook, 4, _("Security"), footnote);
+ append_ident_notebook_page(notebook, 5, _("Security"), footnote);
row = 0;
ident_dialog_add_checkbutton(table, row++, dialog,
_("sign messages by default"),
@@ -1051,6 +1052,9 @@
ident_dialog_add_checkbutton(table, row++, dialog,
_("always trust GnuPG keys when encrypting"),
"identity-trust-always", TRUE);
+ ident_dialog_add_checkbutton(table, row++, dialog,
+ _("remind me if messages can be encrypted"),
+ "identity-warn-send-plain", TRUE);
#ifndef HAVE_GPGME
gtk_widget_set_sensitive(table, FALSE);
#endif
@@ -1491,6 +1495,7 @@
id->gpg_sign = ident_dialog_get_bool(dlg, "identity-gpgsign");
id->gpg_encrypt = ident_dialog_get_bool(dlg, "identity-gpgencrypt");
id->always_trust = ident_dialog_get_bool(dlg, "identity-trust-always");
+ id->warn_send_plain = ident_dialog_get_bool(dlg, "identity-warn-send-plain");
id->crypt_protocol = GPOINTER_TO_INT(ident_dialog_get_value
(dlg, "identity-crypt-protocol"));
#endif
@@ -1871,6 +1876,8 @@
ident->gpg_encrypt);
display_frame_set_boolean(dialog, "identity-trust-always",
ident->always_trust);
+ display_frame_set_boolean(dialog, "identity-warn-send-plain",
+ ident->warn_send_plain);
display_frame_set_gpg_mode(dialog, "identity-crypt-protocol",
&ident->crypt_protocol);
#endif
@@ -1971,6 +1978,7 @@
ident->gpg_sign = libbalsa_conf_get_bool("GpgSign");
ident->gpg_encrypt = libbalsa_conf_get_bool("GpgEncrypt");
ident->always_trust = libbalsa_conf_get_bool("GpgTrustAlways");
+ ident->warn_send_plain = libbalsa_conf_get_bool("GpgWarnSendPlain=true");
ident->crypt_protocol = libbalsa_conf_get_int("CryptProtocol=16");
#endif
@@ -2016,6 +2024,7 @@
libbalsa_conf_set_bool("GpgSign", ident->gpg_sign);
libbalsa_conf_set_bool("GpgEncrypt", ident->gpg_encrypt);
libbalsa_conf_set_bool("GpgTrustAlways", ident->always_trust);
+ libbalsa_conf_set_bool("GpgWarnSendPlain", ident->warn_send_plain);
libbalsa_conf_set_int("CryptProtocol", ident->crypt_protocol);
#endif
Modified: branches/mailbox-gsequence/libbalsa/identity.h
==============================================================================
--- branches/mailbox-gsequence/libbalsa/identity.h (original)
+++ branches/mailbox-gsequence/libbalsa/identity.h Thu Feb 28 02:41:51 2008
@@ -84,6 +84,7 @@
gboolean gpg_sign;
gboolean gpg_encrypt;
gboolean always_trust;
+ gboolean warn_send_plain;
gint crypt_protocol;
#endif
#if ENABLE_ESMTP
Modified: branches/mailbox-gsequence/libbalsa/libbalsa.c
==============================================================================
--- branches/mailbox-gsequence/libbalsa/libbalsa.c (original)
+++ branches/mailbox-gsequence/libbalsa/libbalsa.c Thu Feb 28 02:41:51 2008
@@ -750,7 +750,7 @@
self = pthread_self();
if (libbalsa_threads_lock == 0 || self != libbalsa_threads_id) {
- g_warning("Not holding gdk lock!!!");
+ g_warning("%s: Not holding gdk lock!!!", __func__);
return;
}
Modified: branches/mailbox-gsequence/libbalsa/libbalsa_private.h
==============================================================================
--- branches/mailbox-gsequence/libbalsa/libbalsa_private.h (original)
+++ branches/mailbox-gsequence/libbalsa/libbalsa_private.h Thu Feb 28 02:41:51 2008
@@ -40,13 +40,6 @@
#ifdef BALSA_USE_THREADS
unsigned idle_pending:1;
#endif /* BALSA_USE_THREADS */
-#define CACHE_UNSEEN_CHILD FALSE
-#if CACHE_UNSEEN_CHILD
- /* Code for managing this cached bit is incomplete; if calculating
- * has-unseen-child status on the fly is a performance hit, we'll
- * have to finish it. */
- unsigned has_unseen_child:1;
-#endif /* CACHE_UNSEEN_CHILD */
} ;
#ifdef BALSA_USE_THREADS
Modified: branches/mailbox-gsequence/libbalsa/mailbox.c
==============================================================================
--- branches/mailbox-gsequence/libbalsa/mailbox.c (original)
+++ branches/mailbox-gsequence/libbalsa/mailbox.c Thu Feb 28 02:41:51 2008
@@ -35,6 +35,7 @@
#include "mailbox-filter.h"
#include "message.h"
#include "misc.h"
+#include "filter-funcs.h"
#include "libbalsa_private.h"
#include <glib/gi18n.h>
@@ -2080,17 +2081,22 @@
LibBalsaCondition *cond,
gboolean update_immediately)
{
- gboolean retval = update_immediately;
+ gboolean retval = FALSE;
libbalsa_lock_mailbox(mailbox);
+ if (!mailbox->view_filter_pending
+ && !libbalsa_condition_compare(mailbox->view_filter, cond))
+ mailbox->view_filter_pending = TRUE;
+
libbalsa_condition_unref(mailbox->view_filter);
mailbox->view_filter = libbalsa_condition_ref(cond);
- if (update_immediately) {
+ if (update_immediately && mailbox->view_filter_pending) {
LIBBALSA_MAILBOX_GET_CLASS(mailbox)->update_view_filter(mailbox,
cond);
retval = lbm_set_threading(mailbox, mailbox->view->threading_type);
+ mailbox->view_filter_pending = FALSE;
}
libbalsa_unlock_mailbox(mailbox);
Modified: branches/mailbox-gsequence/libbalsa/mailbox.h
==============================================================================
--- branches/mailbox-gsequence/libbalsa/mailbox.h (original)
+++ branches/mailbox-gsequence/libbalsa/mailbox.h Thu Feb 28 02:41:51 2008
@@ -224,7 +224,12 @@
LibBalsaCondition *view_filter; /* to choose a subset of messages
* to be displayed, e.g., only
* undeleted. */
- LibBalsaCondition *persistent_view_filter;
+ LibBalsaCondition *persistent_view_filter; /* the part of the view
+ * filter that will persist
+ * to the next time the
+ * mailbox is opened */
+ gboolean view_filter_pending; /* a view filter has been set
+ * but the view has not been updated */
/* info fields */
gboolean has_unread_messages;
Modified: branches/mailbox-gsequence/libbalsa/rfc3156.c
==============================================================================
--- branches/mailbox-gsequence/libbalsa/rfc3156.c (original)
+++ branches/mailbox-gsequence/libbalsa/rfc3156.c Thu Feb 28 02:41:51 2008
@@ -65,6 +65,8 @@
GMimeGpgmeContext * ctx);
static gboolean gpg_updates_trustdb(void);
static gchar *fix_EMail_info(gchar * str);
+static gboolean have_pub_key_for(gpgme_ctx_t gpgme_ctx,
+ InternetAddressList * recipients);
/* ==== public functions =================================================== */
@@ -141,6 +143,43 @@
}
+/* return TRUE if we can encrypt for every recipient in the recipients list
+ * using protocol */
+gboolean
+libbalsa_can_encrypt_for_all(InternetAddressList * recipients,
+ gpgme_protocol_t protocol)
+{
+ gpgme_ctx_t gpgme_ctx;
+ gboolean result;
+
+ /* silent paranoia checks */
+ if (!recipients)
+ return TRUE; /* we can of course encrypt for nobody... */
+#ifndef HAVE_SMIME
+ if (protocol == GPGME_PROTOCOL_OpenPGP)
+ return FALSE;
+#endif
+
+ /* check if gpg is currently available */
+ if (protocol == GPGME_PROTOCOL_OpenPGP && gpg_updates_trustdb())
+ return FALSE;
+
+ /* create the gpgme context and set the protocol */
+ if (gpgme_new(&gpgme_ctx) != GPG_ERR_NO_ERROR)
+ return FALSE;
+ if (gpgme_set_protocol(gpgme_ctx, protocol) != GPG_ERR_NO_ERROR) {
+ gpgme_release(gpgme_ctx);
+ return FALSE;
+ }
+
+ /* loop over all recipients and try to find valid keys */
+ result = have_pub_key_for(gpgme_ctx, recipients);
+ gpgme_release(gpgme_ctx);
+
+ return result;
+}
+
+
/*
* Check if body (and eventually its subparts) are RFC 2633 or RFC 3156 signed
* or encrypted.
@@ -1692,4 +1731,49 @@
return FALSE;
}
+
+/* check if the context contains a public key for the passed recipients */
+#define KEY_IS_OK(k) (!((k)->expired || (k)->revoked || \
+ (k)->disabled || (k)->invalid))
+static gboolean
+have_pub_key_for(gpgme_ctx_t gpgme_ctx, InternetAddressList * recipients)
+{
+ gpgme_key_t key;
+ gboolean result = TRUE;
+ time_t now = time(NULL);
+
+ for (; result && recipients; recipients = recipients->next) {
+ InternetAddress *ia = recipients->address;
+
+ /* check all entries in the list, handle groups recursively */
+ if (ia->type == INTERNET_ADDRESS_GROUP)
+ result = have_pub_key_for(gpgme_ctx, ia->value.members);
+ else if (recipients->address->type == INTERNET_ADDRESS_NAME) {
+ if (gpgme_op_keylist_start(gpgme_ctx, ia->value.addr, FALSE) !=
+ GPG_ERR_NO_ERROR)
+ return FALSE;
+
+ result = FALSE;
+ while (!result &&
+ gpgme_op_keylist_next(gpgme_ctx, &key) == GPG_ERR_NO_ERROR) {
+ /* check if this key and the relevant subkey are usable */
+ if (KEY_IS_OK(key)) {
+ gpgme_subkey_t subkey = key->subkeys;
+
+ while (subkey && !subkey->can_encrypt)
+ subkey = subkey->next;
+
+ if (subkey && KEY_IS_OK(subkey) &&
+ (subkey->expires == 0 || subkey->expires > now))
+ result = TRUE;
+ }
+ gpgme_key_unref(key);
+ }
+ gpgme_op_keylist_end(gpgme_ctx);
+ }
+ }
+
+ return result;
+}
+
#endif /* HAVE_GPGME */
Modified: branches/mailbox-gsequence/libbalsa/rfc3156.h
==============================================================================
--- branches/mailbox-gsequence/libbalsa/rfc3156.h (original)
+++ branches/mailbox-gsequence/libbalsa/rfc3156.h Thu Feb 28 02:41:51 2008
@@ -58,6 +58,8 @@
gboolean libbalsa_check_crypto_engine(gpgme_protocol_t protocol);
gint libbalsa_message_body_protection(LibBalsaMessageBody * body);
+gboolean libbalsa_can_encrypt_for_all(InternetAddressList * recipients,
+ gpgme_protocol_t protocol);
/* routines dealing with RFC 2633 and RFC 3156 stuff */
gboolean libbalsa_sign_mime_object(GMimeObject ** content,
Modified: branches/mailbox-gsequence/src/balsa-index.c
==============================================================================
--- branches/mailbox-gsequence/src/balsa-index.c (original)
+++ branches/mailbox-gsequence/src/balsa-index.c Thu Feb 28 02:41:51 2008
@@ -1856,6 +1856,41 @@
* set sensitivity of menuitems on the popup
* menu, and populate the mru submenu
*/
+
+/* If the menu is popped up in response to a keystroke, center it
+ * below the headers of the tree-view.
+ */
+static void
+bndx_popup_position_func(GtkMenu * menu, gint * x, gint * y,
+ gboolean * push_in, gpointer user_data)
+{
+ GtkWidget *bindex = GTK_WIDGET(user_data);
+ GdkScreen *screen = gtk_widget_get_screen(bindex);
+ GtkRequisition req;
+ gint monitor_num;
+ GdkRectangle monitor;
+
+ g_return_if_fail(GTK_WIDGET_REALIZED(bindex));
+
+ gdk_window_get_origin(gtk_tree_view_get_bin_window
+ (GTK_TREE_VIEW(bindex)), x, y);
+
+ gtk_widget_size_request(GTK_WIDGET(menu), &req);
+
+ *x += (bindex->allocation.width - req.width) / 2;
+
+ monitor_num = gdk_screen_get_monitor_at_point(screen, *x, *y);
+ gtk_menu_set_monitor(menu, monitor_num);
+ gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor);
+
+ *x = CLAMP(*x, monitor.x,
+ monitor.x + MAX(0, monitor.width - req.width));
+ *y = CLAMP(*y, monitor.y,
+ monitor.y + MAX(0, monitor.height - req.height));
+
+ *push_in = FALSE;
+}
+
static void
bndx_do_popup(BalsaIndex * index, GdkEventButton * event)
{
@@ -1866,8 +1901,6 @@
gboolean any;
gboolean any_deleted = FALSE;
gboolean any_not_deleted = FALSE;
- gint event_button;
- guint event_time;
GArray *selected = balsa_index_selected_msgnos_new(index);
guint i;
@@ -1914,15 +1947,13 @@
gtk_widget_show_all(menu);
- if (event) {
- event_button = event->button;
- event_time = event->time;
- } else {
- event_button = 0;
- event_time = gtk_get_current_event_time();
- }
- gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
- event_button, event_time);
+ if (event)
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
+ event->button, event->time);
+ else
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
+ bndx_popup_position_func, index,
+ 0, gtk_get_current_event_time());
}
static GtkWidget *
Modified: branches/mailbox-gsequence/src/balsa-mblist.c
==============================================================================
--- branches/mailbox-gsequence/src/balsa-mblist.c (original)
+++ branches/mailbox-gsequence/src/balsa-mblist.c Thu Feb 28 02:41:51 2008
@@ -956,7 +956,9 @@
if (event->type != GDK_BUTTON_PRESS
/* keyboard navigation */
|| event->button.button != 1
- /* soft select */ ) {
+ /* soft select */
+ || event->button.window != gtk_tree_view_get_bin_window(tree_view)
+ /* click on a different widget */ ) {
gdk_event_free(event);
return;
}
@@ -2342,6 +2344,24 @@
/* Make a new row for mbnode in balsa_app.mblist_tree_store; the row
* will be a child to the row for root, if we find it, and a top-level
* row otherwise. */
+static gboolean
+bmbl_sort_idle(gpointer data)
+{
+ GtkTreeSortable *sortable = data;
+
+ gdk_threads_enter();
+
+ gtk_tree_sortable_set_sort_column_id(sortable,
+ balsa_app.mblist->sort_column_id,
+ GTK_SORT_ASCENDING);
+ balsa_app.mblist->sort_idle_id = 0;
+ g_object_unref(sortable);
+
+ gdk_threads_leave();
+
+ return FALSE;
+}
+
void
balsa_mblist_mailbox_node_append(BalsaMailboxNode * root,
BalsaMailboxNode * mbnode)
@@ -2354,9 +2374,21 @@
gdk_threads_enter();
model = GTK_TREE_MODEL(balsa_app.mblist_tree_store);
+
+ if (!balsa_app.mblist->sort_idle_id) {
+ GtkTreeSortable *sortable = GTK_TREE_SORTABLE(model);
+ gtk_tree_sortable_get_sort_column_id
+ (sortable, &balsa_app.mblist->sort_column_id, NULL);
+ gtk_tree_sortable_set_sort_column_id
+ (sortable, GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
+ GTK_SORT_ASCENDING);
+ balsa_app.mblist->sort_idle_id =
+ g_idle_add(bmbl_sort_idle, g_object_ref(sortable));
+ }
+
if (root && balsa_find_iter_by_data(&parent, root))
parent_iter = &parent;
- gtk_tree_store_append(balsa_app.mblist_tree_store, &iter, parent_iter);
+ gtk_tree_store_prepend(balsa_app.mblist_tree_store, &iter, parent_iter);
bmbl_store_redraw_mbnode(&iter, mbnode);
if (parent_iter) {
Modified: branches/mailbox-gsequence/src/balsa-mblist.h
==============================================================================
--- branches/mailbox-gsequence/src/balsa-mblist.h (original)
+++ branches/mailbox-gsequence/src/balsa-mblist.h Thu Feb 28 02:41:51 2008
@@ -40,6 +40,10 @@
gboolean display_info;
/* signal handler id */
gulong toggled_handler_id;
+
+ /* to set sort order in an idle callback */
+ gint sort_column_id;
+ guint sort_idle_id;
};
struct _BalsaMBListClass {
Modified: branches/mailbox-gsequence/src/balsa-message.c
==============================================================================
--- branches/mailbox-gsequence/src/balsa-message.c (original)
+++ branches/mailbox-gsequence/src/balsa-message.c Thu Feb 28 02:41:51 2008
@@ -54,6 +54,24 @@
# include "gmime-part-rfc2440.h"
#endif
+#if HAVE_GTKSOURCEVIEW
+/* Use GtkSourceIter's case-insensitive search functions. */
+# include <gtksourceview/gtksourceiter.h>
+# define FORWARD_SEARCH(iter, text, match_begin, match_end) \
+ gtk_source_iter_forward_search((iter), (text), \
+ GTK_SOURCE_SEARCH_CASE_INSENSITIVE, (match_begin), (match_end), NULL)
+# define BACKWARD_SEARCH(iter, text, match_begin, match_end) \
+ gtk_source_iter_backward_search((iter), (text), \
+ GTK_SOURCE_SEARCH_CASE_INSENSITIVE, (match_begin), (match_end), NULL)
+#else /* HAVE_GTKSOURCEVIEW */
+# define FORWARD_SEARCH(iter, text, match_begin, match_end) \
+ gtk_text_iter_forward_search((iter), (text), \
+ 0, (match_begin), (match_end), NULL)
+# define BACKWARD_SEARCH(iter, text, match_begin, match_end) \
+ gtk_text_iter_backward_search((iter), (text), \
+ 0, (match_begin), (match_end), NULL)
+#endif /* HAVE_GTKSOURCEVIEW */
+
enum {
SELECT_PART,
LAST_SIGNAL,
@@ -368,9 +386,258 @@
gtk_container_foreach (GTK_CONTAINER(widget), balsa_mime_widget_image_resize_all, NULL);
}
+/*
+ * Callbacks and helpers for the find bar.
+ */
+
+typedef enum {
+ BM_FIND_STATUS_INIT,
+ BM_FIND_STATUS_FOUND,
+ BM_FIND_STATUS_WRAPPED,
+ BM_FIND_STATUS_NOT_FOUND
+} BalsaMessageFindStatus;
+
+static void
+bm_find_set_status(BalsaMessage * bm, BalsaMessageFindStatus status)
+{
+ const gchar *text = "";
+ gboolean sensitive = FALSE;
+
+ switch (status) {
+ default:
+ case BM_FIND_STATUS_INIT:
+ break;
+ case BM_FIND_STATUS_FOUND:
+ sensitive = TRUE;
+ break;
+ case BM_FIND_STATUS_WRAPPED:
+ text = _("Wrapped");
+ sensitive = TRUE;
+ break;
+ case BM_FIND_STATUS_NOT_FOUND:
+ text = _("Not found");
+ break;
+ }
+
+ gtk_label_set_text(GTK_LABEL(bm->find_label), text);
+ gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM
+ (bm->find_sep), text[0] != '\0');
+ gtk_widget_set_sensitive(bm->find_prev, sensitive);
+ gtk_widget_set_sensitive(bm->find_next, sensitive);
+}
+
+static void
+bm_find_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, y + location.height);
+}
+
+static void
+bm_find_entry_changed_cb(GtkEditable * editable, gpointer data)
+{
+ const gchar *text = gtk_entry_get_text(GTK_ENTRY(editable));
+ BalsaMessage *bm = data;
+ GtkTextView *text_view =
+ GTK_TEXT_VIEW(bm->current_part->mime_widget->widget);
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(text_view);
+ GtkTextIter match_begin, match_end;
+ gboolean found;
+
+ if (bm->find_forward) {
+ found = FORWARD_SEARCH(&bm->find_iter, text,
+ &match_begin, &match_end);
+ if (!found) {
+ /* Silently wrap to the top. */
+ gtk_text_buffer_get_start_iter(buffer, &bm->find_iter);
+ found = FORWARD_SEARCH(&bm->find_iter, text,
+ &match_begin, &match_end);
+ }
+ } else {
+ found = BACKWARD_SEARCH(&bm->find_iter, text,
+ &match_begin, &match_end);
+ if (!found) {
+ /* Silently wrap to the bottom. */
+ gtk_text_buffer_get_end_iter(buffer, &bm->find_iter);
+ found = BACKWARD_SEARCH(&bm->find_iter, text,
+ &match_begin, &match_end);
+ }
+ }
+
+ if (found) {
+ gtk_text_buffer_select_range(buffer, &match_begin, &match_end);
+ bm_find_scroll_to_iter(bm, text_view, &match_begin);
+ bm->find_iter = match_begin;
+ }
+ bm_find_set_status(bm, found ?
+ BM_FIND_STATUS_FOUND : BM_FIND_STATUS_NOT_FOUND);
+}
+
+static void
+bm_find_again(BalsaMessage * bm, gboolean find_forward)
+{
+ const gchar *text = gtk_entry_get_text(GTK_ENTRY(bm->find_entry));
+ GtkTextView *text_view =
+ GTK_TEXT_VIEW(bm->current_part->mime_widget->widget);
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(text_view);
+ GtkTextIter match_begin, match_end;
+ gboolean found;
+
+ if (find_forward) {
+ gtk_text_iter_forward_char(&bm->find_iter);
+ found = FORWARD_SEARCH(&bm->find_iter, text,
+ &match_begin, &match_end);
+ if (!found) {
+ gtk_text_buffer_get_start_iter(buffer, &bm->find_iter);
+ found = FORWARD_SEARCH(&bm->find_iter, text,
+ &match_begin, &match_end);
+ }
+ } else {
+ gtk_text_iter_backward_char(&bm->find_iter);
+ found = BACKWARD_SEARCH(&bm->find_iter, text,
+ &match_begin, &match_end);
+ if (!found) {
+ gtk_text_buffer_get_end_iter(buffer, &bm->find_iter);
+ found = BACKWARD_SEARCH(&bm->find_iter, text,
+ &match_begin, &match_end);
+ }
+ }
+ bm_find_set_status(bm, found ?
+ BM_FIND_STATUS_FOUND : BM_FIND_STATUS_WRAPPED);
+
+ gtk_text_buffer_select_range(buffer, &match_begin, &match_end);
+ bm_find_scroll_to_iter(bm, text_view, &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 void bm_disable_find_entry(BalsaMessage * bm);
+
+static gboolean
+bm_find_pass_to_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_SHIFT_MASK | GDK_CONTROL_MASK)) ==
+ GDK_CONTROL_MASK && GTK_WIDGET_SENSITIVE(bm->find_next)) {
+ 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 void
+bm_disable_find_entry(BalsaMessage * bm)
+{
+ g_signal_handlers_disconnect_by_func
+ (gtk_widget_get_toplevel(GTK_WIDGET(bm)),
+ G_CALLBACK(bm_find_pass_to_entry), bm);
+ gtk_widget_hide(bm->find_bar);
+}
+
+/*
+ * 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 +646,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 +658,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 +667,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 +755,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 +1056,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 +3136,32 @@
}
#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)) {
+ GtkTextView *text_view = (GtkTextView *) w;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(text_view);
+
+ 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_find_pass_to_entry), bm);
+
+ bm_find_set_status(bm, BM_FIND_STATUS_INIT);
+
+ gtk_widget_show(bm->find_bar);
+ gtk_widget_grab_focus(bm->find_entry);
+ }
+}
Modified: branches/mailbox-gsequence/src/balsa-message.h
==============================================================================
--- branches/mailbox-gsequence/src/balsa-message.h (original)
+++ branches/mailbox-gsequence/src/balsa-message.h Thu Feb 28 02:41:51 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: branches/mailbox-gsequence/src/filter-edit-callbacks.c
==============================================================================
--- branches/mailbox-gsequence/src/filter-edit-callbacks.c (original)
+++ branches/mailbox-gsequence/src/filter-edit-callbacks.c Thu Feb 28 02:41:51 2008
@@ -48,10 +48,12 @@
extern option_list fe_search_type[4];
extern GList * fe_user_headers_list;
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
static void fe_add_pressed(GtkWidget * widget, gpointer throwaway);
static void fe_remove_pressed(GtkWidget * widget, gpointer throwaway);
static void fe_regexs_selection_changed(GtkTreeSelection * selection,
gpointer user_data);
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
static void fe_free_associated_filters(void);
static void fe_free_associated_conditions(void);
static GtkWidget *fe_date_sample(void);
@@ -242,6 +244,7 @@
/**************** Conditions *************************/
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
/* Callback function to fill the regex entry with the selected regex */
static void
@@ -262,6 +265,7 @@
else gtk_entry_set_text(GTK_ENTRY(fe_type_regex_entry),"");
gtk_widget_set_sensitive(fe_regex_remove_button, selected);
}
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
/* Helper. */
static gint
@@ -293,11 +297,16 @@
switch (type) {
case CONDITION_STRING:
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
case CONDITION_REGEX:
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
gtk_widget_show(field_frame);
break;
case CONDITION_DATE:
case CONDITION_FLAG:
+#if !REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
+ case CONDITION_REGEX:
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
gtk_widget_hide(field_frame);
default:
break;
@@ -480,9 +489,11 @@
const gchar *c_str;
gint row, col;
struct tm date;
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
GtkTreeModel *model =
gtk_tree_view_get_model(fe_type_regex_list);
GtkTreeIter iter;
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
/* Sanity checks, prevent "empty" condition */
@@ -535,12 +546,14 @@
}
break;
case CONDITION_REGEX:
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
if (!gtk_tree_model_get_iter_first(model, &iter)) {
balsa_information(LIBBALSA_INFORMATION_ERROR,
_("You must provide at least one "
"regular expression"));
return FALSE;
}
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
break;
case CONDITION_DATE:
c_str = gtk_entry_get_text(GTK_ENTRY(fe_type_date_low_entry));
@@ -629,12 +642,16 @@
static void
clear_condition_widgets()
{
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
GtkTreeModel *model =
gtk_tree_view_get_model(fe_type_regex_list);
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
gtk_entry_set_text(GTK_ENTRY(fe_type_simple_entry),"");
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
gtk_entry_set_text(GTK_ENTRY(fe_type_regex_entry),"");
gtk_list_store_clear(GTK_LIST_STORE(model));
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
gtk_entry_set_text(GTK_ENTRY(fe_type_date_low_entry),"");
gtk_entry_set_text(GTK_ENTRY(fe_type_date_high_entry),"");
}
@@ -682,8 +699,10 @@
static void
fill_condition_widgets(LibBalsaCondition* cnd)
{
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
GtkTreeModel *model =
gtk_tree_view_get_model(fe_type_regex_list);
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
gchar str[20];
struct tm date;
gint row,col;
@@ -698,7 +717,9 @@
if (cnd->type!=CONDITION_REGEX)
gtk_entry_set_text(GTK_ENTRY(fe_type_regex_entry),"");
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
gtk_list_store_clear(GTK_LIST_STORE(model));
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
gtk_notebook_set_current_page(GTK_NOTEBOOK(fe_type_notebook),
cnd->type - 1);
@@ -938,7 +959,11 @@
build_type_notebook()
{
GtkWidget *page,*frame;
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
GtkWidget *scroll;
+#else /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
+ const gchar *msg;
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
GtkWidget *box;
GtkWidget *button, *table;
gint row,col;
@@ -986,11 +1011,12 @@
/* The regex page of the type notebook */
box = gtk_vbox_new(FALSE, 5);
+ gtk_notebook_append_page(GTK_NOTEBOOK(fe_type_notebook), box, NULL);
+
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
page = gtk_table_new(5, 6, FALSE);
gtk_box_pack_start_defaults(GTK_BOX(box), page);
- gtk_notebook_append_page(GTK_NOTEBOOK(fe_type_notebook), box, NULL);
-
fe_type_regex_label =
gtk_label_new_with_mnemonic(_("_One of the regular expressions matches"));
gtk_table_attach(GTK_TABLE(page),
@@ -1037,6 +1063,10 @@
fe_type_regex_entry,
0, 5, 5, 6,
GTK_FILL | GTK_SHRINK | GTK_EXPAND, GTK_SHRINK, 2, 2);
+#else /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
+ msg = _("Filtering using regular expressions is not yet implemented.");
+ gtk_box_pack_start_defaults(GTK_BOX(box), gtk_label_new(msg));
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
/* The date page of the notebook */
@@ -1506,6 +1536,7 @@
set_button_sensitivities(TRUE);
}
+#if REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED
/*
* fe_add_pressed()
*
@@ -1559,6 +1590,7 @@
gtk_tree_path_free(path);
condition_has_changed=TRUE;
} /* end fe_remove_pressed() */
+#endif /* REGULAR_EXPRESSION_FILTERING_IS_IMPLEMENTED */
/************************************************************/
/******** Functions handling filters ************************/
Modified: branches/mailbox-gsequence/src/mailbox-conf.c
==============================================================================
--- branches/mailbox-gsequence/src/mailbox-conf.c (original)
+++ branches/mailbox-gsequence/src/mailbox-conf.c Thu Feb 28 02:41:51 2008
@@ -53,6 +53,8 @@
#include "libbalsa.h"
#include "imap-server.h"
+#include "mailbox-filter.h"
+#include "libbalsa-conf.h"
#include <glib/gi18n.h>
struct _BalsaMailboxConfView {
@@ -371,6 +373,7 @@
gint button;
GtkWidget *ask;
LibBalsaMailbox* mailbox = mbnode->mailbox;
+ gchar *url, *group;
if(BALSA_IS_MAILBOX_SPECIAL(mailbox)) {
balsa_information(
@@ -449,6 +452,9 @@
if ( button < 0)
return;
+ /* Save the mailbox URL */
+ url = g_strdup(mailbox->url ? mailbox->url : mailbox->name);
+
/* Delete it from the config file and internal nodes */
config_mailbox_delete(mailbox);
@@ -492,6 +498,18 @@
} else
balsa_mblist_mailbox_node_remove(mbnode);
update_mail_servers();
+
+ /* Clean up filters */
+ group = mailbox_filters_section_lookup(url);
+ if (group) {
+ libbalsa_conf_remove_group(group);
+ g_free(group);
+ }
+
+ /* Remove view */
+ config_view_remove(url);
+
+ g_free(url);
}
#define MCW_RESPONSE 1
Modified: branches/mailbox-gsequence/src/mailbox-node.c
==============================================================================
--- branches/mailbox-gsequence/src/mailbox-node.c (original)
+++ branches/mailbox-gsequence/src/mailbox-node.c Thu Feb 28 02:41:51 2008
@@ -1215,7 +1215,9 @@
g_print(_("Local mailbox %s loaded as: %s\n"),
mailbox->name,
g_type_name(G_OBJECT_TYPE(mailbox)));
- if (balsa_app.check_mail_upon_startup) {
+ if (balsa_app.check_mail_upon_startup
+ && libbalsa_mailbox_get_subscribe(mailbox) !=
+ LB_MAILBOX_SUBSCRIBE_NO) {
g_object_ref(mailbox);
g_idle_add((GSourceFunc) mailbox_check_idle, mailbox);
}
Modified: branches/mailbox-gsequence/src/main-window.c
==============================================================================
--- branches/mailbox-gsequence/src/main-window.c (original)
+++ branches/mailbox-gsequence/src/main-window.c Thu Feb 28 02:41:51 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'/>"
@@ -1511,6 +1516,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");
@@ -1559,6 +1565,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();
Modified: branches/mailbox-gsequence/src/message-window.c
==============================================================================
--- branches/mailbox-gsequence/src/message-window.c (original)
+++ branches/mailbox-gsequence/src/message-window.c Thu Feb 28 02:41:51 2008
@@ -58,6 +58,7 @@
static void copy_cb (GtkAction * action, MessageWindow * mw);
static void select_all_cb (GtkAction * action, gpointer);
+static void mw_find_in_message_cb (GtkAction * action, gpointer data);
static void mw_header_activate_cb (GtkAction * action, gpointer data);
@@ -251,6 +252,9 @@
G_CALLBACK(copy_cb)},
{"SelectAll", NULL, N_("Select _All"), "<control>A", NULL,
G_CALLBACK(select_all_cb)},
+ {"FindInMessage", NULL, N_("_Find in message"), "slash",
+ N_("Find a string in this message"),
+ G_CALLBACK(mw_find_in_message_cb)},
#ifdef HAVE_GTKHTML
{"ZoomIn", GTK_STOCK_ZOOM_IN, N_("Zoom _In"), "<control>plus",
N_("Increase magnification"), G_CALLBACK(mw_zoom_in_cb)},
@@ -339,6 +343,8 @@
" <menu action='EditMenu'>"
" <menuitem action='Copy'/>"
" <menuitem action='SelectAll'/>"
+" <separator/>"
+" <menuitem action='FindInMessage'/>"
" </menu>"
" <menu action='ViewMenu'>"
" <menuitem action='Wrap'/>"
@@ -883,6 +889,14 @@
}
static void
+mw_find_in_message_cb(GtkAction * action, gpointer data)
+{
+ MessageWindow *mw = (MessageWindow *) (data);
+
+ balsa_message_find_in_message(BALSA_MESSAGE(mw->bmessage));
+}
+
+static void
mw_set_selected(MessageWindow * mw, void (*select_func) (BalsaIndex *))
{
guint msgno;
Modified: branches/mailbox-gsequence/src/save-restore.c
==============================================================================
--- branches/mailbox-gsequence/src/save-restore.c (original)
+++ branches/mailbox-gsequence/src/save-restore.c Thu Feb 28 02:41:51 2008
@@ -1830,22 +1830,33 @@
GINT_TO_POINTER(FALSE));
}
+/* Get viewByUrl prefix */
+static gchar *
+view_by_url_prefix(const gchar * url)
+{
+ gchar *url_enc;
+ gchar *prefix;
+
+ url_enc = libbalsa_urlencode(url);
+ prefix = g_strconcat(VIEW_BY_URL_SECTION_PREFIX, url_enc, NULL);
+ g_free(url_enc);
+
+ return prefix;
+}
+
/* config_views_save:
iterates over all mailbox views.
*/
static void
save_view(const gchar * url, LibBalsaMailboxView * view)
{
- gchar *url_enc;
gchar *prefix;
if (!view || (view->in_sync && view->used))
return;
view->in_sync = TRUE;
- url_enc = libbalsa_urlencode(url);
- prefix = g_strconcat(VIEW_BY_URL_SECTION_PREFIX, url_enc, NULL);
- g_free(url_enc);
+ prefix = view_by_url_prefix(url);
/* Remove the view--it will be recreated if any member needs to be
* saved. */
@@ -1911,6 +1922,15 @@
NULL);
}
+void
+config_view_remove(const gchar * url)
+{
+ gchar *prefix = view_by_url_prefix(url);
+ libbalsa_conf_remove_group(prefix);
+ g_free(prefix);
+ g_hash_table_remove(libbalsa_mailbox_view_table, url);
+}
+
static void
save_color(gchar * key, GdkColor * color)
{
Modified: branches/mailbox-gsequence/src/save-restore.h
==============================================================================
--- branches/mailbox-gsequence/src/save-restore.h (original)
+++ branches/mailbox-gsequence/src/save-restore.h Thu Feb 28 02:41:51 2008
@@ -57,6 +57,7 @@
void config_identities_save(void);
void config_views_load(void);
void config_views_save(void);
+void config_view_remove(const gchar * url);
void config_filters_save(void);
void config_mailbox_filters_save(LibBalsaMailbox * mbox);
Modified: branches/mailbox-gsequence/src/sendmsg-window.c
==============================================================================
--- branches/mailbox-gsequence/src/sendmsg-window.c (original)
+++ branches/mailbox-gsequence/src/sendmsg-window.c Thu Feb 28 02:41:51 2008
@@ -1433,6 +1433,9 @@
ident->replyto);
gtk_widget_show(bsmsg->replyto[0]);
gtk_widget_show(bsmsg->replyto[1]);
+ } else if (!sw_get_active(bsmsg, "ReplyTo")) {
+ gtk_widget_hide(bsmsg->replyto[0]);
+ gtk_widget_hide(bsmsg->replyto[1]);
}
#endif
@@ -5676,6 +5679,116 @@
return response == GTK_RESPONSE_OK;
}
+#ifdef HAVE_GPGME
+static gboolean
+check_suggest_encryption(BalsaSendmsg * bsmsg)
+{
+ InternetAddressList * ia_list;
+ gboolean can_encrypt;
+ InternetAddressList * from_list;
+ InternetAddressList * cc_list;
+ gpgme_protocol_t protocol;
+
+ /* check if the user wants to see the message */
+ if (!bsmsg->ident->warn_send_plain)
+ return TRUE;
+
+ /* nothing to do if encryption is already enabled */
+ if ((bsmsg->gpg_mode & LIBBALSA_PROTECT_ENCRYPT) != 0)
+ return TRUE;
+
+ /* we can not encrypt if we have bcc recipients */
+ if ((ia_list = libbalsa_address_view_get_list(bsmsg->recipient_view, "Bcc:"))) {
+ internet_address_list_destroy(ia_list);
+ return TRUE;
+ }
+
+ /* collect all to and cc recipients */
+ ia_list = libbalsa_address_view_get_list(bsmsg->recipient_view, "To:");
+ cc_list = libbalsa_address_view_get_list(bsmsg->recipient_view, "Cc:");
+ from_list = internet_address_list_prepend(NULL, bsmsg->ident->ia);
+ protocol = bsmsg->gpg_mode & LIBBALSA_PROTECT_SMIMEV3 ?
+ GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP;
+ can_encrypt = libbalsa_can_encrypt_for_all(from_list, protocol) &
+ libbalsa_can_encrypt_for_all(ia_list, protocol) &
+ libbalsa_can_encrypt_for_all(cc_list, protocol);
+ internet_address_list_destroy(from_list);
+ internet_address_list_destroy(ia_list);
+ internet_address_list_destroy(cc_list);
+
+ /* ask the user if we could encrypt this message */
+ if (can_encrypt) {
+ GtkWidget *dialog;
+ gint choice;
+ gchar * message;
+ GtkWidget *dialog_action_area;
+ GtkWidget *button;
+ GtkWidget *alignment;
+ GtkWidget *hbox;
+ GtkWidget *image;
+ GtkWidget *label;
+
+ message =
+ g_strdup_printf(_("You did not select encryption for this message, although "
+ "%s public keys are available for all recipients. In order "
+ "to protect your privacy, the message could be %s encrypted."),
+ gpgme_get_protocol_name(protocol),
+ gpgme_get_protocol_name(protocol));
+ dialog = gtk_message_dialog_new
+ (GTK_WINDOW(bsmsg->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ message);
+
+ dialog_action_area = GTK_DIALOG(dialog)->action_area;
+ gtk_button_box_set_layout(GTK_BUTTON_BOX(dialog_action_area), GTK_BUTTONBOX_END);
+
+ button = gtk_button_new();
+ gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button, GTK_RESPONSE_YES);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ gtk_widget_grab_focus(button);
+ alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
+ gtk_container_add(GTK_CONTAINER(button), alignment);
+
+ hbox = gtk_hbox_new(FALSE, 2);
+ gtk_container_add(GTK_CONTAINER(alignment), hbox);
+ image = gtk_image_new_from_stock(BALSA_PIXMAP_GPG_ENCRYPT, GTK_ICON_SIZE_BUTTON);
+ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+ label = gtk_label_new_with_mnemonic(_("Send _encrypted"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show_all(button);
+
+ button = gtk_button_new();
+ gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button, GTK_RESPONSE_NO);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+ alignment = gtk_alignment_new (0.5, 0.5, 0, 0);
+ gtk_container_add(GTK_CONTAINER(button), alignment);
+
+ hbox = gtk_hbox_new(FALSE, 2);
+ gtk_container_add(GTK_CONTAINER(alignment), hbox);
+ image = gtk_image_new_from_stock(BALSA_PIXMAP_SEND, GTK_ICON_SIZE_BUTTON);
+ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0);
+ label = gtk_label_new_with_mnemonic(_("Send _plain"));
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_widget_show_all(button);
+
+ button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
+ gtk_widget_show(button);
+ gtk_dialog_add_action_widget(GTK_DIALOG(dialog), button, GTK_RESPONSE_CANCEL);
+ GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+
+ choice = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+ if (choice == GTK_RESPONSE_YES)
+ bsmsg_setup_gpg_ui_by_mode(bsmsg, bsmsg->gpg_mode | LIBBALSA_PROTECT_ENCRYPT);
+ else if (choice == GTK_RESPONSE_CANCEL || choice == GTK_RESPONSE_DELETE_EVENT)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+#endif
/* "send message" menu and toolbar callback.
*/
@@ -5697,6 +5810,9 @@
return FALSE;
#ifdef HAVE_GPGME
+ if (!check_suggest_encryption(bsmsg))
+ return FALSE;
+
if ((bsmsg->gpg_mode & LIBBALSA_PROTECT_OPENPGP) != 0 &&
(bsmsg->gpg_mode & LIBBALSA_PROTECT_MODE) != 0 &&
gtk_tree_model_get_iter_first(BALSA_MSG_ATTACH_MODEL(bsmsg), &iter)) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]