[balsa] Move recheck crypto button to menu, toolbar



commit 07c43b9ef18594577265d4f8d6f026be28b5ca26
Author: Albrecht Dreß <albrecht dress arcor de>
Date:   Tue Mar 3 14:30:41 2020 -0500

    Move recheck crypto button to menu, toolbar
    
    * libbalsa/body.[ch]:
      • add new function libbalsa_message_body_has_crypto_content()
        which recursively checks if a LibBalsaMessageBody contains any
        not yet decrypted or any signed content which may be rechecked
      • fix comment typo
    * libbalsa/gmime-part-rfc2440.c: g_mime_part_check_rfc2440()
        make sure to lock/unlock a shared stream
    * libbalsa/message.[ch]:
      • rename libbalsa_message_is_pgp_(signed|encrypted)()
        to libbalsa_message_is_(signed|encrypted)(), do not export them,
        and detect S/MIME (RFC 8551) content
      • add and export libbalsa_message_has_crypto_content() to check
        if a message contains any not yet decrypted or any signed content
        which may be rechecked
    * src/balsa-message.[ch]:
      • remove recheck crypto button from bm_header_tl_buttons()
      • rename message_recheck_crypto_cb() to balsa_message_recheck_crypto()
        and export it
      • remove ancient code relevant for Gtk+-3.0 < 3.15.0 only
    * src/main-window.c, src/message-window.c:
      • add “recheck crypto” button to extra toolbar items
      • add recheck crypto callback, and connect it to the menu item
      • appropriately disable/enable menu item and button
    * src/toolbar-factory.c: register “Recheck cryptography” button
    * ui/main-window.ui, ui/message-window.ui: add menu item to the ui

 ChangeLog                     | 30 +++++++++++++++++++++++
 libbalsa/body.c               | 47 +++++++++++++++++++++++++++++++++++-
 libbalsa/body.h               |  1 +
 libbalsa/gmime-part-rfc2440.c |  6 +++++
 libbalsa/message.c            | 55 +++++++++++++++++++++++++++++++++----------
 libbalsa/message.h            |  3 +--
 src/balsa-message.c           | 44 +++++-----------------------------
 src/balsa-message.h           |  1 +
 src/main-window.c             | 17 +++++++++++++
 src/message-window.c          | 20 ++++++++++++++--
 src/toolbar-factory.c         |  1 +
 ui/main-window.ui             |  6 +++++
 ui/message-window.ui          |  6 +++++
 13 files changed, 182 insertions(+), 55 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8247c534b..2d9ae5db4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2020-03-03  Albrecht Dreß  <albrecht dress arcor de>
+
+       Move recheck crypto button to menu, toolbar
+
+       * libbalsa/body.[ch]:
+         • add new function libbalsa_message_body_has_crypto_content()
+           which recursively checks if a LibBalsaMessageBody contains any
+           not yet decrypted or any signed content which may be rechecked
+         • fix comment typo
+       * libbalsa/gmime-part-rfc2440.c: g_mime_part_check_rfc2440()
+           make sure to lock/unlock a shared stream
+       * libbalsa/message.[ch]:
+         • rename libbalsa_message_is_pgp_(signed|encrypted)()
+           to libbalsa_message_is_(signed|encrypted)(), do not export them,
+           and detect S/MIME (RFC 8551) content
+         • add and export libbalsa_message_has_crypto_content() to check
+           if a message contains any not yet decrypted or any signed content
+           which may be rechecked
+       * src/balsa-message.[ch]:
+         • remove recheck crypto button from bm_header_tl_buttons()
+         • rename message_recheck_crypto_cb() to balsa_message_recheck_crypto()
+           and export it
+         • remove ancient code relevant for Gtk+-3.0 < 3.15.0 only
+       * src/main-window.c, src/message-window.c:
+         • add “recheck crypto” button to extra toolbar items
+         • add recheck crypto callback, and connect it to the menu item
+         • appropriately disable/enable menu item and button
+       * src/toolbar-factory.c: register “Recheck cryptography” button
+       * ui/main-window.ui, ui/message-window.ui: add menu item to the ui
+
 2020-02-26  Peter Bloomfield  <pbloomfield bellsouth net>
 
        mailbox-local: Do not pass message to LibBalsaMailbox
