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