[evolution] Allow the attachments and inline images to be dragged to the editor



commit e84a09b6eb1c1cb798e06ee66e0bd0e16b6888bf
Author: Tomas Popela <tpopela redhat com>
Date:   Wed Mar 22 14:42:00 2017 +0100

    Allow the attachments and inline images to be dragged to the editor
    
    If the HTML mode is enabled then they are inserted to the body (if
    images) otherwise are inserted to the attachment view (we have to teach
    the EAttachmentView how to handle the text/uri-list target).

 src/composer/e-msg-composer.c               |   27 +------
 src/e-util/e-attachment-view.c              |  124 +++++++++++++++++++++++++++
 src/e-util/e-misc-utils.c                   |   35 ++++++++
 src/e-util/e-misc-utils.h                   |    3 +
 src/mail/e-mail-display.c                   |    8 +--
 src/modules/webkit-editor/e-webkit-editor.c |   27 +------
 6 files changed, 166 insertions(+), 58 deletions(-)
---
diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c
index f7f1e4b..c76134e 100644
--- a/src/composer/e-msg-composer.c
+++ b/src/composer/e-msg-composer.c
@@ -1774,31 +1774,6 @@ msg_composer_paste_clipboard_cb (EContentEditor *cnt_editor,
        return TRUE;
 }
 
