* Fixes NB#83408, select attachment is now set as children of the edit window
[modest] / src / maemo / modest-msg-edit-window.c
index 04b467d..b842c0d 100644 (file)
@@ -35,6 +35,7 @@
 #include <tny-account-store.h>
 #include <tny-fs-stream.h>
 #include <tny-vfs-stream.h>
+#include <tny-camel-mem-stream.h>
 
 #include <config.h>
 
@@ -138,6 +139,7 @@ static void modest_msg_edit_window_show_toolbar   (ModestWindow *window,
 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
                                                           GdkEvent *event,
                                                           ModestMsgEditWindow *window);
+static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
 static void subject_field_move_cursor (GtkEntry *entry,
                                       GtkMovementStep step,
                                       gint a1,
@@ -277,7 +279,7 @@ struct _ModestMsgEditWindowPrivate {
        guint        scroll_drag_timeout_id;
        gdouble      last_upper;
 
-       gint last_cid;
+       gint next_cid;
        TnyList *attachments;
        TnyList *images;
        guint64 images_size;
@@ -289,6 +291,7 @@ struct _ModestMsgEditWindowPrivate {
        gulong      clipboard_change_handler_id;
        gulong      default_clipboard_change_handler_id;
        gulong      account_removed_handler_id;
+       guint       clipboard_owner_idle;
        gchar       *clipboard_text;
 
        TnyMsg      *draft_msg;
@@ -417,7 +420,7 @@ modest_msg_edit_window_init (ModestMsgEditWindow *obj)
        priv->images        = TNY_LIST (tny_simple_list_new ());
        priv->images_size   = 0;
        priv->images_count  = 0;
-       priv->last_cid      = 0;
+       priv->next_cid      = 0;
 
        priv->cc_caption    = NULL;
        priv->bcc_caption    = NULL;
@@ -437,6 +440,7 @@ modest_msg_edit_window_init (ModestMsgEditWindow *obj)
        priv->clipboard_change_handler_id = 0;
        priv->default_clipboard_change_handler_id = 0;
        priv->account_removed_handler_id = 0;
+       priv->clipboard_owner_idle = 0;
        priv->clipboard_text = NULL;
        priv->sent = FALSE;
 
@@ -504,15 +508,21 @@ get_transports (void)
 static ModestPair *
 find_transport_from_message_sender (ModestPairList *transports, TnyMsg *msg)
 {
+       ModestPair *account_pair = NULL;
+       gchar *from;
+       TnyHeader *header;
+
        g_return_val_if_fail (transports, NULL);
        g_return_val_if_fail (msg, NULL);
 
-       ModestPair *account_pair = NULL;
-       TnyHeader *header = tny_msg_get_header (msg);
+       header = tny_msg_get_header (msg);
 
-       if (header != NULL && tny_header_get_from (header)) {
-               char *from_addr = modest_text_utils_get_email_address (tny_header_get_from (header));
+       if (header != NULL && (from = tny_header_dup_from (header))) {
                GSList *iter;
+               char *from_addr;
+
+               from_addr = modest_text_utils_get_email_address (from);
+               g_free (from);
                for (iter = transports; iter && !account_pair; iter = iter->next) {
                        ModestPair *pair = (ModestPair *) iter->data;
                        char *account_addr = modest_text_utils_get_email_address ((char *) pair->second);
@@ -693,6 +703,8 @@ connect_signals (ModestMsgEditWindow *obj)
                          G_CALLBACK (text_buffer_can_redo), obj);
        g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
                           G_CALLBACK (body_changed), obj);
+       g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
+                          G_CALLBACK (body_changed), obj);
        g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text", 
                          G_CALLBACK (text_buffer_insert_text), obj);
        g_signal_connect (G_OBJECT (obj), "window-state-event",
@@ -981,6 +993,10 @@ modest_msg_edit_window_finalize (GObject *obj)
                g_source_remove (priv->scroll_drag_timeout_id);
                priv->scroll_drag_timeout_id = 0;
        }
+       if (priv->clipboard_owner_idle > 0) {
+               g_source_remove (priv->clipboard_owner_idle);
+               priv->clipboard_owner_idle = 0;
+       }
        g_free (priv->msg_uid);
        g_free (priv->last_search);
        g_slist_free (priv->font_items_group);
@@ -1138,7 +1154,7 @@ get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
 }
 
 static void
-update_last_cid (ModestMsgEditWindow *self, TnyList *attachments)
+update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
 {
        TnyIterator *iter;
        ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
@@ -1151,8 +1167,8 @@ update_last_cid (ModestMsgEditWindow *self, TnyList *attachments)
                if (cid != NULL) {
                        char *invalid = NULL;
                        gint int_cid = strtol (cid, &invalid, 10);
-                       if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
-                               priv->last_cid = int_cid;
+                       if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
+                               priv->next_cid = int_cid + 1;
                        }
                }
                g_object_unref (part);
@@ -1164,7 +1180,7 @@ static void
 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
 {
        TnyHeader *header;
-       const gchar *to, *cc, *bcc, *subject;
+       gchar *to, *cc, *bcc, *subject;
        gchar *body;
        ModestMsgEditWindowPrivate *priv;
        GtkTextIter iter;
@@ -1178,10 +1194,10 @@ set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
        priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
 
        header = tny_msg_get_header (msg);
-       to      = tny_header_get_to (header);
-       cc      = tny_header_get_cc (header);
-       bcc     = tny_header_get_bcc (header);
-       subject = tny_header_get_subject (header);
+       to      = tny_header_dup_to (header);
+       cc      = tny_header_dup_cc (header);
+       bcc     = tny_header_dup_bcc (header);
+       subject = tny_header_dup_subject (header);
        priority_flags = tny_header_get_priority (header);
 
        if (to)
@@ -1234,8 +1250,8 @@ set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
                gtk_widget_show_all (priv->attachments_caption);
        }
        get_related_images (self, msg);
-       update_last_cid (self, priv->attachments);
-       update_last_cid (self, priv->images);
+       update_next_cid (self, priv->attachments);
+       update_next_cid (self, priv->images);
        replace_with_images (self, priv->images);
 
        if (preserve_is_rich && !is_html) {
@@ -1289,6 +1305,11 @@ set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
                }
                g_object_unref (msg_folder);
        }
+
+       g_free (to);
+       g_free (subject);
+       g_free (cc);
+       g_free (bcc);
 }
 
 static void
