* update for the changes in the APIs, as well as for *some* compile
[modest] / src / hildon / modest-ui-message-editor.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30
31 #include <gtk/gtk.h>
32 #include <glade/glade.h>
33 #include <glib/gi18n.h>
34 #include <string.h>
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif /*HAVE_CONFIG_H*/
39
40 #include <hildon-widgets/hildon-window.h>
41 #include <hildon-widgets/hildon-program.h>
42
43 /* TODO: put in auto* */
44 #include <tny-text-buffer-stream.h>
45 #include <tny-msg-folder.h>
46
47 #include "../modest-ui.h"
48 #include "../modest-window-mgr.h"
49 #include "../modest-account-mgr.h"
50 #include "../modest-account-mgr.h"
51 #include "../modest-identity-mgr.h"
52
53 #include "../modest-tny-account-store.h"
54 #include "../modest-tny-folder-tree-view.h"
55 #include "../modest-tny-header-tree-view.h"
56 #include "../modest-tny-msg-view.h"
57 #include "../modest-tny-transport-actions.h"
58 #include "../modest-tny-store-actions.h"
59
60 #include "../modest-text-utils.h"
61 #include "../modest-tny-msg-actions.h"
62
63 #include "../modest-tny-attachment.h"
64
65 #include "../modest-editor-window.h"
66
67 #include "modest-ui-glade.h"
68 #include "modest-ui-wizard.h"
69
70 #include "modest-ui-message-editor.h"
71
72
73 static void on_attach_button_clicked (GtkWidget *widget, ModestEditorWindow *modest_editwin);
74
75 static void on_send_button_clicked (GtkWidget *widget, ModestEditorWindow *modest_editwin);
76
77
78 typedef struct {
79         ModestUI *modest_ui;
80         ModestEditorWindow *edit_win;
81         GladeXML *glade_xml;
82         GList *attachments;
83 } EditWinData;
84
85
86 static gboolean close_edit_confirm_dialog(ModestEditorWindow *edit_win)
87 {
88         GtkWidget *mdialog;
89         gint res;
90
91         mdialog = gtk_message_dialog_new(GTK_WINDOW(edit_win->window),
92                         GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
93                         GTK_MESSAGE_QUESTION,
94                         GTK_BUTTONS_YES_NO,
95                         _("Message was modified.\nDiscard Changes?"));
96         gtk_widget_show_all (mdialog);
97
98         res=gtk_dialog_run(GTK_DIALOG(mdialog));
99         gtk_widget_destroy (mdialog);
100         if (res == GTK_RESPONSE_YES)
101                 return TRUE;
102         else
103                 return FALSE;
104 }
105
106 static void
107 close_edit_window (GtkWidget *win, GdkEvent *event, gpointer data)
108 {
109         ModestEditorWindow *edit_win;
110         ModestUIPrivate *priv;
111         EditWinData *win_data;
112
113         edit_win = (ModestEditorWindow *)data;
114         win_data = modest_editor_window_get_data(edit_win);
115         priv = MODEST_UI_GET_PRIVATE(win_data->modest_ui);
116
117         if (modest_editor_window_get_modified(edit_win)) {
118                 if (close_edit_confirm_dialog(edit_win)) {
119                         gtk_widget_hide (GTK_WIDGET(edit_win->window));
120                         modest_window_mgr_unregister(priv->modest_window_mgr, G_OBJECT(edit_win->window));
121                         hildon_program_remove_window (priv->program, HILDON_WINDOW (edit_win->window));
122                         g_object_unref(edit_win);
123                         g_message("closing window");
124                 } else {
125                         g_message("not closing window");
126                 }
127         } else {
128                 gtk_widget_hide (GTK_WIDGET(edit_win->window));
129                 modest_window_mgr_unregister(priv->modest_window_mgr, G_OBJECT (edit_win->window));
130                 hildon_program_remove_window (priv->program, HILDON_WINDOW (edit_win->window));
131                 g_object_unref(edit_win);
132                 g_message("closing window");
133         }
134 }
135
136
137 GtkContainer
138 *modest_ui_new_editor_window (ModestUI *modest_ui, gpointer *user_data)
139 {
140         GtkWidget       *top_container;
141         GladeXML                *glade_xml;
142         EditWinData             *win_data;
143
144         glade_xml = glade_xml_new(MODEST_GLADE, "new_mail", NULL);
145         if (!glade_xml)
146                 return NULL;
147
148         win_data = g_malloc(sizeof(EditWinData));
149         win_data->modest_ui = modest_ui;
150         win_data->glade_xml = glade_xml;
151         win_data->attachments = NULL;
152
153         *user_data = win_data;
154
155         top_container = glade_xml_get_widget(glade_xml, "new_mail");
156         if (!top_container) {
157                 g_warning ("Could not create window\n");
158                 g_object_unref(G_OBJECT(glade_xml));
159                 return NULL;
160         }
161         
162         return GTK_CONTAINER(top_container);
163 }
164
165
166 gboolean
167 modest_ui_editor_window_set_to_header(const gchar *to, gpointer window_data)
168 {
169         GladeXML *glade_xml;
170         GtkWidget *w;
171         EditWinData *win_data;
172
173         win_data = (EditWinData *)window_data;
174         glade_xml = win_data->glade_xml;
175         w = glade_xml_get_widget(glade_xml, "to_entry");
176         gtk_entry_set_text(GTK_ENTRY(w), to);
177
178         return TRUE;
179 }
180
181
182 gboolean
183 modest_ui_editor_window_set_cc_header(const gchar *cc, gpointer window_data)
184 {
185         GladeXML *glade_xml;
186         // GtkWidget *w;
187         EditWinData *win_data;
188
189         win_data = (EditWinData *)window_data;
190         glade_xml = win_data->glade_xml;
191 /*
192         w = glade_xml_get_widget(glade_xml, "cc_entry");
193         gtk_entry_set_text(GTK_ENTRY(w), cc);
194 */
195         return TRUE;
196 }
197
198
199 gboolean
200 modest_ui_editor_window_set_bcc_header(const gchar *bcc, gpointer window_data)
201 {
202         GladeXML *glade_xml;
203         // GtkWidget *w;
204         EditWinData *win_data;
205
206         win_data = (EditWinData *)window_data;
207         glade_xml = win_data->glade_xml;
208 /*
209         w = glade_xml_get_widget(glade_xml, "bcc_entry");
210         gtk_entry_set_text(GTK_ENTRY(w), bcc);
211 */
212         return TRUE;
213 }
214
215
216 gboolean
217 modest_ui_editor_window_set_subject_header(const gchar *subject, gpointer window_data)
218 {
219         GladeXML *glade_xml;
220         GtkWidget *w;
221         EditWinData *win_data;
222
223         win_data = (EditWinData *)window_data;
224         glade_xml = win_data->glade_xml;
225
226         w = glade_xml_get_widget(glade_xml, "subject_entry");
227         gtk_entry_set_text(GTK_ENTRY(w), subject);
228
229         return TRUE;
230 }
231
232
233 gboolean
234 modest_ui_editor_window_set_body(const gchar *body, gpointer window_data)
235 {
236         GladeXML *glade_xml;
237         GtkWidget *body_view;
238         GtkTextBuffer *buf;
239         EditWinData *win_data;
240
241         win_data = (EditWinData *)window_data;
242         glade_xml = win_data->glade_xml;
243
244         body_view = glade_xml_get_widget(glade_xml, "body_view");
245         buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(body_view));
246
247         gtk_text_buffer_set_text(GTK_TEXT_BUFFER(buf), body, -1);
248
249         return TRUE;
250 }
251
252
253 gboolean
254 modest_ui_editor_window_update_attachments(gpointer window_data)
255 {
256         GladeXML *glade_xml;
257         
258         glade_xml = ((EditWinData *) window_data)->glade_xml;
259
260         //body_view = glade_xml_get_widget(glade_xml, "body_view");
261         
262         return TRUE;
263 }
264
265
266 static
267 void on_editor_entry_changed(GtkEditable *editable,
268                                             gpointer     user_data)
269 {
270         GtkWidget *edit_win;
271         EditWinData *windata;
272
273         edit_win = (GtkWidget *)user_data;
274         windata = (EditWinData *)modest_editor_window_get_data(MODEST_EDITOR_WINDOW(edit_win));
275
276         modest_editor_window_set_modified(MODEST_EDITOR_WINDOW(edit_win), TRUE);
277 }
278
279
280 static
281 void on_editor_buffer_changed (GtkTextBuffer *textbuffer,
282                                             gpointer       user_data)
283 {
284         GtkWidget *edit_win;
285         
286         edit_win = (GtkWidget *)user_data;
287         modest_editor_window_set_modified(MODEST_EDITOR_WINDOW(edit_win), TRUE);
288 }
289
290
291 static void
292 new_editor_with_presets (ModestUI *modest_ui, const gchar *to_header,
293                                                         const gchar *cc_header, const gchar *bcc_header,
294                                                         const gchar *subject_header, const gchar *body,
295                             const GList *attachments)
296 {
297         ModestEditorWindow *edit_win;
298         GladeXML *glade_xml;
299         GtkWidget *btn, *w;
300         GtkTextBuffer *buf;
301         EditWinData *windata;
302         ModestUIPrivate *priv;
303         GtkWidget *toolbar, *menubar, *menu, *menu_item;
304
305         g_return_if_fail (modest_ui);
306
307         edit_win = MODEST_EDITOR_WINDOW (modest_editor_window_new(modest_ui));
308         windata = (EditWinData *)modest_editor_window_get_data(MODEST_EDITOR_WINDOW(edit_win));
309         g_return_if_fail(windata);
310
311         glade_xml = windata->glade_xml;
312         btn = glade_xml_get_widget (glade_xml, "toolb_send");
313         g_signal_connect (btn, "clicked", G_CALLBACK(on_send_button_clicked),
314                           edit_win);
315         btn = glade_xml_get_widget (glade_xml, "toolb_attach");
316         g_signal_connect (btn, "clicked", G_CALLBACK(on_attach_button_clicked),
317                           edit_win);
318
319         w = glade_xml_get_widget (glade_xml, "to_entry");
320         g_signal_connect(w, "changed", G_CALLBACK(on_editor_entry_changed), edit_win);
321         w = glade_xml_get_widget (glade_xml, "subject_entry");
322         g_signal_connect(w, "changed", G_CALLBACK(on_editor_entry_changed), edit_win);
323         w = glade_xml_get_widget (glade_xml, "body_view");
324         buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w));
325         g_signal_connect(buf, "changed", G_CALLBACK(on_editor_buffer_changed), edit_win);
326
327         g_signal_connect (edit_win->window, "destroy-event", G_CALLBACK(close_edit_window),
328                           edit_win);
329         g_signal_connect (edit_win->window, "delete-event", G_CALLBACK(close_edit_window),
330                           edit_win);
331
332         priv = MODEST_UI_GET_PRIVATE(modest_ui);
333         
334         if (strlen(subject_header) > 0)
335                 gtk_window_set_title (GTK_WINDOW(edit_win->window), subject_header);
336         else
337                 gtk_window_set_title (GTK_WINDOW(edit_win->window), _("Untitled"));
338                 
339         modest_window_mgr_register(priv->modest_window_mgr, G_OBJECT(edit_win->window), MODEST_EDIT_WINDOW, 0);
340
341         modest_editor_window_set_to_header(MODEST_EDITOR_WINDOW(edit_win), to_header);
342         modest_editor_window_set_cc_header(MODEST_EDITOR_WINDOW(edit_win), cc_header);
343         modest_editor_window_set_bcc_header(MODEST_EDITOR_WINDOW(edit_win), bcc_header);
344         modest_editor_window_set_subject_header(MODEST_EDITOR_WINDOW(edit_win), subject_header);
345         modest_editor_window_set_body(MODEST_EDITOR_WINDOW(edit_win), body);
346         modest_editor_window_set_attachments(MODEST_EDITOR_WINDOW(edit_win), attachments);
347
348         modest_editor_window_set_modified(MODEST_EDITOR_WINDOW(edit_win), FALSE);
349
350         menu = gtk_menu_new();
351         menu_item = glade_xml_get_widget (priv->glade_xml, "menuitem5");
352         gtk_widget_reparent(menu_item, menu);
353         menu_item = glade_xml_get_widget (priv->glade_xml, "menuitem13");
354         gtk_widget_reparent(menu_item, menu);
355         menu_item = glade_xml_get_widget (priv->glade_xml, "menuitem22");
356         gtk_widget_reparent(menu_item, menu);
357         menu_item = glade_xml_get_widget (priv->glade_xml, "menuitem27");
358         gtk_widget_reparent(menu_item, menu);
359         menu_item = glade_xml_get_widget (priv->glade_xml, "menuitem29");
360         gtk_widget_reparent(menu_item, menu);
361         menu_item = glade_xml_get_widget (priv->glade_xml, "menuitem34");
362         gtk_widget_reparent(menu_item, menu);
363         menu_item = glade_xml_get_widget (priv->glade_xml, "menuitem41");
364         gtk_widget_reparent(menu_item, menu);
365
366         hildon_window_set_menu (HILDON_WINDOW (edit_win->window), GTK_MENU(menu));
367
368         toolbar = glade_xml_get_widget (priv->glade_xml, "toolbar2");
369         gtk_widget_hide (toolbar);
370         g_object_ref (toolbar);
371         gtk_container_remove (GTK_CONTAINER (glade_xml_get_widget (priv->glade_xml, 
372                               "new_mail_top_container")), toolbar);
373         hildon_window_add_toolbar (HILDON_WINDOW (edit_win->window), GTK_TOOLBAR (toolbar));
374         gtk_widget_show_all (GTK_WIDGET (edit_win->window));
375
376         while (gtk_events_pending ())
377                 gtk_main_iteration ();
378         
379         toolbar = glade_xml_get_widget (priv->glade_xml, "toolbar2");
380         gtk_widget_hide (toolbar);
381         
382         menubar = glade_xml_get_widget (priv->glade_xml, "menubar2");
383         gtk_widget_hide (GTK_WIDGET(menubar));
384         
385         hildon_program_add_window (priv->program, HILDON_WINDOW (edit_win->window));
386 }
387
388
389 void
390 on_new_mail_clicked (GtkWidget *widget, gpointer user_data)
391 {
392         ModestUI *modest_ui = (ModestUI *) user_data;
393
394         new_editor_with_presets(modest_ui, "", "", "", "", "", NULL);
395 }
396
397 void
398 ui_on_mailto_clicked (GtkWidget *widget, const gchar *uri, gpointer user_data)
399 {
400         ModestUI *modest_ui = (ModestUI *) user_data;
401         
402         new_editor_with_presets(modest_ui, uri, "", "", "", "", NULL);
403 }
404
405
406 void
407 quoted_send_msg (ModestUI *modest_ui, quoted_send_type qstype)
408 {
409         GtkTreeSelection *sel;
410         GtkTreeModel *model;
411         GtkTreeIter iter;
412
413         TnyMsgHeaderIface *header;
414
415         ModestTnyHeaderTreeView *header_view;
416         ModestTnyMsgView *msg_view;
417         ModestUIPrivate *priv;
418
419         const TnyMsgIface *msg;
420         const TnyMsgFolderIface *folder;
421         GString *re_sub;
422         const gchar *subject, *from;
423         gchar *unquoted, *quoted;
424         time_t sent_date;
425         gint line_limit = 76;
426         
427         GList *attachments = NULL;
428
429         g_return_if_fail (modest_ui);
430
431         priv = MODEST_UI_GET_PRIVATE(modest_ui);
432
433         msg_view = MODEST_TNY_MSG_VIEW(priv->message_view);
434         g_return_if_fail (msg_view);
435
436         header_view = MODEST_TNY_HEADER_TREE_VIEW(priv->header_view);
437         g_return_if_fail (header_view);
438
439         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
440         g_return_if_fail (sel);
441
442         if (!gtk_tree_selection_get_selected (sel, &model, &iter)) {
443                 g_warning("nothing to reply to");
444                 return;
445         }
446
447         gtk_tree_model_get (model, &iter,
448                             TNY_MSG_HEADER_LIST_MODEL_INSTANCE_COLUMN,
449                             &header, -1);
450
451         if (!header) {
452                 g_warning("no header");
453                 return;
454         }
455
456         folder = tny_msg_header_iface_get_folder (TNY_MSG_HEADER_IFACE(header));
457         if (!folder) {
458                 g_warning ("cannot find folder");
459                 return;
460         }
461
462         msg = tny_msg_folder_iface_get_message (TNY_MSG_FOLDER_IFACE(folder), header);
463         if (!msg) {
464                 g_warning ("cannot find msg");
465                 return;
466         }
467
468         subject = tny_msg_header_iface_get_subject(header);
469         re_sub = g_string_new(subject);
470         /* FIXME: honor replyto, cc */
471         from = tny_msg_header_iface_get_from(header);
472         sent_date = tny_msg_header_iface_get_date_sent(header);
473
474         unquoted = modest_tny_msg_view_get_selected_text(msg_view);
475         quoted = modest_tny_msg_actions_quote(msg, from, sent_date, line_limit, unquoted);
476
477         switch (qstype) {
478                 case QUOTED_SEND_REPLY:
479                         g_string_prepend(re_sub, _("Re: "));
480                         new_editor_with_presets(modest_ui, from, /* cc */ "", /* bcc */ "", re_sub->str, quoted, attachments);
481                         break;
482                 case QUOTED_SEND_FORWARD:
483                         attachments = modest_tny_attachment_new_list_from_msg(msg, FALSE);
484                         g_string_prepend(re_sub, _("Fwd: "));
485                         new_editor_with_presets(modest_ui, /* from */ "", /* cc */ "", /* bcc */ "", re_sub->str, quoted, attachments);
486                         break;
487                 case QUOTED_SEND_FORWARD_ATTACHED:
488                         attachments = modest_tny_attachment_new_list_from_msg(msg, TRUE);
489                         g_string_prepend(re_sub, _("Fwd: "));
490                         new_editor_with_presets(modest_ui, /* from */ "", /* cc */ "", /* bcc */ "", re_sub->str, "", attachments);
491                         break;
492                 default:
493                         break;
494         }
495         g_free(quoted);
496         g_free(unquoted);
497         g_string_free(re_sub, TRUE);
498 }
499
500
501 static void
502 on_attach_button_clicked (GtkWidget *widget, ModestEditorWindow *modest_editwin)
503 {
504         /* open file selector */
505         GtkWidget *dialog;
506         ModestTnyAttachment *attachment;
507         gchar *filename = NULL;
508         
509         dialog = gtk_file_chooser_dialog_new ("Open File",
510                                                                                   GTK_WINDOW(modest_editwin->window),
511                                                                                   GTK_FILE_CHOOSER_ACTION_OPEN,
512                                                                                   GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
513                                                                                   GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
514                                                                                   NULL);
515
516         if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
517         {
518
519                 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
520                 printf ("file:%s\n", filename);
521         }
522         gtk_widget_destroy (dialog);
523       
524         /* check file */
525         if (!filename)
526                 return;
527         
528         attachment = modest_tny_attachment_new();
529         modest_tny_attachment_set_filename(attachment, filename);
530         modest_tny_attachment_guess_mime_type(attachment);
531         
532         modest_editor_window_attach_file(modest_editwin, attachment);
533         
534         g_free (filename);
535 }
536
537
538 static void
539 on_send_button_clicked (GtkWidget *widget, ModestEditorWindow *modest_editwin)
540 {
541         ModestTnyTransportActions *actions;
542         ModestUI *modest_ui;
543         ModestUIPrivate *priv;
544         GtkWidget *to_entry, *subject_entry, *body_view;
545         const gchar *to, *subject, *email_from;
546         gchar *body;
547         GtkTextIter start, end;
548         GtkTextBuffer *buf;
549         TnyAccountStoreIface *account_store;
550         TnyListIface *transport_accounts;
551         TnyIteratorIface *iter;
552         TnyTransportAccountIface *transport_account;
553         ModestIdentityMgr *id_mgr;
554         EditWinData *win_data;
555         GList * attachments;
556
557
558         win_data = modest_editor_window_get_data(modest_editwin);
559         modest_ui = win_data->modest_ui;
560
561         g_return_if_fail (modest_ui);
562
563         actions = MODEST_TNY_TRANSPORT_ACTIONS
564                 (modest_tny_transport_actions_new ());
565
566         priv = MODEST_UI_GET_PRIVATE(modest_ui);
567
568         account_store = priv->account_store;
569
570         transport_accounts = tny_list_new ();
571         tny_account_store_iface_get_accounts (priv->account_store,
572                                               transport_accounts,
573                                               TNY_ACCOUNT_STORE_IFACE_TRANSPORT_ACCOUNTS);      
574         tny_list_iface_create_iterator (transport_accounts);
575
576         iter = tny_list_iface_create_iterator(transport_accounts);
577         if (!tny_iterator_iface_first(iter))   {
578                 g_message ("cannot send message: no transport account defined");
579                 return;
580         } else /* take the first one! */
581                 transport_account =
582                         TNY_TRANSPORT_ACCOUNT_IFACE(tny_iterator_iface_current(iter));
583         g_object_unref (iter);
584         g_object_unref (transport_accounts);
585         
586         to_entry      = glade_xml_get_widget (win_data->glade_xml, "to_entry");
587         subject_entry = glade_xml_get_widget (win_data->glade_xml, "subject_entry");
588         body_view     = glade_xml_get_widget (win_data->glade_xml, "body_view");
589
590         to      = gtk_entry_get_text (GTK_ENTRY(to_entry));
591         subject = gtk_entry_get_text (GTK_ENTRY(subject_entry));
592
593         buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(body_view));
594         gtk_text_buffer_get_bounds (buf, &start, &end);
595         body    = gtk_text_buffer_get_text (buf, &start, &end, FALSE);
596
597         id_mgr = priv->modest_id_mgr;
598         email_from = modest_identity_mgr_get_identity_string(id_mgr,
599                                                              MODEST_IDENTITY_DEFAULT_IDENTITY,
600                                                              MODEST_IDENTITY_EMAIL, NULL);
601         attachments = modest_editor_window_get_attachments(modest_editwin);
602         if (!email_from)
603                 email_from = "";
604         
605         g_message("sending \"%s\" %s ==> %s", subject, email_from, to);
606
607         modest_tny_transport_actions_send_message (actions,
608                                                    transport_account,
609                                                    email_from,
610                                                    to, "", "", subject,
611                                                    body,
612                                                    attachments);
613
614         modest_editor_window_set_attachments(modest_editwin, NULL); /* This unrefs them, too. */
615         g_free (body);
616         g_object_unref (G_OBJECT(actions));
617
618         gtk_widget_hide (GTK_WIDGET(modest_editwin->window));
619         modest_window_mgr_unregister(priv->modest_window_mgr, G_OBJECT(modest_editwin));
620         if (G_IS_OBJECT(modest_editwin)) {
621                 g_object_unref(modest_editwin);
622         } else
623                 g_warning("editor window has vanished!");
624 }