-static gchar *
-next_uri (guchar **uri_list,
-          gint *len,
-          gint *list_len)
-{
-       guchar *uri, *begin;
-
-       begin = *uri_list;
-       *len = 0;
-       while (**uri_list && **uri_list != '\n' && **uri_list != '\r' && *list_len) {
-               (*uri_list) ++;
-               (*len) ++;
-               (*list_len) --;
-       }
-
-       uri = (guchar *) g_strndup ((gchar *) begin, *len);
-
-       while ((!**uri_list || **uri_list == '\n' || **uri_list == '\r') && *list_len) {
-               (*uri_list) ++;
-               (*list_len) --;
-       }
-
-       return (gchar *) uri;
-}
-
 static void
 msg_composer_drag_data_received_cb (GtkWidget *widget,
                                     GdkDragContext *context,
@@ -1846,7 +1821,7 @@ msg_composer_drag_data_received_cb (GtkWidget *widget,
 
                list_len = length;
                do {
-                       uri = next_uri ((guchar **) &data, &len, &list_len);
+                       uri = e_util_next_uri_from_uri_list ((guchar **) &data, &len, &list_len);
                        e_content_editor_insert_image (cnt_editor, uri);
                        g_free (uri);
                } while (list_len);
diff --git a/src/e-util/e-attachment-view.c b/src/e-util/e-attachment-view.c
index 93ca788..3b368d3 100644
--- a/src/e-util/e-attachment-view.c
+++ b/src/e-util/e-attachment-view.c
@@ -37,6 +37,7 @@ enum {
 
 /* Note: Do not use the info field. */
 static GtkTargetEntry target_table[] = {
+       { (gchar *) "text/uri-list", 0, 0 },
        { (gchar *) "_NETSCAPE_URL", 0, 0 }
 };
 
@@ -426,6 +427,125 @@ attachment_view_netscape_url (EAttachmentView *view,
 }
 
 static void
+attachment_view_uri_list (EAttachmentView *view,
+                          GdkDragContext *drag_context,
+                          gint x,
+                          gint y,
+                          GtkSelectionData *selection_data,
+                          guint info,
+                          guint time)
+{
+       static GdkAtom atom = GDK_NONE;
+       EAttachmentStore *store;
+       EAttachment *attachment;
+       const gchar *data;
+       gpointer parent;
+       gint length = 0, list_length = 0, uri_length = 0;
+       gchar *uri;
+
+
+       if (G_UNLIKELY (atom == GDK_NONE))
+               atom = gdk_atom_intern_static_string ("text/uri-list");
+
+       if (gtk_selection_data_get_target (selection_data) != atom)
+               return;
+
+       g_signal_stop_emission_by_name (view, "drag-data-received");
+
+       data = (const gchar *) gtk_selection_data_get_data (selection_data);
+       length = gtk_selection_data_get_length (selection_data);
+
+       if (!data || length < 0) {
+               gtk_drag_finish (drag_context, FALSE, FALSE, time);
+               return;
+       }
+
+       store = e_attachment_view_get_store (view);
+
+       parent = gtk_widget_get_toplevel (GTK_WIDGET (view));
+       parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
+
+       list_length = length;
+       do {
+               uri = e_util_next_uri_from_uri_list ((guchar **) &data, &uri_length, &list_length);
+
+               if (strstr (uri, ";base64,")) {
+                       /* base64 encoded data */
+                       CamelMimePart *mime_part;
+                       gchar *mime_type = NULL, *filename = NULL;
+                       guchar *base64_data;
+                       gsize base64_data_length;
+
+                       if (g_str_has_prefix (uri, "data:")) {
+                               const gchar *base64 = strstr (uri, ";") + 1;
+                               /* strlen ("data:") == 5 */
+                               mime_type = g_strndup (uri + 5, base64 - uri - 5 - 1);
+
+                               base64 = strstr (base64, ",") + 1;
+                               base64_data = g_base64_decode (base64, &base64_data_length);
+                       } else if (strstr (uri, ";data")) {
+                               /* CID attachment from mail preview that has
+                                * the filename prefixed before the base64 data -
+                                * see EMailDisplay. */
+                               const gchar *base64 = strstr (uri, ";") + 1;
+                               glong filename_length, mime_type_length, base64_length;
+
+                               base64_length = g_utf8_strlen (base64, -1);
+
+                               filename_length = uri_length - base64_length - 1;
+                               filename = g_strndup (uri, filename_length);
+
+                               /* strlen ("data:") == 5 */
+                               mime_type_length = base64_length - g_utf8_strlen (strstr (base64, ";"), -1) - 
5;
+                               mime_type = g_strndup (uri + filename_length + 5 + 1, mime_type_length);
+
+                               base64 = strstr (base64, ",") + 1;
+                               base64_data = g_base64_decode (base64, &base64_data_length);
+                       } else {
+                               g_free (uri);
+                               gtk_drag_finish (drag_context, FALSE, FALSE, time);
+                               return;
+                       }
+
+                       mime_part = camel_mime_part_new ();
+
+                       camel_mime_part_set_content (mime_part, (const gchar *) base64_data, 
base64_data_length, mime_type);
+                       camel_mime_part_set_disposition (mime_part, "inline");
+                       if (filename && *filename)
+                               camel_mime_part_set_filename (mime_part, filename);
+                       camel_mime_part_set_encoding (mime_part, CAMEL_TRANSFER_ENCODING_BASE64);
+
+                       attachment = e_attachment_new ();
+                       e_attachment_set_mime_part (attachment, mime_part);
+                       e_attachment_store_add_attachment (store, attachment);
+                       e_attachment_load_async (
+                               attachment, (GAsyncReadyCallback)
+                               call_attachment_load_handle_error, parent ? g_object_ref (parent) : NULL);
+
+                       g_object_unref (attachment);
+                       g_object_unref (mime_part);
+                       if (mime_type)
+                               g_free (mime_type);
+                       if (filename)
+                               g_free (filename);
+                       g_free (base64_data);
+               } else {
+                       /* regular URIs */
+                       attachment = e_attachment_new_for_uri (uri);
+                       e_attachment_store_add_attachment (store, attachment);
+                       e_attachment_load_async (
+                               attachment, (GAsyncReadyCallback)
+                               call_attachment_load_handle_error, parent ? g_object_ref (parent) : NULL);
+                       g_object_unref (attachment);
+               }
+
+               g_free (uri);
+       } while (list_length);
+
+       gtk_drag_finish (drag_context, TRUE, FALSE, time);
+}
+
+static void
 attachment_view_text_calendar (EAttachmentView *view,
                                GdkDragContext *drag_context,
                                gint x,
@@ -807,6 +927,10 @@ e_attachment_view_init (EAttachmentView *view)
 
        g_signal_connect (
                view, "drag-data-received",
+               G_CALLBACK (attachment_view_uri_list), NULL);
+
+       g_signal_connect (
+               view, "drag-data-received",
                G_CALLBACK (attachment_view_text_x_vcard), NULL);
 
        g_signal_connect (
diff --git a/src/e-util/e-misc-utils.c b/src/e-util/e-misc-utils.c
index 1e0f1f8..e5e7097 100644
--- a/src/e-util/e-misc-utils.c
+++ b/src/e-util/e-misc-utils.c
@@ -3908,3 +3908,38 @@ e_util_get_webkit_developer_mode_enabled (void)
 
        return enabled != 0;
 }
+
+/**
+ * e_util_next_uri_from_uri_list:
+ * @uri_list: array of URIs separated by new lines
+ * @len: (out): a length of the found URI
+ * @list_len: (out): a length of the array
+ *
+ * Returns: A newly allocated string with found URI.
+ *
+ * Since: 3.26
+ **/
+gchar *
+e_util_next_uri_from_uri_list (guchar **uri_list,
+                               gint *len,
+                               gint *list_len)
+{
+       guchar *uri, *begin;
+
+       begin = *uri_list;
+       *len = 0;
+       while (**uri_list && **uri_list != '\n' && **uri_list != '\r' && *list_len) {
+               (*uri_list) ++;
+               (*len) ++;
+               (*list_len) --;
+       }
+
+       uri = (guchar *) g_strndup ((gchar *) begin, *len);
+
+       while ((!**uri_list || **uri_list == '\n' || **uri_list == '\r') && *list_len) {
+               (*uri_list) ++;
+               (*list_len) --;
+       }
+
+       return (gchar *) uri;
+}
diff --git a/src/e-util/e-misc-utils.h b/src/e-util/e-misc-utils.h
index 4a08351..65d15fe 100644
--- a/src/e-util/e-misc-utils.h
+++ b/src/e-util/e-misc-utils.h
@@ -332,6 +332,9 @@ void                e_util_save_file_chooser_folder (GtkFileChooser *file_chooser);
 void           e_util_load_file_chooser_folder (GtkFileChooser *file_chooser);
 gboolean       e_util_get_webkit_developer_mode_enabled
                                                (void);
+gchar *                e_util_next_uri_from_uri_list   (guchar **uri_list,
+                                                gint *len,
+                                                gint *list_len);
 
 G_END_DECLS
 
diff --git a/src/mail/e-mail-display.c b/src/mail/e-mail-display.c
index ddbf987..5d0bce8 100644
--- a/src/mail/e-mail-display.c
+++ b/src/mail/e-mail-display.c
@@ -1762,7 +1762,6 @@ mail_display_uri_requested_cb (EWebView *web_view,
        }
 }
 
-#if 0 /* FIXME WK2 */
 static CamelMimePart *
 camel_mime_part_from_cid (EMailDisplay *display,
                           const gchar *uri)
@@ -1870,7 +1869,6 @@ mail_display_drag_data_get (GtkWidget *widget,
  out:
        g_free (uri);
 }
-#endif
 
 static void
 e_mail_display_test_change_and_update_fonts_cb (EMailDisplay *mail_display,
@@ -1929,9 +1927,7 @@ e_mail_display_class_init (EMailDisplayClass *class)
        widget_class->button_press_event = mail_display_button_press_event;
 
        web_view_class = E_WEB_VIEW_CLASS (class);
-#if 0 /* FIXME WK2 */
        web_view_class->suggest_filename = mail_display_suggest_filename;
-#endif
        web_view_class->set_fonts = mail_display_set_fonts;
 
        g_object_class_install_property (
@@ -2064,11 +2060,11 @@ e_mail_display_init (EMailDisplay *display)
        g_signal_connect (
                display, "process-mailto",
                G_CALLBACK (mail_display_process_mailto), NULL);
-#if 0 /* FIXME WK2 */
+
        g_signal_connect_after (
                display, "drag-data-get",
                G_CALLBACK (mail_display_drag_data_get), display);
-#endif
+
        display->priv->settings = e_util_ref_settings ("org.gnome.evolution.mail");
        g_signal_connect_swapped (
                display->priv->settings , "changed::monospace-font",
diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c
index 91dd309..bf52913 100644
--- a/src/modules/webkit-editor/e-webkit-editor.c
+++ b/src/modules/webkit-editor/e-webkit-editor.c
@@ -5820,31 +5820,6 @@ webkit_editor_drag_end_cb (EWebKitEditor *wk_editor,
        wk_editor->priv->performing_drag = FALSE;
 }
 
-static gchar *
-next_uri (guchar **uri_list,
-          gint *len,
-          gint *list_len)
-{
-       guchar *uri, *begin;
-
-       begin = *uri_list;
-       *len = 0;
-       while (**uri_list && **uri_list != '\n' && **uri_list != '\r' && *list_len) {
-               (*uri_list) ++;
-               (*len) ++;
-               (*list_len) --;
-       }
-
-       uri = (guchar *) g_strndup ((gchar *) begin, *len);
-
-       while ((!**uri_list || **uri_list == '\n' || **uri_list == '\r') && *list_len) {
-               (*uri_list) ++;
-               (*list_len) --;
-       }
-
-       return (gchar *) uri;
-}
-
 static void
 webkit_editor_drag_data_received_cb (GtkWidget *widget,
                                      GdkDragContext *context,
@@ -5894,7 +5869,7 @@ webkit_editor_drag_data_received_cb (GtkWidget *widget,
 
                list_len = length;
                do {
-                       text = next_uri ((guchar **) &data, &len, &list_len);
+                       text = e_util_next_uri_from_uri_list ((guchar **) &data, &len, &list_len);
                        webkit_editor_insert_content (
                                E_CONTENT_EDITOR (wk_editor),
                                text,


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