@@ -1561,8 +1582,6 @@ modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean pre
        g_object_unref (menu_rules_group);
        g_object_unref (toolbar_rules_group);
        g_object_unref (clipboard_rules_group);
-       modest_msg_edit_window_clipboard_owner_change (NULL, NULL, MODEST_MSG_EDIT_WINDOW (obj));
-
        set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
 
        text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
@@ -1582,7 +1601,9 @@ modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean pre
                                  "account_removed",
                                  G_CALLBACK(on_account_removed),
                                  obj);
-       
+
+       modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
+
        return (ModestWindow*) obj;
 }
 
@@ -2135,9 +2156,21 @@ static TnyStream* create_stream_for_uri (const gchar* uri)
        GnomeVFSHandle *handle = NULL;
        GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
        if (test == GNOME_VFS_OK) {
-               /* Create the tinymail stream: */
-               /* Presumably tinymai will call gnome_vfs_close (handle) later. */
-               result = TNY_STREAM (tny_vfs_stream_new (handle));
+               TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
+               /* Streams over OBEX (Bluetooth) are not seekable but
+                * we expect them to be (we might need to read them
+                * several times). So if this is a Bluetooth URI just
+                * read the whole file into memory (this is not a fast
+                * protocol so we can assume that these files are not
+                * going to be very big) */
+               if (g_ascii_strncasecmp (uri, "obex://", 7) == 0) {
+                       TnyStream *memstream = tny_camel_mem_stream_new ();
+                       tny_stream_write_to_stream (vfssstream, memstream);
+                       g_object_unref (vfssstream);
+                       result = memstream;
+               } else {
+                       result = vfssstream;
+               }
        }
        
        return result;
@@ -2190,6 +2223,7 @@ modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
                        GnomeVFSURI *vfs_uri;
                        guint64 stream_size;
 
+                       gnome_vfs_close (handle);
                        vfs_uri = gnome_vfs_uri_new (uri);
 
                        escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
@@ -2207,12 +2241,22 @@ modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
                                (modest_runtime_get_platform_factory ());
                                
                        TnyStream *stream = create_stream_for_uri (uri);
