19b2dce2e6e3272e6dae31a07f307ca261ade67c
[modest] / src / gnome / modest-msg-edit-window.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 #include <glib/gi18n.h>
30 #include <string.h>
31 #include <tny-account-store.h>
32 #include <tny-simple-list.h>
33 #include <modest-conf.h>
34 #include <modest-runtime.h>
35 #include <modest-tny-msg.h>
36
37 #include <widgets/modest-window-priv.h>
38 #include <widgets/modest-msg-edit-window.h>
39 #include <widgets/modest-msg-edit-window-ui.h>
40 #include <widgets/modest-combo-box.h>
41 #include <widgets/modest-attachments-view.h>
42
43 #include <modest-widget-memory.h>
44 #include <modest-account-mgr-helpers.h>
45 #include <modest-tny-folder.h>
46 #include <gtkhtml/gtkhtml.h>
47 #include "modest-msg-edit-window-ui-dimming.h"
48 #include <modest-platform.h>
49 #include <libgnomevfs/gnome-vfs-mime-utils.h>
50 #include <libgnomevfs/gnome-vfs.h>
51 #include <tny-vfs-stream.h>
52
53 static void  modest_msg_edit_window_class_init   (ModestMsgEditWindowClass *klass);
54 static void  modest_msg_edit_window_init         (ModestMsgEditWindow *obj);
55 static void  modest_msg_edit_window_finalize     (GObject *obj);
56
57 static void  modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
58                                                             ModestMsgEditWindow *window);
59 static void update_next_cid (ModestMsgEditWindow *self, TnyList *attachments);
60
61 /* list my signals */
62 enum {
63         /* MY_SIGNAL_1, */
64         /* MY_SIGNAL_2, */
65         LAST_SIGNAL
66 };
67
68 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
69 struct _ModestMsgEditWindowPrivate {
70
71         GtkWidget   *toolbar;
72         GtkWidget   *menubar;
73
74         GtkWidget   *msg_body;
75         
76         ModestPairList *from_field_protos;
77         GtkWidget   *from_field;
78         
79         GtkWidget   *to_field;
80         GtkWidget   *cc_field;
81         GtkWidget   *bcc_field;
82         GtkWidget   *subject_field;
83
84         GtkWidget   *attachments_view;
85         TnyList     *attachments;
86         guint       next_cid;
87
88         TnyMsg      *draft_msg;
89         TnyMsg      *outbox_msg;
90         gchar       *msg_uid;
91
92         gboolean    sent;
93 };
94
95 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
96                                                     MODEST_TYPE_MSG_EDIT_WINDOW, \
97                                                     ModestMsgEditWindowPrivate))
98 /* globals */
99 static GtkWindowClass *parent_class = NULL;
100
101 /* uncomment the following if you have defined any signals */
102 /* static guint signals[LAST_SIGNAL] = {0}; */
103
104 GType
105 modest_msg_edit_window_get_type (void)
106 {
107         static GType my_type = 0;
108         if (!my_type) {
109                 static const GTypeInfo my_info = {
110                         sizeof(ModestMsgEditWindowClass),
111                         NULL,           /* base init */
112                         NULL,           /* base finalize */
113                         (GClassInitFunc) modest_msg_edit_window_class_init,
114                         NULL,           /* class finalize */
115                         NULL,           /* class data */
116                         sizeof(ModestMsgEditWindow),
117                         1,              /* n_preallocs */
118                         (GInstanceInitFunc) modest_msg_edit_window_init,
119                         NULL
120                 };
121                 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
122                                                   "ModestMsgEditWindow",
123                                                   &my_info, 0);
124         }
125         return my_type;
126 }
127
128
129 static void
130 save_state (ModestWindow *self)
131 {
132         modest_widget_memory_save (modest_runtime_get_conf (),
133                                     G_OBJECT(self), "modest-edit-msg-window");
134 }
135
136
137 static void
138 restore_settings (ModestMsgEditWindow *self)
139 {
140         modest_widget_memory_restore (modest_runtime_get_conf (),
141                                       G_OBJECT(self), "modest-edit-msg-window");
142 }
143
144 static void
145 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
146 {
147         GObjectClass *gobject_class;
148         ModestWindowClass *modest_window_class;
149         
150         gobject_class = (GObjectClass*) klass;
151         modest_window_class = (ModestWindowClass*) klass;
152
153         parent_class            = g_type_class_peek_parent (klass);
154         gobject_class->finalize = modest_msg_edit_window_finalize;
155
156         g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
157
158         modest_window_class->save_state_func = save_state;
159 }
160
161 static void
162 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
163 {
164         ModestMsgEditWindowPrivate *priv;
165         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
166
167         priv->toolbar       = NULL;
168         priv->menubar       = NULL;
169         priv->msg_body      = NULL;
170         priv->from_field    = NULL;
171         priv->to_field      = NULL;
172         priv->cc_field      = NULL;
173         priv->bcc_field     = NULL;
174         priv->subject_field = NULL;
175         priv->attachments_view = NULL;
176         priv->attachments = TNY_LIST (tny_simple_list_new ());
177         priv->sent          = FALSE;
178         priv->next_cid      = 0;
179         priv->draft_msg = NULL;
180         priv->outbox_msg = NULL;
181         priv->msg_uid = NULL;
182 }
183
184 /** 
185  * @result: A ModestPairList, which must be freed with modest_pair_list_free().
186  */
187 static ModestPairList*
188 get_transports (void)
189 {
190         ModestAccountMgr *account_mgr;
191         GSList *transports = NULL;
192         GSList *cursor, *accounts;
193         
194         account_mgr = modest_runtime_get_account_mgr();
195         cursor = accounts = modest_account_mgr_account_names (account_mgr, TRUE);
196         while (cursor) {
197                 gchar *account_name = cursor->data ? g_strdup((gchar*)cursor->data) : NULL;
198                 gchar *from_string  = modest_account_mgr_get_from_string (account_mgr,
199                                                                           account_name);
200                 if (!from_string)  {
201                         /* something went wrong: ignore this one */
202                         g_free (account_name);
203                         cursor->data = NULL;
204                 } else {
205                         ModestPair *pair;
206                         pair = modest_pair_new ((gpointer) account_name,
207                                                 (gpointer) from_string , TRUE);
208                         transports = g_slist_prepend (transports, pair);
209                 } /* don't free account name; it's freed when the transports list is freed */
210                 cursor = cursor->next;
211         }
212         g_slist_free (accounts);
213         return transports;
214 }
215
216
217 static void
218 on_from_combo_changed (ModestComboBox *combo, ModestWindow *win)
219 {
220         modest_window_set_active_account (
221                 win, modest_combo_box_get_active_id(combo));
222 }
223
224
225
226 static void
227 init_window (ModestMsgEditWindow *obj, const gchar* account)
228 {
229         GtkWidget *to_button, *cc_button, *bcc_button, *add_attachment_button; 
230         GtkWidget *header_table;
231         GtkWidget *main_vbox;
232         GtkWidget *msg_vbox;
233         GtkWidget *scrolled_window;
234         ModestMsgEditWindowPrivate *priv;
235         ModestWindowPrivate *parent_priv;
236         
237         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
238         parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
239
240         to_button     = gtk_button_new_with_label (_("To..."));
241         cc_button     = gtk_button_new_with_label (_("Cc..."));
242         bcc_button    = gtk_button_new_with_label (_("Bcc..."));
243         add_attachment_button = gtk_button_new_with_label (_("Attach..."));
244         
245         /* Note: This ModestPairList* must exist for as long as the combo
246          * that uses it, because the ModestComboBox uses the ID opaquely, 
247          * so it can't know how to manage its memory. */ 
248         priv->from_field_protos = get_transports ();
249         priv->from_field    = modest_combo_box_new (priv->from_field_protos, g_str_equal);
250         
251         if (account) {
252                 modest_combo_box_set_active_id (MODEST_COMBO_BOX(priv->from_field),
253                                                 (gpointer)account);
254                 modest_window_set_active_account (MODEST_WINDOW(obj), account);
255         }
256         /* auto-update the active account */
257         g_signal_connect (G_OBJECT(priv->from_field), "changed", G_CALLBACK(on_from_combo_changed), obj);
258         
259         priv->to_field      = gtk_entry_new_with_max_length (80);
260         priv->cc_field      = gtk_entry_new_with_max_length (80);
261         priv->bcc_field     = gtk_entry_new_with_max_length (80);
262         priv->subject_field = gtk_entry_new_with_max_length (80);
263         priv->attachments_view = modest_attachments_view_new (NULL);
264         
265         header_table = gtk_table_new (6,2, FALSE);
266         
267         gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("From:")),
268                           0,1,0,1, GTK_FILL, 0, 0, 0);
269         gtk_table_attach (GTK_TABLE(header_table), to_button,     0,1,1,2, GTK_FILL, 0, 0, 0);
270         gtk_table_attach (GTK_TABLE(header_table), cc_button,     0,1,2,3, GTK_FILL, 0, 0, 0);
271         gtk_table_attach (GTK_TABLE(header_table), bcc_button,    0,1,3,4, GTK_FILL, 0, 0, 0);
272         gtk_table_attach (GTK_TABLE(header_table), gtk_label_new (_("Subject:")),
273                           0,1,4,5, GTK_FILL, 0, 0, 0);
274         gtk_table_attach (GTK_TABLE(header_table), add_attachment_button, 0, 1, 5, 6, GTK_FILL, 0, 0, 0);
275
276         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->from_field,   1,2,0,1);
277         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->to_field,     1,2,1,2);
278         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->cc_field,     1,2,2,3);
279         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->bcc_field,    1,2,3,4);
280         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->subject_field,1,2,4,5);
281         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->attachments_view,1,2,5,6);
282
283         priv->msg_body = gtk_html_new ();
284         gtk_html_load_empty (GTK_HTML (priv->msg_body));
285         gtk_html_set_editable (GTK_HTML (priv->msg_body), TRUE);
286         
287         main_vbox = gtk_vbox_new  (FALSE, 0);
288
289         scrolled_window = gtk_scrolled_window_new (NULL, NULL);
290         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), 
291                                         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
292         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
293
294         gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
295         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
296         
297         msg_vbox = gtk_vbox_new (FALSE, 0);
298         gtk_box_pack_start (GTK_BOX (main_vbox), msg_vbox, TRUE, TRUE, 0);
299
300         gtk_box_pack_start (GTK_BOX(msg_vbox), header_table, FALSE, FALSE, 0);
301         gtk_container_add (GTK_CONTAINER (scrolled_window), priv->msg_body); 
302
303         gtk_box_pack_start (GTK_BOX(msg_vbox), scrolled_window, TRUE, TRUE, 0);
304
305         gtk_widget_show_all (GTK_WIDGET(main_vbox));
306         gtk_container_add (GTK_CONTAINER(obj), main_vbox);
307
308         g_signal_connect_object (add_attachment_button, "clicked", 
309                                  G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), G_OBJECT (obj), 0);
310 }
311
312
313 static void
314 modest_msg_edit_window_finalize (GObject *obj)
315 {
316         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
317         
318         /* These had to stay alive for as long as the comboboxes that used them: */
319         modest_pair_list_free (priv->from_field_protos);
320         g_object_unref (priv->attachments);
321         priv->attachments = NULL;
322
323         if (priv->draft_msg != NULL) {
324                 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
325                 if (TNY_IS_HEADER (header)) {
326                         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
327                         modest_window_mgr_unregister_header (mgr, header);
328                 }
329                 g_object_unref (priv->draft_msg);
330                 priv->draft_msg = NULL;
331         }
332         if (priv->outbox_msg != NULL) {
333                 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
334                 if (TNY_IS_HEADER (header)) {
335                         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
336                         modest_window_mgr_unregister_header (mgr, header);
337                 }
338                 g_object_unref (priv->outbox_msg);
339                 priv->outbox_msg = NULL;
340         }
341         g_free (priv->msg_uid);
342         
343         G_OBJECT_CLASS(parent_class)->finalize (obj);
344 }
345
346 static void
347 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
348 {
349         TnyIterator *iter;
350         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
351
352         for (iter = tny_list_create_iterator (attachments) ; 
353              !tny_iterator_is_done (iter);
354              tny_iterator_next (iter)) {
355                 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
356                 const gchar *cid = tny_mime_part_get_content_id (part);
357                 if (cid != NULL) {
358                         char *invalid = NULL;
359                         gint int_cid = strtol (cid, &invalid, 10);
360                         if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
361                                 priv->next_cid = int_cid + 1;
362                         }
363                 }
364                 g_object_unref (part);
365         }
366         g_object_unref (iter);
367 }
368
369
370
371 static gboolean
372 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgEditWindow *self)
373 {
374         modest_window_save_state (MODEST_WINDOW(self));
375         return FALSE;
376 }
377
378
379 static void
380 set_msg (ModestMsgEditWindow *self, TnyMsg *msg)
381 {
382         TnyHeader *header;
383         TnyFolder *msg_folder;
384         gchar *to, *cc, *bcc, *subject;
385         ModestMsgEditWindowPrivate *priv;
386         gchar *body;
387         
388         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
389         g_return_if_fail (TNY_IS_MSG (msg));
390
391         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
392
393         header  = tny_msg_get_header (msg);
394         to      = tny_header_dup_to (header);
395         cc      = tny_header_dup_cc (header);
396         bcc     = tny_header_dup_bcc (header);
397         subject = tny_header_dup_subject (header);
398
399         if (to)
400                 gtk_entry_set_text (GTK_ENTRY(priv->to_field), to);
401         if (cc)
402                 gtk_entry_set_text (GTK_ENTRY(priv->cc_field), cc);
403         if (bcc)
404                 gtk_entry_set_text (GTK_ENTRY(priv->bcc_field),  bcc);
405         if (subject)
406                 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
407
408         modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
409         priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
410         update_next_cid (self, priv->attachments);
411
412         body = modest_tny_msg_get_body (msg, FALSE, NULL);
413         gtk_html_set_editable (GTK_HTML (priv->msg_body), FALSE);
414         if (body) {
415                 gtk_html_load_from_string (GTK_HTML (priv->msg_body), body, -1);
416         }
417         gtk_html_set_editable (GTK_HTML (priv->msg_body), TRUE);
418         g_free (body);
419
420         modest_msg_edit_window_set_modified (self, FALSE);
421
422         if (priv->msg_uid) {
423                 g_free (priv->msg_uid);
424                 priv->msg_uid = NULL;
425         }
426
427         /* we should set a reference to the incoming message if it is a draft */
428         msg_folder = tny_msg_get_folder (msg);
429         if (msg_folder) {               
430                 if (modest_tny_folder_is_local_folder (msg_folder)) {
431                         TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
432                         if (type == TNY_FOLDER_TYPE_INVALID)
433                                 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
434                         
435                         if (type == TNY_FOLDER_TYPE_DRAFTS) 
436                                 priv->draft_msg = g_object_ref(msg);
437                         if (type == TNY_FOLDER_TYPE_OUTBOX)
438                                 priv->outbox_msg = g_object_ref(msg);
439                         priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
440                 }
441                 g_object_unref (msg_folder);
442         }
443
444         g_free (subject);
445         g_free (to);
446         g_free (cc);
447         g_free (bcc);
448 }
449
450
451 ModestWindow *
452 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account,
453                             gboolean preserve_is_rich)
454 {
455         ModestMsgEditWindow *self;
456         ModestMsgEditWindowPrivate *priv;
457         ModestWindowPrivate *parent_priv;
458         GtkActionGroup *action_group;
459         ModestDimmingRulesGroup *menu_rules_group = NULL;
460         ModestDimmingRulesGroup *toolbar_rules_group = NULL;
461         ModestDimmingRulesGroup *clipboard_rules_group = NULL;
462         GError *error = NULL;
463
464         g_return_val_if_fail (msg, NULL);
465         
466         self = MODEST_MSG_EDIT_WINDOW(g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL));
467         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(self);
468         parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
469         
470         parent_priv->ui_manager = gtk_ui_manager_new();
471         action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
472         gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
473
474         /* Add common actions */
475         gtk_action_group_add_actions (action_group,
476                                       modest_msg_edit_action_entries,
477                                       G_N_ELEMENTS (modest_msg_edit_action_entries),
478                                       self);
479         gtk_action_group_add_toggle_actions (action_group,
480                                              modest_msg_edit_toggle_action_entries,
481                                              G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
482                                              self);
483         gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
484         g_object_unref (action_group);
485
486         /* Load the UI definition */
487         gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager,
488                                          MODEST_UIDIR "modest-msg-edit-window-ui.xml",
489                                          &error);
490         if (error) {
491                 g_printerr ("modest: could not merge modest-msg-edit-window-ui.xml: %s\n", error->message);
492                 g_error_free (error);
493                 error = NULL;
494         }
495         /* ****** */
496
497         /* Add accelerators */
498         gtk_window_add_accel_group (GTK_WINDOW (self), 
499                                     gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
500
501         /* Toolbar / Menubar */
502         priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
503         priv->menubar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/MenuBar");
504
505         gtk_toolbar_set_tooltips (GTK_TOOLBAR (priv->toolbar), TRUE);
506
507         /* Init window */
508         init_window (MODEST_MSG_EDIT_WINDOW(self), account);
509
510         restore_settings (MODEST_MSG_EDIT_WINDOW(self));
511         
512         gtk_window_set_title (GTK_WINDOW(self), "Modest");
513         gtk_window_set_icon_from_file (GTK_WINDOW(self), MODEST_APP_ICON, NULL);
514
515         g_signal_connect (G_OBJECT(self), "delete-event",
516                           G_CALLBACK(on_delete_event), self);
517         
518         parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
519         menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
520         toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
521         clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
522
523         /* Add common dimming rules */
524         modest_dimming_rules_group_add_rules (menu_rules_group, 
525                                               modest_msg_edit_window_menu_dimming_entries,
526                                               G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
527                                               MODEST_WINDOW (self));
528         modest_dimming_rules_group_add_rules (toolbar_rules_group, 
529                                               modest_msg_edit_window_toolbar_dimming_entries,
530                                               G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
531                                               MODEST_WINDOW (self));
532 /*      modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button, */
533 /*                                                  G_CALLBACK (modest_ui_dimming_rules_on_set_style), */
534 /*                                                  MODEST_WINDOW (self)); */
535 /*      modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem, */
536 /*                                                  G_CALLBACK (modest_ui_dimming_rules_on_set_style), */
537 /*                                                  MODEST_WINDOW (self)); */
538 /*      modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem, */
539 /*                                                  G_CALLBACK (modest_ui_dimming_rules_on_set_style), */
540 /*                                                  MODEST_WINDOW (self)); */
541         modest_dimming_rules_group_add_rules (clipboard_rules_group, 
542                                               modest_msg_edit_window_clipboard_dimming_entries,
543                                               G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
544                                               MODEST_WINDOW (self));
545         /* Insert dimming rules group for this window */
546         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
547         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
548         modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
549         /* Checks the dimming rules */
550         g_object_unref (menu_rules_group);
551         g_object_unref (toolbar_rules_group);
552         g_object_unref (clipboard_rules_group);
553
554         set_msg (self, msg);
555         
556         return MODEST_WINDOW(self);
557 }
558
559 static gboolean
560 html_export_save_buffer (gpointer engine,
561                          const gchar *data,
562                          size_t len,
563                          GString **buffer)
564 {
565         *buffer = g_string_append (*buffer, data);
566         return TRUE;
567 }
568
569
570 MsgData * 
571 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
572 {
573         MsgData *data;
574         
575         const gchar *account_name;
576         gchar *from_string = NULL;
577         ModestMsgEditWindowPrivate *priv;
578         GString *buffer;
579         TnyIterator *att_iter;
580         
581         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
582
583         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
584         
585         account_name = (gchar*)modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
586         if (account_name) 
587                 from_string = modest_account_mgr_get_from_string (
588                         modest_runtime_get_account_mgr(), account_name);
589         if (!from_string) {
590                 g_printerr ("modest: cannot get from string\n");
591                 return NULL;
592         }
593         
594         
595         
596         data = g_slice_new0 (MsgData);
597         data->from    =  from_string; /* will be freed when data is freed */
598         data->to      =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->to_field)));
599         data->cc      =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->cc_field)));
600         data->bcc     =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->bcc_field)));
601         data->subject =  g_strdup ( gtk_entry_get_text (GTK_ENTRY(priv->subject_field)));
602
603 /*      GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)); */
604 /*      GtkTextIter b, e; */
605 /*      gtk_text_buffer_get_bounds (buf, &b, &e); */
606 /*      data->plain_body =  gtk_text_buffer_get_text (buf, &b, &e, FALSE); /\* Returns a copy. *\/ */
607
608         buffer = g_string_new ("");
609         gtk_html_export (GTK_HTML (priv->msg_body), "text/html", (GtkHTMLSaveReceiverFn) html_export_save_buffer, &buffer);
610         data->html_body = g_string_free (buffer, FALSE);
611         buffer = g_string_new ("");
612         gtk_html_export (GTK_HTML (priv->msg_body), "text/plain", (GtkHTMLSaveReceiverFn) html_export_save_buffer, &buffer);
613         data->plain_body = g_string_free (buffer, FALSE);
614
615         /* deep-copy the attachment data */
616         att_iter = tny_list_create_iterator (priv->attachments);
617         data->attachments = NULL;
618         while (!tny_iterator_is_done (att_iter)) {
619                 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
620                 if (!(TNY_IS_MIME_PART(part))) {
621                         g_warning ("strange data in attachment list");
622                         g_object_unref (part);
623                         tny_iterator_next (att_iter);
624                         continue;
625                 }
626                 data->attachments = g_list_append (data->attachments,
627                                                    part);
628                 tny_iterator_next (att_iter);
629         }
630         g_object_unref (att_iter);
631
632
633         if (priv->draft_msg) {
634                 data->draft_msg = g_object_ref (priv->draft_msg);
635         } else if (priv->outbox_msg) {
636                 data->draft_msg = g_object_ref (priv->outbox_msg);
637         } else {
638                 data->draft_msg = NULL;
639         }
640         return data;
641 }
642
643 static void
644 unref_gobject (GObject *obj, gpointer data)
645 {
646         if (!G_IS_OBJECT(obj))
647                 return;
648         g_object_unref (obj);
649 }
650
651 void 
652 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
653                                       MsgData *data)
654 {
655         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
656
657         if (!data)
658                 return;
659
660         g_free (data->to);
661         g_free (data->cc);
662         g_free (data->bcc);
663         g_free (data->subject);
664         g_free (data->plain_body);
665         g_free (data->html_body);
666
667         if (data->draft_msg != NULL) {
668                 g_object_unref (data->draft_msg);
669                 data->draft_msg = NULL;
670         }       
671         
672         g_list_foreach (data->attachments, (GFunc)unref_gobject,  NULL);
673         g_list_free (data->attachments);
674
675         g_slice_free (MsgData, data);
676 }
677
678 /* Rich formatting API functions */
679 ModestMsgEditFormat
680 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
681 {
682         return MODEST_MSG_EDIT_FORMAT_TEXT;
683 }
684
685 void
686 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
687                                    ModestMsgEditFormat format)
688 {
689         switch (format) {
690         case MODEST_MSG_EDIT_FORMAT_TEXT:
691                 break;
692         case MODEST_MSG_EDIT_FORMAT_HTML:
693                 g_message ("HTML format not supported in Gnome ModestMsgEditWindow");
694                 break;
695         default:
696                 break;
697         }
698 }
699
700 ModestMsgEditFormatState *
701 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
702 {
703         ModestMsgEditFormatState *format_state;
704
705         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
706
707         format_state = g_new0 (ModestMsgEditFormatState, 1);
708
709         return format_state;
710 }
711
712 void
713 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self, 
714                                          const ModestMsgEditFormatState *format_state)
715 {
716         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (self));
717
718         /* Ends silently as set_format_state should do nothing when edit window format
719            is not HTML */
720         return;
721 }
722
723 void
724 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
725 {
726         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
727
728         g_message ("Select color operation is not supported");
729 }
730
731 void
732 modest_msg_edit_window_select_file_format (ModestMsgEditWindow *window,
733                                            gint file_format)
734 {
735         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
736
737         g_message ("Select file format operation is not supported");
738 }
739
740 void
741 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
742 {
743         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
744
745         g_message ("Select font operation is not supported");
746 }
747
748 void
749 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
750 {
751         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
752
753         g_message ("Select background color operation is not supported");
754 }
755
756 void
757 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
758 {
759         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
760
761         g_message ("Insert image operation is not supported");
762 }
763
764 void
765 modest_msg_edit_window_attach_file (ModestMsgEditWindow *window)
766 {
767         g_return_if_fail (MODEST_MSG_EDIT_WINDOW (window));
768
769         g_message ("Attach file operation is not supported");
770 }
771
772 void
773 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
774                                            TnyList *att_list)
775 {
776         ModestMsgEditWindowPrivate *priv;
777         TnyIterator *iter;
778
779         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
780         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
781
782         if (att_list == NULL) {
783                 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
784         } else {
785                 g_object_ref (att_list);
786         }
787
788         if (tny_list_get_length (att_list) == 0) {
789                 modest_platform_information_banner (NULL, NULL, _("TODO: no attachments selected to remove"));
790         } else {
791                 GtkWidget *confirmation_dialog = NULL;
792                 gboolean dialog_response;
793                 gchar *message = NULL;
794                 gchar *filename = NULL;
795
796                 if (tny_list_get_length (att_list) == 1) {
797                         TnyMimePart *part;
798                         iter = tny_list_create_iterator (att_list);
799                         part = (TnyMimePart *) tny_iterator_get_current (iter);
800                         g_object_unref (iter);
801                         if (TNY_IS_MSG (part)) {
802                                 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
803                                 if (header) {
804                                         filename = tny_header_dup_subject (header);
805                                         g_object_unref (header);
806                                 }
807                                 if (filename == NULL) {
808                                         filename = g_strdup (_("mail_va_no_subject"));
809                                 }
810                         } else {
811                                 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
812                         }
813                         g_object_unref (part);
814                 } else {
815                         filename = g_strdup ("");
816                 }
817                 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
818                                                     (tny_list_get_length (att_list) == 1)), filename);
819                 g_free (filename);
820                 confirmation_dialog = gtk_message_dialog_new (GTK_WINDOW (window), 
821                                                               GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, 
822                                                               GTK_MESSAGE_QUESTION,
823                                                               GTK_BUTTONS_OK_CANCEL,
824                                                               message);
825                 g_free (message);
826                 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
827                 gtk_widget_destroy (confirmation_dialog);
828                 if (!dialog_response) {
829                         g_object_unref (att_list);
830                         return;
831                 }
832                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
833                 
834                 for (iter = tny_list_create_iterator (att_list);
835                      !tny_iterator_is_done (iter);
836                      tny_iterator_next (iter)) {
837                         TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
838                         tny_list_remove (priv->attachments, (GObject *) mime_part);
839
840                         modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
841                                                                    mime_part);
842                         g_object_unref (mime_part);
843                 }
844                 g_object_unref (iter);
845         }
846
847         g_object_unref (att_list);
848
849 }
850
851 static void
852 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
853                                                ModestMsgEditWindow *window)
854 {
855         modest_msg_edit_window_offer_attach_file (window);
856 }
857
858 void 
859 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
860                                        gint *parts_count,
861                                        guint64 *parts_size)
862 {
863         ModestMsgEditWindowPrivate *priv;
864
865         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
866
867         modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
868
869 }
870
871 void
872 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window, 
873                                 gboolean show)
874 {
875         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
876
877         g_message ("not implemented yet %s", __FUNCTION__);
878 }
879 void
880 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window, 
881                                 gboolean show)
882 {
883         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
884
885         g_message ("not implemented yet %s", __FUNCTION__);
886 }
887 void
888 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
889 {
890         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
891       
892         g_message ("not implemented yet %s", __FUNCTION__);
893 }
894 void
895 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
896 {
897         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
898       
899         g_message ("not implemented yet %s", __FUNCTION__);
900 }
901 void
902 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
903                                            TnyHeaderFlags priority_flags)
904 {
905         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
906       
907         g_message ("not implemented yet %s", __FUNCTION__);
908 }
909
910
911 void
912 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
913 {
914         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
915
916         g_message ("not implemented yet %s", __FUNCTION__);
917 }
918
919 gboolean
920 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
921 {
922         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
923
924         g_message ("not implemented yet %s", __FUNCTION__);
925         return TRUE;
926 }
927
928 void
929 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
930                                         gint file_format)
931 {
932         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
933
934         g_message ("not implemented yet %s", __FUNCTION__);
935 }
936
937 gboolean 
938 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
939 {
940         ModestMsgEditWindowPrivate *priv;
941
942         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
943         return priv->sent;
944 }
945
946 void 
947 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window, 
948                                  gboolean sent)
949 {
950         ModestMsgEditWindowPrivate *priv;
951
952         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
953         priv->sent = sent;
954 }
955
956 GtkWidget *
957 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
958                                          ModestMsgEditWindowWidgetType widget_type)
959 {
960         ModestMsgEditWindowPrivate *priv;
961
962         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
963         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
964
965         switch (widget_type) {
966         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
967                 return priv->msg_body;
968                 break;
969         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
970                 return priv->to_field;
971                 break;
972         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
973                 return priv->cc_field;
974                 break;
975         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
976                 return priv->bcc_field;
977                 break;
978         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
979                 return priv->subject_field;
980                 break;
981         case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
982                 return priv->attachments_view;
983                 break;
984         default:
985                 return NULL;
986         }
987         return NULL;
988 }
989
990 /* FUNCTIONS NOT IMPLEMENTED YET */
991
992 void            
993 modest_msg_edit_window_set_modified      (ModestMsgEditWindow *window,
994                                           gboolean modified)
995 {
996         g_message (__FUNCTION__);
997 }
998
999 void            
1000 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
1001                                             gboolean show)
1002 {
1003         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1004 }
1005
1006 void                    
1007 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
1008                                  TnyMimePart *part)
1009 {
1010         ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1011
1012         g_return_if_fail (TNY_IS_MIME_PART (part));
1013         tny_list_prepend (priv->attachments, (GObject *) part);
1014         modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
1015 }
1016
1017 void            
1018 modest_msg_edit_window_redo               (ModestMsgEditWindow *window)
1019 {
1020         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1021 }
1022
1023 void                    
1024 modest_msg_edit_window_offer_attach_file           (ModestMsgEditWindow *window)
1025 {
1026         GtkWidget *dialog = NULL;
1027         gint response = 0;
1028         GSList *uris = NULL;
1029         GSList *uri_node;
1030         
1031         dialog = gtk_file_chooser_dialog_new (_("mcen_ti_select_attachment_title"), 
1032                                               GTK_WINDOW (window), 
1033                                               GTK_FILE_CHOOSER_ACTION_OPEN,
1034                                               GTK_STOCK_OPEN,
1035                                               GTK_RESPONSE_OK,
1036                                               GTK_STOCK_CANCEL,
1037                                               GTK_RESPONSE_CANCEL,
1038                                               NULL);
1039
1040         response = gtk_dialog_run (GTK_DIALOG (dialog));
1041         switch (response) {
1042         case GTK_RESPONSE_OK:
1043                 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1044                 break;
1045         default:
1046                 break;
1047         }
1048         gtk_widget_destroy (dialog);
1049
1050         for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1051                 const gchar *uri = (const gchar *) uri_node->data;
1052                 modest_msg_edit_window_attach_file_one (window, uri, MODEST_MAX_ATTACHMENT_SIZE);
1053         }
1054         g_slist_foreach (uris, (GFunc) g_free, NULL);
1055         g_slist_free (uris);
1056 }
1057
1058 GnomeVFSFileSize
1059 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window, 
1060                                         const gchar *uri,
1061                                         GnomeVFSFileSize allowed_size)
1062 {
1063         GnomeVFSHandle *handle = NULL;
1064         ModestMsgEditWindowPrivate *priv;
1065         GnomeVFSResult result;
1066
1067         g_return_if_fail (window);
1068         g_return_if_fail (uri);
1069                 
1070         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1071         
1072         result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1073         if (result == GNOME_VFS_OK) {
1074                 TnyMimePart *mime_part;
1075                 TnyStream *stream;
1076                 const gchar *mime_type = NULL;
1077                 gchar *basename;
1078                 gchar *escaped_filename;
1079                 gchar *filename;
1080                 gchar *content_id;
1081                 GnomeVFSFileInfo *info;
1082                 GnomeVFSURI *vfs_uri;
1083
1084                 vfs_uri = gnome_vfs_uri_new (uri);
1085
1086                 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1087                 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1088                 g_free (escaped_filename);
1089                 gnome_vfs_uri_unref (vfs_uri);
1090
1091                 info = gnome_vfs_file_info_new ();
1092                 
1093                 if (gnome_vfs_get_file_info (uri, 
1094                                              info, 
1095                                              GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
1096                     == GNOME_VFS_OK)
1097                         mime_type = gnome_vfs_file_info_get_mime_type (info);
1098                 mime_part = tny_platform_factory_new_mime_part
1099                         (modest_runtime_get_platform_factory ());
1100                 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1101                 
1102                 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
1103
1104                 g_object_unref (stream);
1105                 
1106                 content_id = g_strdup_printf ("%d", priv->next_cid);
1107                 tny_mime_part_set_content_id (mime_part, content_id);
1108                 g_free (content_id);
1109                 priv->next_cid++;
1110                 
1111                 basename = g_path_get_basename (filename);
1112                 tny_mime_part_set_filename (mime_part, basename);
1113                 g_free (basename);
1114                 
1115                 tny_list_prepend (priv->attachments, (GObject *) mime_part);
1116                 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1117                                                         mime_part,
1118                                                         info->size == 0, info->size);
1119                 g_free (filename);
1120                 g_object_unref (mime_part);
1121                 gnome_vfs_file_info_unref (info);
1122         }
1123 }
1124
1125 void            
1126 modest_msg_edit_window_set_draft           (ModestMsgEditWindow *window,
1127                                             TnyMsg *draft)
1128 {
1129         ModestMsgEditWindowPrivate *priv;
1130         TnyHeader *header = NULL;
1131
1132         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1133         g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
1134
1135         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1136         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
1137
1138         if (priv->draft_msg != NULL) {
1139                 g_object_unref (priv->draft_msg);
1140         }
1141
1142         if (draft != NULL) {
1143                 g_object_ref (draft);
1144                 header = tny_msg_get_header (draft);
1145                 if (priv->msg_uid) {
1146                         g_free (priv->msg_uid);
1147                         priv->msg_uid = NULL;
1148                 }
1149                 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1150                 if (GTK_WIDGET_REALIZED (window))
1151                         modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
1152         }
1153
1154         priv->draft_msg = draft;
1155 }
1156
1157 gboolean        
1158 modest_msg_edit_window_is_modified         (ModestMsgEditWindow *window)
1159 {
1160         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1161         return TRUE;
1162 }
1163
1164 const gchar *
1165 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
1166 {
1167         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1168         return NULL;
1169 }
1170
1171 gboolean            
1172 modest_msg_edit_window_can_redo               (ModestMsgEditWindow *window)
1173 {
1174         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1175         return FALSE;
1176 }
1177 gboolean            
1178 modest_msg_edit_window_can_undo               (ModestMsgEditWindow *window)
1179 {
1180         g_message ("NOT IMPLEMENTED %s", __FUNCTION__);
1181         return FALSE;
1182 }
1183
1184 const gchar*    
1185 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
1186 {
1187         ModestMsgEditWindowPrivate *priv;
1188
1189         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);        
1190         priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1191
1192         return priv->msg_uid;
1193 }