diff --git a/libbalsa/body.c b/libbalsa/body.c
index 1718786bb..1ff135c7e 100644
--- a/libbalsa/body.c
+++ b/libbalsa/body.c
@@ -33,6 +33,7 @@
 #include "libbalsa-vfs.h"
 #include "misc.h"
 #include <glib/gi18n.h>
+#include "gmime-part-rfc2440.h"
 #include "libbalsa-gpgme.h"
 
 LibBalsaMessageBody *
@@ -972,7 +973,7 @@ libbalsa_message_body_multipart_signed(const LibBalsaMessageBody *body)
 /** \brief Check if a body is signed inline with a valid signature
  *
  * \param body message body (part)
- * \return TRUE if the body is an inlined singed part, fFALSE if not
+ * \return TRUE if the body is an inlined singed part, FALSE if not
  *
  * The body is a valid inlined signed part if has a \ref GMimeGpgmeSigstat which is not \ref 
GPG_ERR_NOT_SIGNED.  This applies to
  * - RFC 4880 message parts,
@@ -986,3 +987,47 @@ libbalsa_message_body_inline_signed(const LibBalsaMessageBody *body)
                        (body->sig_info != NULL) &&
                        (g_mime_gpgme_sigstat_status(body->sig_info) != GPG_ERR_NOT_SIGNED);
 }
+
+
+/** \brief Check if a body contains any crypto content
+ *
+ * \param body message body
+ * \return TRUE if any crypto content has been found
+ *
+ * Return if the passed body chain or any of its children contains any crypto content which may be either 
decrypted or rechecked.
+ * This includes PGP/MIME (RFC 3156) and S/MIME (RFC 8551) parts as well as RFC 4880 signed or encrypted 
text/... bodies.
+ */
+gboolean
+libbalsa_message_body_has_crypto_content(const LibBalsaMessageBody *body)
+{
+       gboolean result;
+
+       /* check if we have a signature info */
+       result = (body->sig_info != NULL);
+
+       /* check for signed or encrypted content-type */
+       if (!result && (body->content_type != NULL)) {
+               if ((g_ascii_strcasecmp(body->content_type, "multipart/signed") == 0) ||
+                       (g_ascii_strcasecmp(body->content_type, "multipart/encrypted") == 0) ||
+                       (g_ascii_strcasecmp(body->content_type, "application/pkcs7-mime") == 0) ||
+                       (g_ascii_strcasecmp(body->content_type, "application/x-pkcs7-mime") == 0)) {
+                       result = TRUE;
+               }
+       }
+
+       /* check if a text/... body is RFC 4880 signed or encrypted */
+       if (!result && (body->body_type == LIBBALSA_MESSAGE_BODY_TYPE_TEXT) && 
(GMIME_IS_PART(body->mime_part)) &&
+               (g_mime_part_check_rfc2440(GMIME_PART(body->mime_part)) != GMIME_PART_RFC2440_NONE)) {
+               result = TRUE;
+       }
+
+       /* check children and parts */
+       if (!result && (body->parts != NULL)) {
+               result = libbalsa_message_body_has_crypto_content(body->parts);
+       }
+       if (!result && (body->next != NULL)) {
+               result = libbalsa_message_body_has_crypto_content(body->next);
+       }
+
+       return result;
+}
diff --git a/libbalsa/body.h b/libbalsa/body.h
index 5d4907192..08098aa28 100644
--- a/libbalsa/body.h
+++ b/libbalsa/body.h
@@ -135,6 +135,7 @@ LibBalsaMessageBody *libbalsa_message_body_mp_related_root(LibBalsaMessageBody *
 LibBalsaMsgProtectState libbalsa_message_body_protect_state(const LibBalsaMessageBody *body);
 gboolean libbalsa_message_body_multipart_signed(const LibBalsaMessageBody *body);
 gboolean libbalsa_message_body_inline_signed(const LibBalsaMessageBody *body);
+gboolean libbalsa_message_body_has_crypto_content(const LibBalsaMessageBody *body);
 
 
 #endif                         /* __LIBBALSA_BODY_H__ */
diff --git a/libbalsa/gmime-part-rfc2440.c b/libbalsa/gmime-part-rfc2440.c
index 97183a650..9d4fde992 100644
--- a/libbalsa/gmime-part-rfc2440.c
+++ b/libbalsa/gmime-part-rfc2440.c
@@ -26,6 +26,7 @@
 #include <gtk/gtk.h>
 #include <gmime/gmime.h>
 #include "libbalsa-gpgme.h"
+#include "mime-stream-shared.h"
 #include "gmime-part-rfc2440.h"
 
 
@@ -70,6 +71,9 @@ g_mime_part_check_rfc2440(GMimePart * part)
     if (!stream || (slen = g_mime_stream_length(stream)) < 0)
        return retval;
 
+    /* note: the following is a noop if the stream is not a shared stream */
+    libbalsa_mime_stream_shared_lock(stream);
+
     g_mime_stream_reset(stream);
 
     /* check if the complete stream fits in the buffer */
@@ -110,6 +114,8 @@ g_mime_part_check_rfc2440(GMimePart * part)
        }
     }
 