+
+                       if (stream == NULL) {
+
+                               modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
+                               
+                               g_object_unref (mime_part);
+                               gnome_vfs_file_info_unref (info);
+                               continue;
+                       }
+
                        tny_mime_part_construct (mime_part, stream, mime_type, "base64");
                        
-                       content_id = g_strdup_printf ("%d", priv->last_cid);
+                       content_id = g_strdup_printf ("%d", priv->next_cid);
                        tny_mime_part_set_content_id (mime_part, content_id);
                        g_free (content_id);
-                       priv->last_cid++;
+                       priv->next_cid++;
                        
                        basename = g_path_get_basename (filename);
                        tny_mime_part_set_filename (mime_part, basename);
@@ -2251,6 +2295,7 @@ modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
        dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
        gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
        gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
 
        response = gtk_dialog_run (GTK_DIALOG (dialog));
        switch (response) {
@@ -2296,6 +2341,7 @@ modest_msg_edit_window_attach_file_one (
                GnomeVFSFileInfo *info;
                GnomeVFSURI *vfs_uri;
 
+               gnome_vfs_close (handle);
                vfs_uri = gnome_vfs_uri_new (uri);
                
 
@@ -2313,16 +2359,24 @@ modest_msg_edit_window_attach_file_one (
                        mime_type = gnome_vfs_file_info_get_mime_type (info);
                mime_part = tny_platform_factory_new_mime_part
                        (modest_runtime_get_platform_factory ());
-               stream = TNY_STREAM (tny_vfs_stream_new (handle));
+               stream = create_stream_for_uri (uri);
                
-               tny_mime_part_construct (mime_part, stream, mime_type, "base64");
+               if (stream == NULL) {
+
+                       modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
+
+                       g_object_unref (mime_part);
+                       gnome_vfs_file_info_unref (info);
+                       return;
+               }
 
+               tny_mime_part_construct (mime_part, stream, mime_type, "base64");
                g_object_unref (stream);
                
-               content_id = g_strdup_printf ("%d", priv->last_cid);
+               content_id = g_strdup_printf ("%d", priv->next_cid);
                tny_mime_part_set_content_id (mime_part, content_id);
                g_free (content_id);
-               priv->last_cid++;
+               priv->next_cid++;
                
                basename = g_path_get_basename (filename);
                tny_mime_part_set_filename (mime_part, basename);
@@ -2373,7 +2427,7 @@ modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
                        if (TNY_IS_MSG (part)) {
                                TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
                                if (header) {
-                                       filename = g_strdup (tny_header_get_subject (header));
+                                       filename = tny_header_dup_subject (header);
                                        g_object_unref (header);
                                }
                                if (filename == NULL) {
@@ -2387,7 +2441,7 @@ modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
                        filename = g_strdup ("");
                }
                message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
-                                                   (tny_list_get_length (att_list) == 1)), filename);
+                                                   tny_list_get_length (att_list)), filename);
                g_free (filename);
                confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
                g_free (message);
@@ -2748,6 +2802,7 @@ modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
                        break;
                }
                modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
+               text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
        }
 }
 
@@ -2773,6 +2828,8 @@ modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
        priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
        
        dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
+       modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
+                                    GTK_WINDOW(dialog));
 
        /* First we get the currently selected font information */
        wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
@@ -3135,6 +3192,7 @@ modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
        if (!GTK_WIDGET_VISIBLE (window))
                return;
 
+       g_object_ref (window);
        text = gtk_clipboard_wait_for_text (selection_clipboard);
 
        if (priv->clipboard_text != NULL) {
@@ -3142,8 +3200,37 @@ modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
        }
        priv->clipboard_text = text;
 
-       modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
+       if (GTK_WIDGET_VISIBLE (window)) {
+               modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
+       }
+       g_object_unref (window);
+}
+
+static gboolean clipboard_owner_change_idle (gpointer userdata)
+{
+       ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
+       ModestMsgEditWindowPrivate *priv;
+
+       gdk_threads_enter ();
+       g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
+       priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+
+       priv->clipboard_owner_idle = 0;
+       modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
+       gdk_threads_leave ();
+
+       return FALSE;
+}
+
+static void
+modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
+{
+       ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
+       if (priv->clipboard_owner_idle == 0) {
+               priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
+       }
 }
+
 static void 
 subject_field_move_cursor (GtkEntry *entry,
                           GtkMovementStep step,