Implement copying of attached images to clipboard
authorColin Leroy <colin@colino.net>
Sun, 7 Jul 2019 08:40:15 +0000 (10:40 +0200)
committerColin Leroy <colin@colino.net>
Sun, 7 Jul 2019 08:40:15 +0000 (10:40 +0200)
src/mimeview.c
src/procmime.c
src/procmime.h
src/textview.c

index 7e283307eece1963feb9b0020ed3f4ab68498c45..fe840f516dc763931b51d4ea34596d33d33d8530 100644 (file)
@@ -157,6 +157,33 @@ static void mimeview_open_with_cb(GtkAction *action, gpointer data)
 }
 #endif
 
+static void mimeview_copy_cb(GtkAction *action, gpointer data)
+{
+       MimeView *mimeview = (MimeView *)data;
+       MimeInfo *mimeinfo = mimeview_get_part_to_use(mimeview);
+
+       if (mimeinfo == NULL)
+               return;
+
+       if (mimeinfo->type == MIMETYPE_IMAGE) {
+               GError *error = NULL;
+               GdkPixbuf *pixbuf = procmime_get_part_as_pixbuf(mimeinfo, &error);
+               if (error != NULL) {
+                       g_warning("could not copy: %s", error->message);
+                       g_error_free(error);
+               } else {
+                       gtk_clipboard_set_image(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+                                               pixbuf);
+               }
+               g_object_unref(pixbuf);
+       } else {
+               void *data = procmime_get_part_as_string(mimeinfo, FALSE);
+               gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+                                      data, mimeinfo->length);
+               g_free(data);
+       }
+}
+
 static void mimeview_send_to_cb(GtkAction *action, gpointer data)
 {
        MimeView *mimeview = (MimeView *)data;  
@@ -194,6 +221,7 @@ static GtkActionEntry mimeview_menu_actions[] = {
 #if (!defined G_OS_WIN32)
        { "MimeView/OpenWith", NULL, N_("Open _with..."), NULL, "Open MIME part with...", G_CALLBACK(mimeview_open_with_cb) },
 #endif
+       { "MimeView/Copy", NULL, N_("Copy"), NULL, "Copy", G_CALLBACK(mimeview_copy_cb) },
        { "MimeView/SendTo", NULL, N_("Send to..."), NULL, "Send to", G_CALLBACK(mimeview_send_to_cb) },
        { "MimeView/DisplayAsText", NULL, N_("_Display as text"), NULL, "Display as text", G_CALLBACK(mimeview_display_as_text_cb) },
        { "MimeView/SaveAs", NULL, N_("_Save as..."), NULL, "Save as", G_CALLBACK(mimeview_save_as_cb) },
@@ -400,6 +428,9 @@ MimeView *mimeview_create(MainWindow *mainwin)
                        GTK_UI_MANAGER_MENUITEM);
 #endif
        MENUITEM_ADDUI_MANAGER(mimeview->ui_manager, 
+                       "/Menus/MimeView/", "Copy", "MimeView/Copy",
+                       GTK_UI_MANAGER_MENUITEM);
+       MENUITEM_ADDUI_MANAGER(mimeview->ui_manager,
                        "/Menus/MimeView/", "SendTo", "MimeView/SendTo",
                        GTK_UI_MANAGER_MENUITEM);
        MENUITEM_ADDUI_MANAGER(mimeview->ui_manager, 
@@ -1519,6 +1550,13 @@ static gboolean part_button_pressed(MimeView *mimeview, GdkEventButton *event,
                        cm_menu_set_sensitive_full(mimeview->ui_manager, "Menus/MimeView/DisplayAsText", FALSE);
                else
                        cm_menu_set_sensitive_full(mimeview->ui_manager, "Menus/MimeView/DisplayAsText", TRUE);
+
+               if (partinfo && (partinfo->type == MIMETYPE_MESSAGE ||
+                                partinfo->type == MIMETYPE_IMAGE ||
+                                partinfo->type == MIMETYPE_TEXT))
+                       cm_menu_set_sensitive_full(mimeview->ui_manager, "Menus/MimeView/Copy", TRUE);
+               else
+                       cm_menu_set_sensitive_full(mimeview->ui_manager, "Menus/MimeView/Copy", FALSE);
 #ifndef G_OS_WIN32
                if (partinfo &&
                    partinfo->type == MIMETYPE_APPLICATION &&
index a146339e969fcd018863619cddc869ee958286db..1f126ecd2ac6ae3ba592bb792cd97963456b0866 100644 (file)
@@ -2724,9 +2724,10 @@ GInputStream *procmime_get_part_as_inputstream(MimeInfo *mimeinfo)
        cm_return_val_if_fail(mimeinfo != NULL, NULL);
 
        if (mimeinfo->encoding_type != ENC_BINARY &&
-                       !procmime_decode_content(mimeinfo))
+                       !procmime_decode_content(mimeinfo)) {
+               g_warning("could not decode part");
                return NULL;
-
+       }
        if (mimeinfo->content == MIMECONTENT_MEM) {
                /* NULL for destroy func, since we're not copying
                 * the data for the stream. */
@@ -2739,3 +2740,25 @@ GInputStream *procmime_get_part_as_inputstream(MimeInfo *mimeinfo)
                                mimeinfo->length, g_free);
        }
 }
+
+GdkPixbuf *procmime_get_part_as_pixbuf(MimeInfo *mimeinfo, GError **error)
+{
+       GdkPixbuf *pixbuf;
+       GInputStream *stream;
+
+       *error = NULL;
+
+       stream = procmime_get_part_as_inputstream(mimeinfo);
+       if (stream == NULL) {
+               return NULL;
+       }
+
+       pixbuf = gdk_pixbuf_new_from_stream(stream, NULL, error);
+       g_object_unref(stream);
+
+       if (*error != NULL) {
+               return NULL;
+       }
+       return pixbuf;
+}
+
index 5749e6f699a3b351d65101c581e2896162d65819..e87a276245dcda00d09d8dd92661cfc04a91340e 100644 (file)
@@ -25,6 +25,7 @@
 #endif
 
 #include <gio/gio.h>
+#include <gtk/gtk.h>
 
 #include "utils.h"
 #include "proctypes.h"
@@ -244,6 +245,7 @@ gboolean procmime_scan_text_content(MimeInfo *mimeinfo,
 void *procmime_get_part_as_string(MimeInfo *mimeinfo,
                gboolean null_terminate);
 GInputStream *procmime_get_part_as_inputstream(MimeInfo *mimeinfo);
+GdkPixbuf *procmime_get_part_as_pixbuf(MimeInfo *mimeinfo, GError **error);
 
 #ifdef __cplusplus
 }
index 88c0aa10abeb4e017599a757518351cce106782a..55760036f6c1d82c69546ad31ff1c579d4325244 100644 (file)
@@ -722,22 +722,14 @@ static void textview_add_part(TextView *textview, MimeInfo *mimeinfo)
 
                        START_TIMING("inserting image");
 
-                       stream = procmime_get_part_as_inputstream(mimeinfo);
-                       if (stream == NULL) {
-                               g_warning("Can't get the image file");
-                               END_TIMING();
-                               return;
-                       }
-
-                       pixbuf = gdk_pixbuf_new_from_stream(stream, NULL, &error);
-                       g_object_unref(stream);
-
+                       pixbuf = procmime_get_part_as_pixbuf(mimeinfo, &error);
                        if (error != NULL) {
                                g_warning("Can't load the image: %s\n", error->message);
                                g_error_free(error);
                                END_TIMING();
                                return;
                        }
+
                        if (textview->stop_loading) {
                                END_TIMING();
                                return;