+    libbalsa_mime_stream_shared_unlock(stream);
+
     return retval;
 }
 
diff --git a/libbalsa/message.c b/libbalsa/message.c
index fcac44517..3371da668 100644
--- a/libbalsa/message.c
+++ b/libbalsa/message.c
@@ -52,6 +52,8 @@
 
 static void libbalsa_message_dispose(GObject * object);
 static void libbalsa_message_finalize(GObject * object);
+static gboolean libbalsa_message_is_signed(LibBalsaMessage * message);
+static gboolean libbalsa_message_is_encrypted(LibBalsaMessage * message);
 
 struct _LibBalsaMessage {
     GObject object;
@@ -632,10 +634,10 @@ libbalsa_message_get_attach_icon(LibBalsaMessage * message)
 {
     LibBalsaMessageAttach attach_icon;
 
-    if (libbalsa_message_is_pgp_encrypted(message)) {
+    if (libbalsa_message_is_encrypted(message)) {
        attach_icon = LIBBALSA_MESSAGE_ATTACH_ENCR;
     } else if (message->prot_state != LIBBALSA_MSG_PROTECT_NONE ||
-       libbalsa_message_is_pgp_signed(message)) {
+       libbalsa_message_is_signed(message)) {
        switch (message->prot_state) {
        case LIBBALSA_MSG_PROTECT_SIGN_GOOD:
            attach_icon = LIBBALSA_MESSAGE_ATTACH_GOOD;
@@ -843,24 +845,44 @@ libbalsa_message_has_attachment(LibBalsaMessage *message)
     }
  }
 
-gboolean
-libbalsa_message_is_pgp_signed(LibBalsaMessage * message)
+static gboolean
+libbalsa_message_is_signed(LibBalsaMessage * message)
 {
+       gboolean is_signed = FALSE;
+
     g_return_val_if_fail(LIBBALSA_IS_MESSAGE(message), FALSE);
 
-    return message->headers->content_type ?
-       g_mime_content_type_is_type(message->headers->content_type,
-                                   "multipart", "signed") : FALSE;
+    if (message->headers->content_type != NULL) {
+       GMimeContentType *ct = message->headers->content_type; /* convenience pointer */
+
+       if (g_mime_content_type_is_type(ct, "multipart", "signed") ||
+               ((g_mime_content_type_is_type(ct, "application", "pkcs7-mime") ||
+                 g_mime_content_type_is_type(ct, "application", "x-pkcs7-mime")) &&
+                g_ascii_strcasecmp(g_mime_content_type_get_parameter(ct,"smime-type" ), "signed-data") == 
0)) {
+               is_signed = TRUE;
+       }
+    }
+    return is_signed;
 }
 
-gboolean
-libbalsa_message_is_pgp_encrypted(LibBalsaMessage * message)
+static gboolean
+libbalsa_message_is_encrypted(LibBalsaMessage * message)
 {
+       gboolean encrypted = FALSE;
+
     g_return_val_if_fail(LIBBALSA_IS_MESSAGE(message), FALSE);
 
-    return message->headers->content_type ?
-       g_mime_content_type_is_type(message->headers->content_type,
-                                   "multipart", "encrypted") : FALSE;
+    if (message->headers->content_type != NULL) {
+       GMimeContentType *ct = message->headers->content_type; /* convenience pointer */
+
+       if (g_mime_content_type_is_type(ct, "multipart", "encrypted") ||
+               ((g_mime_content_type_is_type(ct, "application", "pkcs7-mime") ||
+                 g_mime_content_type_is_type(ct, "application", "x-pkcs7-mime")) &&
+                g_ascii_strcasecmp(g_mime_content_type_get_parameter(ct,"smime-type" ), "enveloped-data") == 
0)) {
+               encrypted = TRUE;
+       }
+    }
+    return encrypted;
 }
 
 void
@@ -1667,6 +1689,15 @@ libbalsa_message_get_protect_state(LibBalsaMessage *message)
 }
 
 
+gboolean
+libbalsa_message_has_crypto_content(LibBalsaMessage *message)
+{
+    g_return_val_if_fail(LIBBALSA_IS_MESSAGE(message), FALSE);
+
+    return libbalsa_message_body_has_crypto_content(message->body_list);
+}
+
+
 guint
 libbalsa_message_get_body_ref(LibBalsaMessage *message)
 {
diff --git a/libbalsa/message.h b/libbalsa/message.h
index 1ce60be41..634fd5055 100644
--- a/libbalsa/message.h
+++ b/libbalsa/message.h
@@ -203,8 +203,6 @@ gboolean libbalsa_message_is_multipart(LibBalsaMessage * message);
 gboolean libbalsa_message_is_partial(LibBalsaMessage * message,
                                     gchar ** id);
 gboolean libbalsa_message_has_attachment(LibBalsaMessage * message);
-gboolean libbalsa_message_is_pgp_signed(LibBalsaMessage * message);
-gboolean libbalsa_message_is_pgp_encrypted(LibBalsaMessage * message);
 
 const gchar* libbalsa_message_header_get_one(LibBalsaMessageHeaders* headers,
                                              const gchar *find);
@@ -284,6 +282,7 @@ GList                  *libbalsa_message_get_in_reply_to(LibBalsaMessage *messag
 gboolean                libbalsa_message_get_attach_pubkey(LibBalsaMessage *message);
 LibBalsaMsgProtectState libbalsa_message_get_protect_state(LibBalsaMessage *message);
 guint                   libbalsa_message_get_body_ref(LibBalsaMessage *message);
+gboolean                               libbalsa_message_has_crypto_content(LibBalsaMessage *message);
 
 /*
  * Setters
diff --git a/src/balsa-message.c b/src/balsa-message.c
index 0de604bf4..d496b9fcd 100644
--- a/src/balsa-message.c
+++ b/src/balsa-message.c
@@ -142,7 +142,6 @@ static LibBalsaMsgProtectState bm_scan_signatures(LibBalsaMessageBody *body,
 static GdkPixbuf * get_crypto_content_icon(LibBalsaMessageBody * body,
                                           const gchar * content_type,
                                           gchar ** icon_title);
-static void message_recheck_crypto_cb(GtkWidget * button, BalsaMessage * balsa_message);
 
 #ifdef ENABLE_AUTOCRYPT
 static inline gboolean autocrypt_in_use(void);
@@ -250,6 +249,9 @@ balsa_headers_attachments_popup(GtkButton * button, BalsaMessage * balsa_message
 }
 
 
+/* Note: this function returns a NULL-terminated array of buttons for a top-level headers widget.  
Currently, we return just a
+ * single item (the button for showing the menu for switching between attachments) so we /could/ change the 
return type to
+ * GtkWidget *. */
 static GtkWidget **
 bm_header_tl_buttons(BalsaMessage * balsa_message)
 {
@@ -258,22 +260,6 @@ bm_header_tl_buttons(BalsaMessage * balsa_message)
 
     array = g_ptr_array_new();
 
-    button =
-        gtk_button_new_from_icon_name(balsa_icon_id(BALSA_PIXMAP_GPG_RECHECK),
-                                      GTK_ICON_SIZE_BUTTON);
-    gtk_widget_set_tooltip_text(button,
-                               _("Check cryptographic signature"));
-    g_signal_connect(button, "focus_in_event",
-                    G_CALLBACK(balsa_mime_widget_limit_focus),
-                    (gpointer) balsa_message);
-    g_signal_connect(button, "focus_out_event",
-                    G_CALLBACK(balsa_mime_widget_unlimit_focus),
-                    (gpointer) balsa_message);
-    gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
-    g_signal_connect(button, "clicked",
-                    G_CALLBACK(message_recheck_crypto_cb), balsa_message);
-    g_ptr_array_add(array, button);
-
     balsa_message->attach_button = button =
         gtk_button_new_from_icon_name(balsa_icon_id(BALSA_PIXMAP_ATTACHMENT),
                                       GTK_ICON_SIZE_BUTTON);
@@ -298,24 +284,6 @@ bm_header_tl_buttons(BalsaMessage * balsa_message)
 }
 
 
-#if !GTK_CHECK_VERSION(3, 15, 0)
-/* Callback for the "style-updated" signal; set the message background to
- * match the base color of the content in the tree-view. */
-static void
-bm_on_set_style(GtkWidget * widget,
-               BalsaMessage * balsa_message)
-{
-    GtkStyleContext *context;
-    GdkRGBA rgba;
-
-    context = gtk_widget_get_style_context(balsa_message->treeview);
-    gtk_style_context_get_background_color(context, GTK_STATE_FLAG_NORMAL,
-                                           &rgba);
-    gtk_widget_override_background_color(balsa_message->scroll,
-                                         GTK_STATE_FLAG_NORMAL, &rgba);
-}
-#endif
-
 /*
  * Callbacks and helpers for the find bar.
  */
@@ -3213,13 +3181,13 @@ balsa_message_perform_crypto(LibBalsaMessage * message,
 
 
 /*
- * Callback for the "Check Crypto" button in the message's top-level headers.
+ * Recheck crypto status of a message.
  * It works roughly like balsa_message_set, but with less overhead and with
  * "check always" mode. Note that this routine adds a temporary reference to
  * the message.
  */
-static void
-message_recheck_crypto_cb(GtkWidget * button, BalsaMessage * balsa_message)
+void
+balsa_message_recheck_crypto(BalsaMessage *balsa_message)
 {
     LibBalsaMessageBody *body_list;
     LibBalsaMsgProtectState prot_state;
diff --git a/src/balsa-message.h b/src/balsa-message.h
index b3d2b17c8..d4ea7c90b 100644
--- a/src/balsa-message.h
+++ b/src/balsa-message.h
@@ -47,6 +47,7 @@ GtkWidget *balsa_message_new(void);
 
 gboolean balsa_message_set(BalsaMessage * bmessage,
                           LibBalsaMailbox * mailbox, guint msgno);
+void balsa_message_recheck_crypto(BalsaMessage *balsa_message);
 
 void balsa_message_next_part(BalsaMessage * bmessage);
 gboolean balsa_message_has_next_part(BalsaMessage * bmessage);
diff --git a/src/main-window.c b/src/main-window.c
index dac8cf08e..b8a98fc2a 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -701,6 +701,7 @@ static const BalsaToolbarEntry main_toolbar_extras[] = {
     { "mailbox-close",     "window-close-symbolic"     },
     { "mailbox-select-all", BALSA_PIXMAP_MARK_ALL      },
     { "show-all-headers",   BALSA_PIXMAP_SHOW_HEADERS  },
+       { "recheck-crypt",      BALSA_PIXMAP_GPG_RECHECK   },
     { "reset-filter",      "gtk-cancel"                },
     { "show-preview-pane",  BALSA_PIXMAP_SHOW_PREVIEW  },
     { "mailbox-expunge",   "edit-clear"                },
@@ -1624,6 +1625,17 @@ view_source_activated(GSimpleAction * action,
     g_list_free_full(messages, g_object_unref);
 }
 
+static void
+recheck_crypt_activated(GSimpleAction * action,
+                                       GVariant      * parameter,
+                                               gpointer        user_data)
+{
+    BalsaWindow *window = BALSA_WINDOW(user_data);
+    BalsaWindowPrivate *priv = balsa_window_get_instance_private(window);
+
+       balsa_message_recheck_crypto(BALSA_MESSAGE(priv->preview));
+}
+
 static void
 copy_message_activated(GSimpleAction * action,
                        GVariant      * parameter,
@@ -2072,6 +2084,7 @@ bw_add_win_action_entries(GActionMap * action_map)
         {"previous-part",         previous_part_activated},
         {"save-part",             save_part_activated},
         {"view-source",           view_source_activated},
+               {"recheck-crypt",                 recheck_crypt_activated},
         {"copy-message",          copy_message_activated},
         {"select-text",           select_text_activated},
         {"move-to-trash",         move_to_trash_activated},
@@ -2695,11 +2708,15 @@ bw_enable_part_menu_items(BalsaWindow * window)
 {
     BalsaWindowPrivate *priv = balsa_window_get_instance_private(window);
     BalsaMessage *msg = window ? BALSA_MESSAGE(priv->preview) : NULL;
+       LibBalsaMessage *lbmessage;
 
     bw_action_set_enabled(window, "next-part",
                           balsa_message_has_next_part(msg));
     bw_action_set_enabled(window, "previous-part",
                           balsa_message_has_previous_part(msg));
+    lbmessage = (msg != NULL) ? balsa_message_get_message(msg) : NULL;
+    bw_action_set_enabled(window, "recheck-crypt",
+       (lbmessage != NULL) ? libbalsa_message_has_crypto_content(lbmessage) : FALSE);
 }
 
 static void
diff --git a/src/message-window.c b/src/message-window.c
index ced9dc5f7..dacd08602 100644
--- a/src/message-window.c
+++ b/src/message-window.c
@@ -99,13 +99,18 @@ mw_set_active(MessageWindow * mw,
 static void
 mw_set_part_buttons_sensitive(MessageWindow * mw, BalsaMessage * msg)
 {
-    if (msg == NULL || balsa_message_get_tree_view(msg) == NULL)
+       LibBalsaMessage *lbmsg;
+
+       if (msg == NULL || balsa_message_get_tree_view(msg) == NULL)
        return;
 
     mw_set_enabled(mw, "next-part",
                    balsa_message_has_next_part(msg));
     mw_set_enabled(mw, "previous-part",
                    balsa_message_has_previous_part(msg));
+    lbmsg = balsa_message_get_message(msg);
+    mw_set_enabled(mw, "recheck-crypt",
+       (lbmsg != NULL) ? libbalsa_message_has_crypto_content(lbmsg) : FALSE);
 }
 
 static gboolean
@@ -159,7 +164,8 @@ static const BalsaToolbarEntry message_toolbar_extras[] = {
     { "next-flagged",     BALSA_PIXMAP_NEXT_FLAGGED  },
     { "previous-part",    BALSA_PIXMAP_PREVIOUS_PART },
     { "close",           "window-close-symbolic"     },
-    { "show-all-headers", BALSA_PIXMAP_SHOW_HEADERS  }
+    { "show-all-headers", BALSA_PIXMAP_SHOW_HEADERS  },
+       { "recheck-crypt",    BALSA_PIXMAP_GPG_RECHECK   },
 };
 
 /* Create the toolbar model for the message window's toolbar.
@@ -511,6 +517,15 @@ mw_view_source_activated(GSimpleAction * action, GVariant * parameter,
                                  &balsa_app.source_escape_specials);
 }
 
+static void
+mw_recheck_crypt_activated(GSimpleAction * action,
+                                          GVariant      * parameter,
+                                                  gpointer        data)
+{
+    MessageWindow *mw = (MessageWindow *) data;
+       balsa_message_recheck_crypto(BALSA_MESSAGE(mw->bmessage));
+}
+
 static void
 mw_close_activated(GSimpleAction * action, GVariant * parameter,
                    gpointer data)
@@ -779,6 +794,7 @@ static GActionEntry win_entries[] = {
     {"previous-part",         mw_previous_part_activated},
     {"save-part",             mw_save_part_activated},
     {"view-source",           mw_view_source_activated},
+       {"recheck-crypt",                 mw_recheck_crypt_activated},
     {"select-text",           mw_select_text_activated},
     {"move-to-trash",         mw_move_to_trash_activated},
     /* Only a toolbar button: */
diff --git a/src/toolbar-factory.c b/src/toolbar-factory.c
index c52e679c5..8a9f226de 100644
--- a/src/toolbar-factory.c
+++ b/src/toolbar-factory.c
@@ -143,6 +143,7 @@ button_data toolbar_buttons[]={
     {BALSA_PIXMAP_MARKED_NEW,    N_("Toggle\nnew"),     FALSE},
     {BALSA_PIXMAP_MARK_ALL,      N_("Mark all"),        FALSE},
     {BALSA_PIXMAP_SHOW_HEADERS,  N_("All\nheaders"),    FALSE},
+       {BALSA_PIXMAP_GPG_RECHECK,   N_("Recheck\ncryptography"), FALSE},
     {"gtk-cancel",           N_("Reset\nFilter"),   FALSE},
     {BALSA_PIXMAP_SHOW_PREVIEW,  N_("Message Preview"),     FALSE},
     {BALSA_PIXMAP_GPG_SIGN,      N_("Sign"),            FALSE},
diff --git a/ui/main-window.ui b/ui/main-window.ui
index 0bbf27cb2..c39898175 100644
--- a/ui/main-window.ui
+++ b/ui/main-window.ui
@@ -447,6 +447,12 @@
           <attribute name="action">win.view-source</attribute>
           <attribute name="accel">&lt;Primary&gt;u</attribute>
         </item>
+        <item>
+          <attribute name="label"
+            translatable="yes">Decrypt and check signatures</attribute>
+          <attribute name="action">win.recheck-crypt</attribute>
+          <attribute name="accel">&lt;Primary&gt;d</attribute>
+        </item>
       </section>
       <section>
         <item>
diff --git a/ui/message-window.ui b/ui/message-window.ui
index 55522758a..9d03e50d2 100644
--- a/ui/message-window.ui
+++ b/ui/message-window.ui
@@ -166,6 +166,12 @@
           <attribute name="action">win.view-source</attribute>
           <attribute name="accel">&lt;Primary&gt;u</attribute>
         </item>
+        <item>
+          <attribute name="label"
+            translatable="yes">Decrypt and check signatures</attribute>
+          <attribute name="action">win.recheck-crypt</attribute>
+          <attribute name="accel">&lt;Primary&gt;d</attribute>
+        </item>
       </section>
       <section>
         <item>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]