1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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.
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.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
49 #include <modest-runtime.h>
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-tny-folder.h"
59 #include "modest-tny-account.h"
60 #include "modest-address-book.h"
61 #include "modest-text-utils.h"
62 #include <tny-simple-list.h>
63 #include <wptextview.h>
64 #include <wptextbuffer.h>
65 #include "modest-scroll-area.h"
66 #include "modest-msg-edit-window-ui-dimming.h"
68 #include "modest-hildon-includes.h"
69 #ifdef MODEST_HAVE_HILDON0_WIDGETS
70 #include <hildon-widgets/hildon-color-chooser.h>
72 #include "widgets/modest-msg-edit-window-ui.h"
73 #ifdef MODEST_HAVE_HILDON0_WIDGETS
74 #include <libgnomevfs/gnome-vfs-mime-utils.h>
76 #include <libgnomevfs/gnome-vfs-mime.h>
78 #include <modest-utils.h>
79 #include "modest-maemo-utils.h"
82 #define DEFAULT_FONT_SIZE 3
83 #define DEFAULT_FONT 2
84 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
85 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
86 #define DEFAULT_MAIN_VBOX_SPACING 6
87 #define SUBJECT_MAX_LENGTH 1000
88 #define IMAGE_MAX_WIDTH 560
89 #define DEFAULT_FONT_SCALE 1.5
91 static gboolean is_wp_text_buffer_started = FALSE;
93 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
94 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
95 static void modest_msg_edit_window_finalize (GObject *obj);
97 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
98 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
99 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
101 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
102 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
103 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
104 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
105 GtkTextIter *start, GtkTextIter *end,
107 static void text_buffer_insert_text (GtkTextBuffer *buffer,
108 GtkTextIter *location,
111 ModestMsgEditWindow *window);
112 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
113 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
114 static void subject_field_insert_text (GtkEditable *editable,
116 gint new_text_length,
118 ModestMsgEditWindow *window);
119 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
121 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
123 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
125 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
126 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
127 GdkEventWindowState *event,
129 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
130 ModestRecptEditor *editor);
131 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
132 ModestMsgEditWindow *window);
134 /* ModestWindow methods implementation */
135 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
136 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
137 gboolean show_toolbar);
138 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
140 ModestMsgEditWindow *window);
141 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
142 static void subject_field_move_cursor (GtkEntry *entry,
143 GtkMovementStep step,
147 static void update_window_title (ModestMsgEditWindow *window);
150 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
151 ModestMsgEditWindow *window);
152 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
153 ModestMsgEditWindow *window);
154 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
156 GtkTextIter *match_start,
157 GtkTextIter *match_end);
159 static void remove_tags (WPTextBuffer *buffer);
161 static void on_account_removed (TnyAccountStore *account_store,
165 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
166 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
167 static gdouble get_zoom_do_nothing (ModestWindow *window);
169 static void init_window (ModestMsgEditWindow *obj);
171 gboolean scroll_drag_timeout (gpointer userdata);
172 static void correct_scroll (ModestMsgEditWindow *w);
173 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
174 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
175 ModestMsgEditWindow *userdata);
176 static void text_buffer_mark_set (GtkTextBuffer *buffer,
179 ModestMsgEditWindow *userdata);
180 void vadj_changed (GtkAdjustment *adj,
181 ModestMsgEditWindow *window);
183 static ModestPair *find_transport_from_message_sender (ModestPairList *transports,
189 static void DEBUG_BUFFER (WPTextBuffer *buffer)
193 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
195 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
196 while (!gtk_text_iter_is_end (&iter)) {
197 GString *output = g_string_new ("");
198 GSList *toggled_tags;
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
202 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
203 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
204 GtkTextTag *tag = (GtkTextTag *) node->data;
206 g_object_get (G_OBJECT (tag), "name", &name, NULL);
207 output = g_string_append (output, name);
208 g_string_append (output, " ");
210 output = g_string_append (output, "] OPENED [ ");
211 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
212 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
213 GtkTextTag *tag = (GtkTextTag *) node->data;
215 g_object_get (G_OBJECT (tag), "name", &name, NULL);
216 output = g_string_append (output, name);
217 g_string_append (output, " ");
219 output = g_string_append (output, "]\n");
220 g_message ("%s", output->str);
221 g_string_free (output, TRUE);
222 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
224 g_message ("END BUFFER");
229 /* static gboolean */
230 /* on_key_pressed (GtkWidget *self, */
231 /* GdkEventKey *event, */
232 /* gpointer user_data); */
234 /* list my signals */
241 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
242 struct _ModestMsgEditWindowPrivate {
245 GtkWidget *header_box;
247 ModestPairList *from_field_protos;
248 GtkWidget *from_field;
249 const gchar *original_account_name;
253 GtkWidget *bcc_field;
254 GtkWidget *subject_field;
255 GtkWidget *attachments_view;
256 GtkWidget *priority_icon;
257 GtkWidget *add_attachment_button;
259 GtkWidget *cc_caption;
260 GtkWidget *bcc_caption;
261 gboolean update_caption_visibility;
262 GtkWidget *attachments_caption;
264 GtkTextBuffer *text_buffer;
266 GtkWidget *font_size_toolitem;
267 GtkWidget *font_face_toolitem;
268 GtkWidget *font_color_button;
269 GSList *font_items_group;
270 GtkWidget *font_tool_button_label;
271 GSList *size_items_group;
272 GtkWidget *size_tool_button_label;
274 GtkWidget *find_toolbar;
278 guint scroll_drag_timeout_id;
282 TnyList *attachments;
287 TnyHeaderFlags priority_flags;
289 gboolean can_undo, can_redo;
290 gulong clipboard_change_handler_id;
291 gulong default_clipboard_change_handler_id;
292 gulong account_removed_handler_id;
293 guint clipboard_owner_idle;
294 gchar *clipboard_text;
303 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
304 MODEST_TYPE_MSG_EDIT_WINDOW, \
305 ModestMsgEditWindowPrivate))
307 static GtkWindowClass *parent_class = NULL;
309 /* uncomment the following if you have defined any signals */
310 /* static guint signals[LAST_SIGNAL] = {0}; */
313 modest_msg_edit_window_get_type (void)
315 static GType my_type = 0;
317 static const GTypeInfo my_info = {
318 sizeof(ModestMsgEditWindowClass),
319 NULL, /* base init */
320 NULL, /* base finalize */
321 (GClassInitFunc) modest_msg_edit_window_class_init,
322 NULL, /* class finalize */
323 NULL, /* class data */
324 sizeof(ModestMsgEditWindow),
326 (GInstanceInitFunc) modest_msg_edit_window_init,
329 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
330 "ModestMsgEditWindow",
338 save_state (ModestWindow *self)
340 modest_widget_memory_save (modest_runtime_get_conf(),
341 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
346 restore_settings (ModestMsgEditWindow *self)
348 ModestConf *conf = NULL;
350 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
352 conf = modest_runtime_get_conf ();
353 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
354 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
355 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
356 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
357 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
358 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
359 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
360 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
362 /* set initial state of cc and bcc */
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
364 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
365 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
366 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
367 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
368 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
370 /* Dim at start clipboard actions */
371 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
372 gtk_action_set_sensitive (action, FALSE);
373 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
374 gtk_action_set_sensitive (action, FALSE);
375 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
376 gtk_action_set_sensitive (action, FALSE);
378 modest_widget_memory_restore (conf,
379 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
384 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
386 GObjectClass *gobject_class;
387 ModestWindowClass *modest_window_class;
388 gobject_class = (GObjectClass*) klass;
389 modest_window_class = (ModestWindowClass*) klass;
391 parent_class = g_type_class_peek_parent (klass);
392 gobject_class->finalize = modest_msg_edit_window_finalize;
394 modest_window_class->set_zoom_func = set_zoom_do_nothing;
395 modest_window_class->get_zoom_func = get_zoom_do_nothing;
396 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
397 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
398 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
399 modest_window_class->save_state_func = save_state;
400 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
402 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
406 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
408 ModestMsgEditWindowPrivate *priv;
409 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
411 priv->msg_body = NULL;
413 priv->from_field = NULL;
414 priv->to_field = NULL;
415 priv->cc_field = NULL;
416 priv->bcc_field = NULL;
417 priv->subject_field = NULL;
418 priv->attachments = TNY_LIST (tny_simple_list_new ());
419 priv->images = TNY_LIST (tny_simple_list_new ());
420 priv->images_size = 0;
421 priv->images_count = 0;
424 priv->cc_caption = NULL;
425 priv->bcc_caption = NULL;
426 priv->update_caption_visibility = FALSE;
428 priv->priority_flags = 0;
430 priv->find_toolbar = NULL;
431 priv->last_search = NULL;
433 priv->draft_msg = NULL;
434 priv->outbox_msg = NULL;
435 priv->msg_uid = NULL;
437 priv->can_undo = FALSE;
438 priv->can_redo = FALSE;
439 priv->clipboard_change_handler_id = 0;
440 priv->default_clipboard_change_handler_id = 0;
441 priv->account_removed_handler_id = 0;
442 priv->clipboard_owner_idle = 0;
443 priv->clipboard_text = NULL;
446 priv->scroll_drag_timeout_id = 0;
447 priv->last_upper = 0.0;
449 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
450 GTK_WINDOW(obj),"applications_email_editor");
452 if (!is_wp_text_buffer_started) {
453 is_wp_text_buffer_started = TRUE;
454 wp_text_buffer_library_init ();
459 hildon_program_add_window (hildon_program_get_instance(),
464 /* FIXME: this is a dup from the one in gtk/ */
467 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
469 static ModestPairList*
470 get_transports (void)
472 GSList *transports = NULL;
474 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
475 GSList *accounts = modest_account_mgr_account_names (account_mgr,
476 TRUE /* only enabled accounts. */);
478 GSList *cursor = accounts;
480 gchar *account_name = cursor->data;
481 gchar *from_string = NULL;
483 from_string = modest_account_mgr_get_from_string (account_mgr,
487 if (from_string && account_name) {
488 gchar *name = account_name;
489 ModestPair *pair = modest_pair_new ((gpointer) name,
490 (gpointer) from_string , TRUE);
491 transports = g_slist_prepend (transports, pair);
494 cursor = cursor->next;
496 g_slist_free (accounts); /* only free the accounts, not the elements,
497 * because they are used in the pairlist */
502 * Search an (account, address) ModestPairList for a pair whose
503 * address matches the one in the From: header of a TnyMsg
505 * @result: A ModestPair * with a matching address, or NULL if none found
508 find_transport_from_message_sender (ModestPairList *transports, TnyMsg *msg)
510 g_return_val_if_fail (transports, NULL);
511 g_return_val_if_fail (msg, NULL);
513 ModestPair *account_pair = NULL;
514 TnyHeader *header = tny_msg_get_header (msg);
516 if (header != NULL && tny_header_get_from (header)) {
517 char *from_addr = modest_text_utils_get_email_address (tny_header_get_from (header));
519 for (iter = transports; iter && !account_pair; iter = iter->next) {
520 ModestPair *pair = (ModestPair *) iter->data;
521 char *account_addr = modest_text_utils_get_email_address ((char *) pair->second);
522 if (account_addr && !strcasecmp(from_addr, account_addr)) {
525 g_free (account_addr);
531 g_object_unref (header);
536 static void window_focus (GtkWindow *window,
540 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
544 scroll_drag_timeout (gpointer userdata)
546 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
547 ModestMsgEditWindowPrivate *priv;
549 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
551 correct_scroll_without_drag_check (win, TRUE);
553 priv->scroll_drag_timeout_id = 0;
559 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
561 ModestMsgEditWindowPrivate *priv;
564 GdkRectangle rectangle;
570 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
572 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
575 insert = gtk_text_buffer_get_insert (priv->text_buffer);
576 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
578 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
579 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
580 offset = priv->msg_body->allocation.y;
582 new_value = vadj->value;
584 if ((offset + rectangle.y + rectangle.height) >
585 ((gint) (vadj->value +vadj->page_size))) {
586 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
587 if (new_value > vadj->upper - vadj->page_size)
588 new_value = vadj->upper - vadj->page_size;
589 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
590 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
591 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
592 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
595 if (new_value > vadj->value)
596 new_value = vadj->value;
599 if (vadj->value != new_value) {
600 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
602 vadj->value = new_value;
603 gtk_adjustment_value_changed (vadj);
604 /* invalidate body */
605 window = gtk_widget_get_parent_window (priv->msg_body);
607 gdk_window_invalidate_rect (window, NULL, TRUE);
613 correct_scroll (ModestMsgEditWindow *w)
615 ModestMsgEditWindowPrivate *priv;
617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
618 if (gtk_grab_get_current () == priv->msg_body) {
619 if (priv->scroll_drag_timeout_id == 0) {
620 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
626 correct_scroll_without_drag_check (w, TRUE);
630 text_buffer_end_user_action (GtkTextBuffer *buffer,
631 ModestMsgEditWindow *userdata)
634 correct_scroll (userdata);
638 text_buffer_mark_set (GtkTextBuffer *buffer,
641 ModestMsgEditWindow *userdata)
643 gtk_text_buffer_begin_user_action (buffer);
644 gtk_text_buffer_end_user_action (buffer);
648 cut_clipboard_check (GtkTextView *text_view,
651 GtkTextBuffer *buffer;
653 buffer = gtk_text_view_get_buffer (text_view);
654 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
655 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
660 copy_clipboard_check (GtkTextView *text_view,
663 GtkTextBuffer *buffer;
665 buffer = gtk_text_view_get_buffer (text_view);
666 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
667 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
671 void vadj_changed (GtkAdjustment *adj,
672 ModestMsgEditWindow *window)
674 ModestMsgEditWindowPrivate *priv;
676 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
678 if (priv->last_upper != adj->upper) {
679 priv->last_upper = adj->upper;
680 correct_scroll (window);
685 connect_signals (ModestMsgEditWindow *obj)
687 ModestMsgEditWindowPrivate *priv;
689 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
691 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
692 G_CALLBACK (text_buffer_refresh_attributes), obj);
693 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
694 G_CALLBACK (text_buffer_can_undo), obj);
695 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
696 G_CALLBACK (text_buffer_can_redo), obj);
697 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
698 G_CALLBACK (body_changed), obj);
699 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
700 G_CALLBACK (body_changed), obj);
701 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
702 G_CALLBACK (text_buffer_insert_text), obj);
703 g_signal_connect (G_OBJECT (obj), "window-state-event",
704 G_CALLBACK (modest_msg_edit_window_window_state_event),
706 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
707 G_CALLBACK (text_buffer_end_user_action), obj);
708 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
709 G_CALLBACK (text_buffer_mark_set), obj);
710 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
711 G_CALLBACK (text_buffer_apply_tag), obj);
712 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
713 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
714 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
715 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
716 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
717 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
719 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
720 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
722 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
723 G_CALLBACK (msg_body_focus), obj);
724 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
725 G_CALLBACK (msg_body_focus), obj);
726 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
727 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
728 "changed", G_CALLBACK (recpt_field_changed), obj);
729 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
730 "changed", G_CALLBACK (recpt_field_changed), obj);
731 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
732 "changed", G_CALLBACK (recpt_field_changed), obj);
733 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
734 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
735 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
737 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
738 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
740 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
742 G_CALLBACK (vadj_changed),
745 priv->clipboard_change_handler_id =
746 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
747 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
748 priv->default_clipboard_change_handler_id =
749 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
750 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
752 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
753 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
758 init_window (ModestMsgEditWindow *obj)
760 GtkWidget *from_caption, *to_caption, *subject_caption;
761 GtkWidget *main_vbox;
762 ModestMsgEditWindowPrivate *priv;
763 GtkActionGroup *action_group;
764 ModestWindowPrivate *parent_priv;
765 GdkPixbuf *window_icon = NULL;
766 GError *error = NULL;
768 GtkSizeGroup *size_group;
769 GtkWidget *subject_box;
770 GtkWidget *attachment_icon;
771 GtkWidget *window_box;
772 #if (GTK_MINOR_VERSION >= 10)
773 GdkAtom deserialize_type;
775 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
776 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
778 parent_priv->ui_manager = gtk_ui_manager_new();
779 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
780 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
782 /* Add common actions */
783 gtk_action_group_add_actions (action_group,
784 modest_msg_edit_action_entries,
785 G_N_ELEMENTS (modest_msg_edit_action_entries),
787 gtk_action_group_add_toggle_actions (action_group,
788 modest_msg_edit_toggle_action_entries,
789 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
791 gtk_action_group_add_radio_actions (action_group,
792 modest_msg_edit_alignment_radio_action_entries,
793 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
795 G_CALLBACK (modest_ui_actions_on_change_justify),
797 gtk_action_group_add_radio_actions (action_group,
798 modest_msg_edit_priority_action_entries,
799 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
801 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
803 gtk_action_group_add_radio_actions (action_group,
804 modest_msg_edit_file_format_action_entries,
805 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
806 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
807 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
809 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
810 g_object_unref (action_group);
812 /* Load the UI definition */
813 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
816 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
817 g_clear_error (&error);
820 /* Add accelerators */
821 gtk_window_add_accel_group (GTK_WINDOW (obj),
822 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
824 parent_priv->menubar = NULL;
826 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
828 /* Note: This ModestPairList* must exist for as long as the combo
829 * that uses it, because the ModestComboBox uses the ID opaquely,
830 * so it can't know how to manage its memory. */
831 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
833 priv->to_field = modest_recpt_editor_new ();
834 priv->cc_field = modest_recpt_editor_new ();
835 priv->bcc_field = modest_recpt_editor_new ();
836 subject_box = gtk_hbox_new (FALSE, 0);
837 priv->priority_icon = gtk_image_new ();
838 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
839 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
840 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
841 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
842 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
843 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
844 priv->add_attachment_button = gtk_button_new ();
845 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
846 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
847 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
848 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
849 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
850 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
851 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
852 priv->attachments_view = modest_attachments_view_new (NULL);
854 priv->header_box = gtk_vbox_new (FALSE, 0);
856 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
857 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
858 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
859 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
860 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
861 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
862 g_object_unref (size_group);
864 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
865 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
866 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
867 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
868 gtk_size_group_add_widget (size_group, priv->subject_field);
869 gtk_size_group_add_widget (size_group, priv->attachments_view);
870 g_object_unref (size_group);
872 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
873 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
874 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
875 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
876 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
877 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
878 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
881 priv->msg_body = wp_text_view_new ();
882 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
883 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
884 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
885 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
886 #if (GTK_MINOR_VERSION >= 10)
887 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
888 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
890 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
891 deserialize_type, TRUE);
893 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
895 priv->find_toolbar = hildon_find_toolbar_new (NULL);
896 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
898 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
900 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
901 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
902 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
903 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
905 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
907 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
908 priv->frame = gtk_frame_new (NULL);
909 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
911 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
912 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
913 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
915 window_box = gtk_vbox_new (FALSE, 0);
916 gtk_container_add (GTK_CONTAINER(obj), window_box);
918 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
920 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
922 /* Set window icon */
923 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
925 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
926 g_object_unref (window_icon);
931 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
933 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
935 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
936 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
937 priv->clipboard_change_handler_id))
938 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
939 priv->clipboard_change_handler_id);
940 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
941 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
942 priv->default_clipboard_change_handler_id))
943 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
944 priv->default_clipboard_change_handler_id);
946 if (priv->account_removed_handler_id &&
947 g_signal_handler_is_connected (modest_runtime_get_account_store (),
948 priv->account_removed_handler_id))
949 g_signal_handler_disconnect(modest_runtime_get_account_store (),
950 priv->account_removed_handler_id);
954 modest_msg_edit_window_finalize (GObject *obj)
956 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
958 /* Sanity check: shouldn't be needed, the window mgr should
959 call this function before */
960 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
962 if (priv->clipboard_text != NULL) {
963 g_free (priv->clipboard_text);
964 priv->clipboard_text = NULL;
967 if (priv->draft_msg != NULL) {
968 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
969 if (TNY_IS_HEADER (header)) {
970 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
971 modest_window_mgr_unregister_header (mgr, header);
973 g_object_unref (priv->draft_msg);
974 priv->draft_msg = NULL;
976 if (priv->outbox_msg != NULL) {
977 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
978 if (TNY_IS_HEADER (header)) {
979 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
980 modest_window_mgr_unregister_header (mgr, header);
982 g_object_unref (priv->outbox_msg);
983 priv->outbox_msg = NULL;
985 if (priv->scroll_drag_timeout_id > 0) {
986 g_source_remove (priv->scroll_drag_timeout_id);
987 priv->scroll_drag_timeout_id = 0;
989 if (priv->clipboard_owner_idle > 0) {
990 g_source_remove (priv->clipboard_owner_idle);
991 priv->clipboard_owner_idle = 0;
993 g_free (priv->msg_uid);
994 g_free (priv->last_search);
995 g_slist_free (priv->font_items_group);
996 g_slist_free (priv->size_items_group);
997 g_object_unref (priv->attachments);
998 g_object_unref (priv->images);
1000 /* This had to stay alive for as long as the combobox that used it: */
1001 modest_pair_list_free (priv->from_field_protos);
1003 G_OBJECT_CLASS(parent_class)->finalize (obj);
1007 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
1009 GdkPixbufLoader *loader;
1015 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1017 if (loader == NULL) {
1023 tny_stream_reset (TNY_STREAM (stream));
1024 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1025 GError *error = NULL;
1026 unsigned char read_buffer[128];
1028 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1030 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1035 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1037 g_object_ref (pixbuf);
1038 gdk_pixbuf_loader_close (loader, NULL);
1039 g_object_unref (loader);
1044 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1045 GdkPixbuf *new_pixbuf;
1047 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1048 gdk_pixbuf_get_width (pixbuf);
1049 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1050 g_object_unref (pixbuf);
1051 pixbuf = new_pixbuf;
1055 *stream_size = size;
1061 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1063 ModestMsgEditWindowPrivate *priv;
1066 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1068 for (iter = tny_list_create_iterator (attachments);
1069 !tny_iterator_is_done (iter);
1070 tny_iterator_next (iter)) {
1071 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1072 const gchar *cid = tny_mime_part_get_content_id (part);
1073 const gchar *mime_type = tny_mime_part_get_content_type (part);
1074 if ((cid != NULL)&&(mime_type != NULL)) {
1075 guint64 stream_size;
1076 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1077 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1080 g_object_unref (stream);
1082 if (pixbuf != NULL) {
1083 priv->images_count ++;
1084 priv->images_size += stream_size;
1085 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1086 g_object_unref (pixbuf);
1089 g_object_unref (part);
1091 g_object_unref (iter);
1095 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1097 TnyMimePart *parent = NULL;
1098 const gchar *content_type = NULL;
1099 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1101 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1103 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1104 parent = g_object_ref (msg);
1105 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1106 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1109 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1110 iter = tny_list_create_iterator (parts);
1111 while (!tny_iterator_is_done (iter)) {
1113 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1114 content_type = tny_mime_part_get_content_type (part);
1115 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1119 g_object_unref (part);
1121 tny_iterator_next (iter);
1123 g_object_unref (iter);
1124 g_object_unref (parts);
1127 if (parent != NULL) {
1128 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1131 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1132 iter = tny_list_create_iterator (parts);
1133 while (!tny_iterator_is_done (iter)) {
1135 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1136 content_type = tny_mime_part_get_content_type (part);
1137 if (content_type && g_str_has_prefix (content_type, "image/")) {
1138 tny_list_prepend (priv->images, (GObject *) part);
1140 g_object_unref (part);
1141 tny_iterator_next (iter);
1143 g_object_unref (iter);
1144 g_object_unref (parts);
1145 g_object_unref (parent);
1150 update_last_cid (ModestMsgEditWindow *self, TnyList *attachments)
1153 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1155 for (iter = tny_list_create_iterator (attachments) ;
1156 !tny_iterator_is_done (iter);
1157 tny_iterator_next (iter)) {
1158 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1159 const gchar *cid = tny_mime_part_get_content_id (part);
1161 char *invalid = NULL;
1162 gint int_cid = strtol (cid, &invalid, 10);
1163 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
1164 priv->last_cid = int_cid;
1167 g_object_unref (part);
1169 g_object_unref (iter);
1173 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1176 const gchar *to, *cc, *bcc, *subject;
1178 ModestMsgEditWindowPrivate *priv;
1180 TnyHeaderFlags priority_flags;
1181 TnyFolder *msg_folder;
1182 gboolean is_html = FALSE;
1184 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1185 g_return_if_fail (TNY_IS_MSG (msg));
1187 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1189 header = tny_msg_get_header (msg);
1190 to = tny_header_get_to (header);
1191 cc = tny_header_get_cc (header);
1192 bcc = tny_header_get_bcc (header);
1193 subject = tny_header_get_subject (header);
1194 priority_flags = tny_header_get_priority (header);
1197 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1199 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1200 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1201 gtk_widget_show (priv->cc_caption);
1202 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1203 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1204 gtk_widget_hide (priv->cc_caption);
1207 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1208 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1209 gtk_widget_show (priv->bcc_caption);
1210 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1211 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1212 gtk_widget_hide (priv->bcc_caption);
1215 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1216 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1219 update_window_title (self);
1221 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1222 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1224 if ((body == NULL)||(body[0] == '\0')) {
1226 body = modest_text_utils_convert_to_html ("");
1229 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1230 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1233 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1236 /* Add attachments to the view */
1237 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1238 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1239 if (tny_list_get_length (priv->attachments) == 0) {
1240 gtk_widget_hide (priv->attachments_caption);
1242 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1243 gtk_widget_show_all (priv->attachments_caption);
1245 get_related_images (self, msg);
1246 update_last_cid (self, priv->attachments);
1247 update_last_cid (self, priv->images);
1248 replace_with_images (self, priv->images);
1250 if (preserve_is_rich && !is_html) {
1251 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1252 /* Get the default format required from configuration */
1253 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1254 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1257 /* Set the default focus depending on having already a To: field or not */
1258 if ((!to)||(*to == '\0')) {
1259 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1261 gtk_widget_grab_focus (priv->msg_body);
1264 /* TODO: lower priority, select in the From: combo to the
1265 value that comes from msg <- not sure, should it be
1268 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1270 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1271 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1273 modest_msg_edit_window_set_modified (self, FALSE);
1275 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1276 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1277 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1278 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1280 if (priv->msg_uid) {
1281 g_free (priv->msg_uid);
1282 priv->msg_uid = NULL;
1285 /* we should set a reference to the incoming message if it is a draft */
1286 msg_folder = tny_msg_get_folder (msg);
1288 if (modest_tny_folder_is_local_folder (msg_folder)) {
1289 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1290 if (type == TNY_FOLDER_TYPE_INVALID)
1291 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1293 if (type == TNY_FOLDER_TYPE_DRAFTS)
1294 priv->draft_msg = g_object_ref(msg);
1295 if (type == TNY_FOLDER_TYPE_OUTBOX)
1296 priv->outbox_msg = g_object_ref(msg);
1297 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1299 g_object_unref (msg_folder);
1304 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1307 GList *item_children, *node;
1308 GtkWidget *bin_child;
1310 bin_child = gtk_bin_get_child (GTK_BIN(item));
1312 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1314 for (node = item_children; node != NULL; node = g_list_next (node)) {
1315 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1316 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1319 g_list_free (item_children);
1323 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1326 GList *item_children, *node;
1328 box = gtk_bin_get_child (GTK_BIN (item));
1329 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1330 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1332 for (node = item_children; node != NULL; node = g_list_next (node)) {
1333 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1334 if (GTK_IS_TOGGLE_BUTTON (node->data))
1335 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1336 else if (GTK_IS_BUTTON (node->data))
1337 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1339 g_list_free (item_children);
1344 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1346 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1347 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1348 GtkWidget *placeholder;
1349 GtkWidget *tool_item;
1354 GtkWidget *sizes_menu;
1355 GtkWidget *fonts_menu;
1356 GSList *radio_group = NULL;
1357 GSList *node = NULL;
1361 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1362 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1364 /* Font color placeholder */
1365 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1366 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1369 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1370 priv->font_color_button = hildon_color_button_new ();
1371 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1372 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1373 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1374 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1375 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1376 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1377 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1379 G_CALLBACK (modest_msg_edit_window_color_button_change),
1382 /* Font size and face placeholder */
1383 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1384 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1386 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1387 priv->size_tool_button_label = gtk_label_new (NULL);
1388 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1389 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1390 size_text,"</span>", NULL);
1391 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1393 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1394 sizes_menu = gtk_menu_new ();
1395 priv->size_items_group = NULL;
1397 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1398 GtkWidget *size_menu_item;
1400 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1401 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1402 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1403 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1404 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1405 gtk_widget_show (size_menu_item);
1407 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1411 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1412 GtkWidget *item = (GtkWidget *) node->data;
1413 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1417 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1418 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1419 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1420 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1421 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1422 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1423 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1424 priv->font_size_toolitem = tool_item;
1427 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1428 priv->font_tool_button_label = gtk_label_new (NULL);
1429 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1430 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1432 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1433 fonts_menu = gtk_menu_new ();
1434 priv->font_items_group = NULL;
1436 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1437 GtkWidget *font_menu_item;
1438 GtkWidget *child_label;
1440 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1441 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1442 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1443 wp_get_font_name (font_index), "</span>", NULL);
1444 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1447 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1448 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1449 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1450 gtk_widget_show (font_menu_item);
1452 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1455 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1456 GtkWidget *item = (GtkWidget *) node->data;
1457 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1460 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1461 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1462 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1463 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1464 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1465 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1466 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1467 priv->font_face_toolitem = tool_item;
1469 /* Set expand and homogeneous for remaining items */
1470 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1471 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1472 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1473 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1474 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1475 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1476 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1477 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1478 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1480 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1481 will not show the tool items added to the placeholders) */
1482 gtk_widget_show_all (parent_priv->toolbar);
1484 /* Set the no show all *after* showing all items. We do not
1485 want the toolbar to be shown with a show all because it
1486 could go agains the gconf setting regarding showing or not
1487 the toolbar of the editor window */
1488 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1494 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1497 ModestWindowPrivate *parent_priv;
1498 ModestMsgEditWindowPrivate *priv;
1499 ModestPair *account_pair = NULL;
1500 ModestDimmingRulesGroup *menu_rules_group = NULL;
1501 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1502 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1503 ModestWindowMgr *mgr = NULL;
1505 g_return_val_if_fail (msg, NULL);
1506 g_return_val_if_fail (account_name, NULL);
1508 mgr = modest_runtime_get_window_mgr ();
1510 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1512 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1513 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1515 /* Menubar. Update the state of some toggles */
1516 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1517 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1518 priv->from_field_protos = get_transports ();
1519 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1520 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1521 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1524 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1526 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1528 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1530 account_pair = find_transport_from_message_sender (priv->from_field_protos, msg);
1531 if (account_pair == NULL) {
1532 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1534 if (account_pair != NULL)
1535 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1537 priv->original_account_name = account_pair ? (const gchar *) account_pair->first : NULL;
1539 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1540 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1541 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1542 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1543 /* Add common dimming rules */
1544 modest_dimming_rules_group_add_rules (menu_rules_group,
1545 modest_msg_edit_window_menu_dimming_entries,
1546 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1547 MODEST_WINDOW (obj));
1548 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1549 modest_msg_edit_window_toolbar_dimming_entries,
1550 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1551 MODEST_WINDOW (obj));
1552 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1553 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1554 MODEST_WINDOW (obj));
1555 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1556 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1557 MODEST_WINDOW (obj));
1558 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1559 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1560 MODEST_WINDOW (obj));
1561 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1562 modest_msg_edit_window_clipboard_dimming_entries,
1563 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1564 MODEST_WINDOW (obj));
1565 /* Insert dimming rules group for this window */
1566 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1567 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1568 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1569 /* Checks the dimming rules */
1570 g_object_unref (menu_rules_group);
1571 g_object_unref (toolbar_rules_group);
1572 g_object_unref (clipboard_rules_group);
1573 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1575 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1577 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1578 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1579 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1580 priv->update_caption_visibility = TRUE;
1582 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1584 /* Track account-removed signal, this window should be closed
1585 in the case we're creating a mail associated to the account
1587 priv->account_removed_handler_id =
1588 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1590 G_CALLBACK(on_account_removed),
1593 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1595 return (ModestWindow*) obj;
1599 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1601 GString **string_buffer = (GString **) user_data;
1603 *string_buffer = g_string_append (*string_buffer, buffer);
1609 * @result: A new string which should be freed with g_free().
1612 get_formatted_data (ModestMsgEditWindow *edit_window)
1614 ModestMsgEditWindowPrivate *priv;
1615 GString *string_buffer = g_string_new ("");
1617 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1619 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1621 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1623 return g_string_free (string_buffer, FALSE);
1628 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1631 const gchar *account_name;
1632 ModestMsgEditWindowPrivate *priv;
1633 TnyIterator *att_iter;
1635 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1637 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1639 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1640 g_return_val_if_fail (account_name, NULL);
1643 /* don't free these (except from) */
1644 data = g_slice_new0 (MsgData);
1645 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1647 data->account_name = g_strdup (account_name);
1648 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1649 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1650 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1651 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1652 if (priv->draft_msg) {
1653 data->draft_msg = g_object_ref (priv->draft_msg);
1654 } else if (priv->outbox_msg) {
1655 data->draft_msg = g_object_ref (priv->outbox_msg);
1657 data->draft_msg = NULL;
1660 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1662 gtk_text_buffer_get_bounds (buf, &b, &e);
1663 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1665 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1666 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1668 data->html_body = NULL;
1670 /* deep-copy the data */
1671 att_iter = tny_list_create_iterator (priv->attachments);
1672 data->attachments = NULL;
1673 while (!tny_iterator_is_done (att_iter)) {
1674 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1675 if (!(TNY_IS_MIME_PART(part))) {
1676 g_warning ("strange data in attachment list");
1677 g_object_unref (part);
1678 tny_iterator_next (att_iter);
1681 data->attachments = g_list_append (data->attachments,
1683 tny_iterator_next (att_iter);
1685 g_object_unref (att_iter);
1687 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1688 att_iter = tny_list_create_iterator (priv->images);
1689 data->images = NULL;
1690 while (!tny_iterator_is_done (att_iter)) {
1691 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1693 if (!(TNY_IS_MIME_PART(part))) {
1694 g_warning ("strange data in attachment list");
1695 g_object_unref (part);
1696 tny_iterator_next (att_iter);
1699 cid = tny_mime_part_get_content_id (part);
1701 gchar *image_tag_id;
1702 GtkTextTag *image_tag;
1704 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1705 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1706 g_free (image_tag_id);
1708 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1710 ((gtk_text_iter_has_tag (&iter, image_tag))||
1711 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1712 data->images = g_list_append (data->images,
1713 g_object_ref (part));
1715 g_object_unref (part);
1716 tny_iterator_next (att_iter);
1718 g_object_unref (att_iter);
1720 data->priority_flags = priv->priority_flags;
1727 unref_gobject (GObject *obj, gpointer data)
1729 if (!G_IS_OBJECT(obj))
1731 g_object_unref (obj);
1735 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1738 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1746 g_free (data->from);
1747 g_free (data->subject);
1748 g_free (data->plain_body);
1749 g_free (data->html_body);
1750 g_free (data->account_name);
1752 if (data->draft_msg != NULL) {
1753 g_object_unref (data->draft_msg);
1754 data->draft_msg = NULL;
1757 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1758 g_list_free (data->attachments);
1759 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1760 g_list_free (data->images);
1762 g_slice_free (MsgData, data);
1766 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1768 guint64 *parts_size)
1770 ModestMsgEditWindowPrivate *priv;
1772 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1774 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1776 /* TODO: add images */
1777 *parts_size += priv->images_size;
1778 *parts_count += priv->images_count;
1783 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1786 ModestMsgEditWindowPrivate *priv = NULL;
1787 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1791 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1793 return MODEST_MSG_EDIT_FORMAT_HTML;
1795 return MODEST_MSG_EDIT_FORMAT_TEXT;
1799 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1800 ModestMsgEditFormat format)
1802 ModestMsgEditWindowPrivate *priv;
1804 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1805 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1808 case MODEST_MSG_EDIT_FORMAT_HTML:
1809 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1811 case MODEST_MSG_EDIT_FORMAT_TEXT:
1812 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1815 g_return_if_reached ();
1819 ModestMsgEditFormatState *
1820 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1822 ModestMsgEditFormatState *format_state = NULL;
1823 ModestMsgEditWindowPrivate *priv;
1824 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1826 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1827 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1829 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1831 format_state = g_new0 (ModestMsgEditFormatState, 1);
1832 format_state->bold = buffer_format->bold&0x1;
1833 format_state->italics = buffer_format->italic&0x1;
1834 format_state->bullet = buffer_format->bullet&0x1;
1835 format_state->color = buffer_format->color;
1836 format_state->font_size = buffer_format->font_size;
1837 format_state->font_family = wp_get_font_name (buffer_format->font);
1838 format_state->justification = buffer_format->justification;
1839 g_free (buffer_format);
1841 return format_state;
1846 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1847 const ModestMsgEditFormatState *format_state)
1849 ModestMsgEditWindowPrivate *priv;
1850 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1851 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1852 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1853 g_return_if_fail (format_state != NULL);
1855 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1856 gtk_widget_grab_focus (priv->msg_body);
1857 buffer_format->bold = (format_state->bold != FALSE);
1858 buffer_format->italic = (format_state->italics != FALSE);
1859 buffer_format->color = format_state->color;
1860 buffer_format->font_size = format_state->font_size;
1861 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1862 buffer_format->justification = format_state->justification;
1863 buffer_format->bullet = format_state->bullet;
1865 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1867 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1868 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1869 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1870 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1871 buffer_format->cs.font = (buffer_format->font != current_format->font);
1872 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1873 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1875 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1876 if (buffer_format->cs.bold) {
1877 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1878 GINT_TO_POINTER (buffer_format->bold&0x1));
1880 if (buffer_format->cs.italic) {
1881 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1882 GINT_TO_POINTER (buffer_format->italic&0x1));
1884 if (buffer_format->cs.color) {
1885 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1886 GINT_TO_POINTER (&(buffer_format->color)));
1888 if (buffer_format->cs.font_size) {
1889 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1890 GINT_TO_POINTER (buffer_format->font_size));
1892 if (buffer_format->cs.justification) {
1893 switch (buffer_format->justification) {
1894 case GTK_JUSTIFY_LEFT:
1895 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1896 GINT_TO_POINTER(TRUE));
1898 case GTK_JUSTIFY_CENTER:
1899 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1900 GINT_TO_POINTER(TRUE));
1902 case GTK_JUSTIFY_RIGHT:
1903 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1904 GINT_TO_POINTER(TRUE));
1911 if (buffer_format->cs.font) {
1912 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1913 GINT_TO_POINTER (buffer_format->font));
1915 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1916 if (buffer_format->cs.bullet) {
1917 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1918 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1920 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1922 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1924 g_free (current_format);
1929 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1931 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1933 ModestWindowPrivate *parent_priv;
1934 ModestMsgEditWindowPrivate *priv;
1935 GtkWidget *new_size_menuitem;
1936 GtkWidget *new_font_menuitem;
1938 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1939 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1941 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1942 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1943 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1944 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1946 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1947 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1948 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1951 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1953 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1954 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1956 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1957 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1959 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1960 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1963 switch (buffer_format->justification)
1965 case GTK_JUSTIFY_LEFT:
1966 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1968 case GTK_JUSTIFY_CENTER:
1969 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1971 case GTK_JUSTIFY_RIGHT:
1972 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1979 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1981 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1982 G_CALLBACK (modest_msg_edit_window_color_button_change),
1984 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1985 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1986 G_CALLBACK (modest_msg_edit_window_color_button_change),
1989 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1990 buffer_format->font_size))->data);
1991 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1995 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1996 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1997 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1999 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
2000 G_CALLBACK (modest_msg_edit_window_size_change),
2002 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
2003 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
2004 G_CALLBACK (modest_msg_edit_window_size_change),
2008 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2009 buffer_format->font))->data);
2010 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2014 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2015 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2016 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2018 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2019 G_CALLBACK (modest_msg_edit_window_font_change),
2021 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2022 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2023 G_CALLBACK (modest_msg_edit_window_font_change),
2027 g_free (buffer_format);
2031 #ifdef MODEST_HILDON_VERSION_0
2033 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2036 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2037 ModestMsgEditWindowPrivate *priv;
2038 GtkWidget *dialog = NULL;
2040 GdkColor *new_color = NULL;
2042 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2043 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2045 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2046 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2047 g_free (buffer_format);
2049 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2050 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2051 if (new_color != NULL) {
2052 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2053 (gpointer) new_color);
2056 gtk_widget_destroy (dialog);
2061 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2064 ModestMsgEditWindowPrivate *priv;
2065 GtkWidget *dialog = NULL;
2067 GdkColor *old_color = NULL;
2068 const GdkColor *new_color = NULL;
2070 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2071 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2073 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2074 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2076 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2077 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2078 if (new_color != NULL)
2079 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2081 gtk_widget_destroy (dialog);
2087 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2090 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2091 ModestMsgEditWindowPrivate *priv;
2092 GtkWidget *dialog = NULL;
2094 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2095 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2097 dialog = hildon_color_chooser_new ();
2098 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2099 g_free (buffer_format);
2101 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2103 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2104 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2107 gtk_widget_destroy (dialog);
2112 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2115 ModestMsgEditWindowPrivate *priv;
2116 GtkWidget *dialog = NULL;
2117 GdkColor *old_color = NULL;
2119 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2120 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2122 dialog = hildon_color_chooser_new ();
2123 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2125 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2127 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2128 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2130 gtk_widget_destroy (dialog);
2133 #endif /*!MODEST_HILDON_VERSION_0*/
2137 static TnyStream* create_stream_for_uri (const gchar* uri)
2142 TnyStream *result = NULL;
2144 GnomeVFSHandle *handle = NULL;
2145 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2146 if (test == GNOME_VFS_OK) {
2147 /* Create the tinymail stream: */
2148 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
2149 result = TNY_STREAM (tny_vfs_stream_new (handle));
2156 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2159 ModestMsgEditWindowPrivate *priv;
2160 GtkWidget *dialog = NULL;
2162 GSList *uris = NULL;
2163 GSList *uri_node = NULL;
2165 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2167 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2168 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2169 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2171 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2173 response = gtk_dialog_run (GTK_DIALOG (dialog));
2175 case GTK_RESPONSE_OK:
2176 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2181 gtk_widget_destroy (dialog);
2183 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2185 GnomeVFSHandle *handle = NULL;
2186 GnomeVFSResult result;
2187 GtkTextIter position;
2188 GtkTextMark *insert_mark;
2190 uri = (const gchar *) uri_node->data;
2191 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2192 if (result == GNOME_VFS_OK) {
2194 GnomeVFSFileInfo *info;
2195 gchar *filename, *basename, *escaped_filename;
2196 TnyMimePart *mime_part;
2198 const gchar *mime_type = NULL;
2199 GnomeVFSURI *vfs_uri;
2200 guint64 stream_size;
2202 vfs_uri = gnome_vfs_uri_new (uri);
2204 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2205 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2206 g_free (escaped_filename);
2207 gnome_vfs_uri_unref (vfs_uri);
2208 info = gnome_vfs_file_info_new ();
2210 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2211 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2213 mime_type = gnome_vfs_file_info_get_mime_type (info);
2215 mime_part = tny_platform_factory_new_mime_part
2216 (modest_runtime_get_platform_factory ());
2218 TnyStream *stream = create_stream_for_uri (uri);
2219 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2221 content_id = g_strdup_printf ("%d", priv->last_cid);
2222 tny_mime_part_set_content_id (mime_part, content_id);
2223 g_free (content_id);
2226 basename = g_path_get_basename (filename);
2227 tny_mime_part_set_filename (mime_part, basename);
2230 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2232 if (pixbuf != NULL) {
2233 priv->images_size += stream_size;
2234 priv->images_count ++;
2235 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2236 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2237 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2240 tny_list_prepend (priv->images, (GObject *) mime_part);
2241 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2243 g_object_unref (mime_part);
2244 gnome_vfs_file_info_unref (info);
2253 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2255 GtkWidget *dialog = NULL;
2257 GSList *uris = NULL;
2260 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2261 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2262 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2264 response = gtk_dialog_run (GTK_DIALOG (dialog));
2266 case GTK_RESPONSE_OK:
2267 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2272 gtk_widget_destroy (dialog);
2274 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2275 const gchar *uri = (const gchar *) uri_node->data;
2276 modest_msg_edit_window_attach_file_one (window, uri);
2278 g_slist_foreach (uris, (GFunc) g_free, NULL);
2279 g_slist_free (uris);
2283 modest_msg_edit_window_attach_file_one (
2284 ModestMsgEditWindow *window,
2287 GnomeVFSHandle *handle = NULL;
2288 ModestMsgEditWindowPrivate *priv;
2289 GnomeVFSResult result;
2291 g_return_if_fail (window);
2292 g_return_if_fail (uri);
2294 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2296 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2297 if (result == GNOME_VFS_OK) {
2298 TnyMimePart *mime_part;
2300 const gchar *mime_type = NULL;
2302 gchar *escaped_filename;
2305 GnomeVFSFileInfo *info;
2306 GnomeVFSURI *vfs_uri;
2308 vfs_uri = gnome_vfs_uri_new (uri);
2311 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2312 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2313 g_free (escaped_filename);
2314 gnome_vfs_uri_unref (vfs_uri);
2316 info = gnome_vfs_file_info_new ();
2318 if (gnome_vfs_get_file_info (uri,
2320 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2322 mime_type = gnome_vfs_file_info_get_mime_type (info);
2323 mime_part = tny_platform_factory_new_mime_part
2324 (modest_runtime_get_platform_factory ());
2325 stream = TNY_STREAM (tny_vfs_stream_new (handle));
2327 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2329 g_object_unref (stream);
2331 content_id = g_strdup_printf ("%d", priv->last_cid);
2332 tny_mime_part_set_content_id (mime_part, content_id);
2333 g_free (content_id);
2336 basename = g_path_get_basename (filename);
2337 tny_mime_part_set_filename (mime_part, basename);
2340 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2341 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2343 info->size == 0, info->size);
2344 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2345 gtk_widget_show_all (priv->attachments_caption);
2346 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2348 g_object_unref (mime_part);
2349 gnome_vfs_file_info_unref (info);
2354 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2357 ModestMsgEditWindowPrivate *priv;
2360 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2361 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2363 if (att_list == NULL) {
2364 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2366 g_object_ref (att_list);
2369 if (tny_list_get_length (att_list) == 0) {
2370 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2372 GtkWidget *confirmation_dialog = NULL;
2373 gboolean dialog_response;
2374 gchar *message = NULL;
2375 gchar *filename = NULL;
2377 if (tny_list_get_length (att_list) == 1) {
2379 iter = tny_list_create_iterator (att_list);
2380 part = (TnyMimePart *) tny_iterator_get_current (iter);
2381 g_object_unref (iter);
2382 if (TNY_IS_MSG (part)) {
2383 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2385 filename = g_strdup (tny_header_get_subject (header));
2386 g_object_unref (header);
2388 if (filename == NULL) {
2389 filename = g_strdup (_("mail_va_no_subject"));
2392 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2394 g_object_unref (part);
2396 filename = g_strdup ("");
2398 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2399 (tny_list_get_length (att_list) == 1)), filename);
2401 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
2403 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
2404 gtk_widget_destroy (confirmation_dialog);
2405 if (!dialog_response) {
2406 g_object_unref (att_list);
2409 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2411 for (iter = tny_list_create_iterator (att_list);
2412 !tny_iterator_is_done (iter);
2413 tny_iterator_next (iter)) {
2414 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2415 const gchar *att_id;
2416 tny_list_remove (priv->attachments, (GObject *) mime_part);
2418 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2420 if (tny_list_get_length (priv->attachments) == 0)
2421 gtk_widget_hide (priv->attachments_caption);
2422 att_id = tny_mime_part_get_content_id (mime_part);
2424 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2426 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2427 g_object_unref (mime_part);
2429 g_object_unref (iter);
2432 g_object_unref (att_list);
2434 /* if the last attachment has been removed, focus the Subject: field */
2435 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2436 gtk_widget_grab_focus (priv->subject_field);
2440 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2443 ModestMsgEditWindowPrivate *priv;
2444 GdkColor *new_color;
2445 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2447 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2448 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2451 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2453 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2455 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2457 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2462 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2465 ModestMsgEditWindowPrivate *priv;
2466 gint new_size_index;
2467 ModestMsgEditWindow *window;
2470 window = MODEST_MSG_EDIT_WINDOW (userdata);
2471 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2472 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2474 if (gtk_check_menu_item_get_active (menu_item)) {
2476 WPTextBufferFormat format;
2478 memset (&format, 0, sizeof (format));
2479 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2481 label = gtk_bin_get_child (GTK_BIN (menu_item));
2483 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2484 format.cs.font_size = TRUE;
2485 format.cs.text_position = TRUE;
2486 format.cs.font = TRUE;
2487 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2488 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2490 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2491 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2492 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2494 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2495 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2496 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2502 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2505 ModestMsgEditWindowPrivate *priv;
2506 gint new_font_index;
2507 ModestMsgEditWindow *window;
2510 window = MODEST_MSG_EDIT_WINDOW (userdata);
2511 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2512 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2514 if (gtk_check_menu_item_get_active (menu_item)) {
2517 label = gtk_bin_get_child (GTK_BIN (menu_item));
2519 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2521 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2522 GINT_TO_POINTER(new_font_index)))
2523 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2525 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2526 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2527 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2533 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2535 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2536 ModestWindowPrivate *parent_priv;
2537 ModestWindowMgr *mgr;
2538 gboolean is_fullscreen;
2539 GtkAction *fs_toggle_action;
2542 mgr = modest_runtime_get_window_mgr ();
2543 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2545 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2547 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2548 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2549 if (is_fullscreen != active)
2550 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2558 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2561 ModestMsgEditWindowPrivate *priv = NULL;
2562 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2564 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2565 if (!priv->update_caption_visibility)
2568 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2570 gtk_widget_show (priv->cc_caption);
2572 gtk_widget_hide (priv->cc_caption);
2574 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2578 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2581 ModestMsgEditWindowPrivate *priv = NULL;
2582 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2584 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2585 if (!priv->update_caption_visibility)
2588 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2590 gtk_widget_show (priv->bcc_caption);
2592 gtk_widget_hide (priv->bcc_caption);
2594 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2598 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2599 ModestRecptEditor *editor)
2601 ModestMsgEditWindowPrivate *priv;
2603 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2604 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2605 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2607 if (editor == NULL) {
2608 GtkWidget *view_focus;
2609 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2611 /* This code should be kept in sync with ModestRecptEditor. The
2612 textview inside the recpt editor is the one that really gets the
2613 focus. As it's inside a scrolled window, and this one inside the
2614 hbox recpt editor inherits from, we'll need to go up in the
2615 hierarchy to know if the text view is part of the recpt editor
2616 or if it's a different text entry */
2618 if (gtk_widget_get_parent (view_focus)) {
2619 GtkWidget *first_parent;
2621 first_parent = gtk_widget_get_parent (view_focus);
2622 if (gtk_widget_get_parent (first_parent) &&
2623 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2624 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2629 editor = MODEST_RECPT_EDITOR (priv->to_field);
2633 modest_address_book_select_addresses (editor);
2638 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2640 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2642 modest_msg_edit_window_open_addressbook (window, NULL);
2646 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2647 gboolean show_toolbar)
2649 ModestWindowPrivate *parent_priv;
2650 const gchar *action_name;
2653 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2654 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2656 /* We can not just use the code of
2657 modest_msg_edit_window_setup_toolbar because it has a
2658 mixture of both initialization and creation code. */
2660 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2662 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2664 /* Update also the actions (to update the toggles in the
2665 menus), we have to do it manually because some other window
2666 of the same time could have changed it (remember that the
2667 toolbar fullscreen mode is shared by all the windows of the
2669 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2670 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2672 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2674 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2675 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2681 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2682 TnyHeaderFlags priority_flags)
2684 ModestMsgEditWindowPrivate *priv;
2685 ModestWindowPrivate *parent_priv;
2687 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2689 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2690 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2692 if (priv->priority_flags != priority_flags) {
2693 GtkAction *priority_action = NULL;
2695 priv->priority_flags = priority_flags;
2697 switch (priority_flags) {
2698 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2699 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2700 gtk_widget_show (priv->priority_icon);
2701 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2702 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2704 case TNY_HEADER_FLAG_LOW_PRIORITY:
2705 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2706 gtk_widget_show (priv->priority_icon);
2707 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2708 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2711 gtk_widget_hide (priv->priority_icon);
2712 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2713 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2716 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2717 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2722 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2725 ModestMsgEditWindowPrivate *priv;
2726 ModestWindowPrivate *parent_priv;
2727 gint current_format;
2729 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2731 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2732 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2734 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2735 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2737 if (current_format != file_format) {
2738 switch (file_format) {
2739 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2740 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2741 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2743 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2747 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2748 response = gtk_dialog_run (GTK_DIALOG (dialog));
2749 gtk_widget_destroy (dialog);
2750 if (response == GTK_RESPONSE_OK) {
2751 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2753 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2754 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2759 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2760 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2765 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2768 ModestMsgEditWindowPrivate *priv;
2769 WPTextBufferFormat oldfmt, fmt;
2770 gint old_position = 0;
2774 GdkColor *color = NULL;
2775 gboolean bold, bold_set, italic, italic_set;
2776 gboolean underline, underline_set;
2777 gboolean strikethrough, strikethrough_set;
2778 gboolean position_set;
2779 gboolean font_size_set, font_set, color_set;
2782 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2783 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2785 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2787 /* First we get the currently selected font information */
2788 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2790 switch (oldfmt.text_position) {
2791 case TEXT_POSITION_NORMAL:
2794 case TEXT_POSITION_SUPERSCRIPT:
2802 g_object_set (G_OBJECT (dialog),
2803 "bold", oldfmt.bold != FALSE,
2804 "bold-set", !oldfmt.cs.bold,
2805 "underline", oldfmt.underline != FALSE,
2806 "underline-set", !oldfmt.cs.underline,
2807 "italic", oldfmt.italic != FALSE,
2808 "italic-set", !oldfmt.cs.italic,
2809 "strikethrough", oldfmt.strikethrough != FALSE,
2810 "strikethrough-set", !oldfmt.cs.strikethrough,
2811 "color", &oldfmt.color,
2812 "color-set", !oldfmt.cs.color,
2813 "size", wp_font_size[oldfmt.font_size],
2814 "size-set", !oldfmt.cs.font_size,
2815 "position", old_position,
2816 "position-set", !oldfmt.cs.text_position,
2817 "family", wp_get_font_name (oldfmt.font),
2818 "family-set", !oldfmt.cs.font,
2821 gtk_widget_show_all (dialog);
2822 response = gtk_dialog_run (GTK_DIALOG (dialog));
2823 if (response == GTK_RESPONSE_OK) {
2825 g_object_get( dialog,
2827 "bold-set", &bold_set,
2828 "underline", &underline,
2829 "underline-set", &underline_set,
2831 "italic-set", &italic_set,
2832 "strikethrough", &strikethrough,
2833 "strikethrough-set", &strikethrough_set,
2835 "color-set", &color_set,
2837 "size-set", &font_size_set,
2838 "family", &font_name,
2839 "family-set", &font_set,
2840 "position", &position,
2841 "position-set", &position_set,
2846 if (response == GTK_RESPONSE_OK) {
2847 memset(&fmt, 0, sizeof(fmt));
2853 fmt.italic = italic;
2854 fmt.cs.italic = TRUE;
2856 if (underline_set) {
2857 fmt.underline = underline;
2858 fmt.cs.underline = TRUE;
2860 if (strikethrough_set) {
2861 fmt.strikethrough = strikethrough;
2862 fmt.cs.strikethrough = TRUE;
2867 ? TEXT_POSITION_NORMAL
2868 : ( ( position == 1 )
2869 ? TEXT_POSITION_SUPERSCRIPT
2870 : TEXT_POSITION_SUBSCRIPT );
2871 fmt.cs.text_position = TRUE;
2872 fmt.font_size = oldfmt.font_size;
2876 fmt.cs.color = TRUE;
2879 fmt.font = wp_get_font_index(font_name,
2884 if (font_size_set) {
2885 fmt.cs.font_size = TRUE;
2886 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2888 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2889 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2891 gtk_widget_destroy (dialog);
2893 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2897 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2899 ModestMsgEditWindowPrivate *priv;
2901 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2902 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2904 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2906 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2907 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2912 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2914 ModestMsgEditWindowPrivate *priv;
2916 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2917 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2919 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2921 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2922 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2927 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2929 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2931 priv->can_undo = can_undo;
2935 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2937 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2939 priv->can_redo = can_redo;
2943 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2945 ModestMsgEditWindowPrivate *priv;
2946 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2947 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2949 return priv->can_undo;
2953 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2955 ModestMsgEditWindowPrivate *priv;
2956 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2957 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2959 return priv->can_redo;
2964 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2967 GtkTextIter match_start, match_end;
2969 if (image_id == NULL)
2972 gtk_text_buffer_get_start_iter (buffer, &iter);
2974 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2975 GSList *tags = gtk_text_iter_get_tags (&match_start);
2977 for (node = tags; node != NULL; node = g_slist_next (node)) {
2978 GtkTextTag *tag = (GtkTextTag *) node->data;
2979 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2980 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2981 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2983 offset = gtk_text_iter_get_offset (&match_start);
2984 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2985 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2989 gtk_text_iter_forward_char (&iter);
2994 message_is_empty (ModestMsgEditWindow *window)
2996 ModestMsgEditWindowPrivate *priv = NULL;
2998 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2999 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3001 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3002 * so we can ignore markup.
3004 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3007 count = gtk_text_buffer_get_char_count (buf);
3013 msg_body_focus (GtkWidget *focus,
3014 GdkEventFocus *event,
3018 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3019 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3020 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3025 recpt_field_changed (GtkTextBuffer *buffer,
3026 ModestMsgEditWindow *editor)
3028 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3029 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3033 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3035 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3036 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3040 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3043 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3044 GtkTextBuffer *buffer;
3046 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3047 gtk_text_buffer_set_modified (buffer, modified);
3048 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3049 gtk_text_buffer_set_modified (buffer, modified);
3050 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3051 gtk_text_buffer_set_modified (buffer, modified);
3052 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3056 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3058 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3059 const char *account_name;
3060 GtkTextBuffer *buffer;
3062 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3063 if (gtk_text_buffer_get_modified (buffer))
3065 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3066 if (gtk_text_buffer_get_modified (buffer))
3068 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3069 if (gtk_text_buffer_get_modified (buffer))
3071 if (gtk_text_buffer_get_modified (priv->text_buffer))
3073 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3074 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3085 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3087 ModestMsgEditWindowPrivate *priv = NULL;
3089 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3090 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3092 /* check if there's no recipient added */
3093 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3094 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3095 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3096 /* no recipient contents, then select contacts */
3097 modest_msg_edit_window_open_addressbook (window, NULL);
3101 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3102 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3105 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3106 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3109 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3110 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3114 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3115 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3116 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3123 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3124 ModestMsgEditWindow *window)
3126 modest_msg_edit_window_offer_attach_file (window);
3130 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3132 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3134 return priv->clipboard_text;
3138 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3140 ModestMsgEditWindow *window)
3142 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3143 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3145 if (!GTK_WIDGET_VISIBLE (window))
3148 g_object_ref (window);
3149 text = gtk_clipboard_wait_for_text (selection_clipboard);
3151 if (priv->clipboard_text != NULL) {
3152 g_free (priv->clipboard_text);
3154 priv->clipboard_text = text;
3156 if (GTK_WIDGET_VISIBLE (window)) {
3157 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3159 g_object_unref (window);
3162 static gboolean clipboard_owner_change_idle (gpointer userdata)
3164 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3165 ModestMsgEditWindowPrivate *priv;
3167 gdk_threads_enter ();
3168 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3169 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3171 priv->clipboard_owner_idle = 0;
3172 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3173 gdk_threads_leave ();
3179 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3181 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3182 if (priv->clipboard_owner_idle == 0) {
3183 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3188 subject_field_move_cursor (GtkEntry *entry,
3189 GtkMovementStep step,
3194 if (!GTK_WIDGET_VISIBLE (window))
3197 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3201 update_window_title (ModestMsgEditWindow *window)
3203 ModestMsgEditWindowPrivate *priv = NULL;
3204 const gchar *subject;
3206 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3207 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3208 if (subject == NULL || subject[0] == '\0')
3209 subject = _("mail_va_new_email");
3211 gtk_window_set_title (GTK_WINDOW (window), subject);
3216 subject_field_changed (GtkEditable *editable,
3217 ModestMsgEditWindow *window)
3219 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3220 update_window_title (window);
3221 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3222 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3223 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3227 subject_field_insert_text (GtkEditable *editable,
3229 gint new_text_length,
3231 ModestMsgEditWindow *window)
3233 GString *result = g_string_new ("");
3235 gint result_len = 0;
3236 const gchar *entry_text = NULL;
3239 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3240 old_length = g_utf8_strlen (entry_text, -1);
3242 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3243 gunichar c = g_utf8_get_char_validated (current, 8);
3244 /* Invalid unichar, stop */
3250 result = g_string_append_unichar (result, c);
3254 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3255 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3258 /* Prevent endless recursion */
3259 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3260 g_signal_emit_by_name (editable, "insert-text",
3261 (gpointer) result->str, (gpointer) result->len,
3262 (gpointer) position, (gpointer) window);
3263 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3267 if (result_len + old_length > 1000) {
3268 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3269 dgettext("hildon-common-strings",
3270 "ckdg_ib_maximum_characters_reached"));
3273 g_string_free (result, TRUE);
3277 text_buffer_insert_text (GtkTextBuffer *buffer,
3280 gint new_text_length,
3281 ModestMsgEditWindow *window)
3283 GString *result = g_string_new ("");
3285 gint result_len = 0;
3286 gboolean changed = FALSE;
3288 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3289 gunichar c = g_utf8_get_char_validated (current, 8);
3290 /* Invalid unichar, stop */
3296 result = g_string_append_c (result, ' ');
3300 result = g_string_append_unichar (result, c);
3306 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3307 g_signal_handlers_block_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3308 g_signal_emit_by_name (buffer, "insert-text",
3310 (gpointer) result->str, (gpointer) result->len,
3312 g_signal_handlers_unblock_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3315 g_string_free (result, TRUE);
3319 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3322 ModestMsgEditWindowPrivate *priv = NULL;
3324 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3325 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3327 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3330 gtk_widget_show_all (priv->find_toolbar);
3331 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3333 gtk_widget_hide_all (priv->find_toolbar);
3334 gtk_widget_grab_focus (priv->msg_body);
3340 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3342 GtkTextIter *match_start,
3343 GtkTextIter *match_end)
3345 GtkTextIter end_iter;
3346 gchar *str_casefold;
3349 gchar *range_casefold;
3352 gboolean result = FALSE;
3359 gtk_text_iter_forward_to_end (&end_iter);
3361 str_casefold = g_utf8_casefold (str, -1);
3362 str_chars_n = strlen (str);
3364 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3365 range_casefold = g_utf8_casefold (range_text, -1);
3366 range_chars_n = strlen (range_casefold);
3368 if (range_chars_n < str_chars_n) {
3369 g_free (str_casefold);
3370 g_free (range_text);
3371 g_free (range_casefold);
3375 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3376 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3377 if (!g_utf8_collate (range_subtext, str_casefold)) {
3378 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3380 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3381 match_start, match_end, NULL);
3382 g_free (found_text);
3384 g_free (range_subtext);
3388 g_free (str_casefold);
3389 g_free (range_text);
3390 g_free (range_casefold);
3397 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3398 ModestMsgEditWindow *window)
3400 gchar *current_search = NULL;
3401 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3403 GtkTextIter selection_start, selection_end;
3404 GtkTextIter match_start, match_end;
3405 gboolean continue_search = FALSE;
3407 if (message_is_empty (window)) {
3408 g_free (priv->last_search);
3409 priv->last_search = NULL;
3410 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3414 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3415 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3416 g_free (current_search);
3417 g_free (priv->last_search);
3418 priv->last_search = NULL;
3419 /* Information banner about empty search */
3420 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3424 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3425 continue_search = TRUE;
3427 g_free (priv->last_search);
3428 priv->last_search = g_strdup (current_search);
3431 if (continue_search) {
3432 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3433 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3434 &match_start, &match_end);
3436 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3438 GtkTextIter buffer_start;
3439 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3440 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3441 &match_start, &match_end);
3443 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3446 /* Mark as selected the string found in search */
3448 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3449 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3450 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3452 g_free (priv->last_search);
3453 priv->last_search = NULL;
3455 g_free (current_search);
3459 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3460 ModestMsgEditWindow *window)
3462 GtkToggleAction *toggle;
3463 ModestWindowPrivate *parent_priv;
3464 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3466 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3467 gtk_toggle_action_set_active (toggle, FALSE);
3471 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3473 ModestMsgEditWindowPrivate *priv;
3475 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3480 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3483 ModestMsgEditWindowPrivate *priv;
3485 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3491 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3494 ModestMsgEditWindowPrivate *priv;
3495 TnyHeader *header = NULL;
3497 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3498 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3501 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3503 if (priv->draft_msg != NULL) {
3504 g_object_unref (priv->draft_msg);
3507 if (draft != NULL) {
3508 g_object_ref (draft);
3509 header = tny_msg_get_header (draft);
3510 if (priv->msg_uid) {
3511 g_free (priv->msg_uid);
3512 priv->msg_uid = NULL;
3514 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3515 if (GTK_WIDGET_REALIZED (window))
3516 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3519 priv->draft_msg = draft;
3523 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3524 GtkTextIter *start, GtkTextIter *end,
3527 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3528 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3531 if (tag == NULL+13) return;
3532 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3533 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3534 replace_with_images (window, priv->images);
3539 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3542 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3544 g_return_if_fail (TNY_IS_MIME_PART (part));
3545 tny_list_prepend (priv->attachments, (GObject *) part);
3546 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3547 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3548 gtk_widget_show_all (priv->attachments_caption);
3549 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3553 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3555 ModestMsgEditWindowPrivate *priv;
3557 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3558 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3560 return priv->msg_uid;
3564 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3565 ModestMsgEditWindowWidgetType widget_type)
3567 ModestMsgEditWindowPrivate *priv;
3569 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3570 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3572 switch (widget_type) {
3573 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3574 return priv->msg_body;
3576 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3577 return priv->to_field;
3579 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3580 return priv->cc_field;
3582 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3583 return priv->bcc_field;
3585 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3586 return priv->subject_field;
3588 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3589 return priv->attachments_view;
3597 remove_tags (WPTextBuffer *buffer)
3599 GtkTextIter start, end;
3601 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3602 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3604 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3608 on_account_removed (TnyAccountStore *account_store,
3609 TnyAccount *account,
3612 /* Do nothing if it's a store account, because we use the
3613 transport to send the messages */
3614 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3615 const gchar *parent_acc = NULL;
3616 const gchar *our_acc = NULL;
3618 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3619 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3620 /* Close this window if I'm showing a message of the removed account */
3621 if (strcmp (parent_acc, our_acc) == 0)
3622 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3627 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3629 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3631 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3637 set_zoom_do_nothing (ModestWindow *window,
3643 get_zoom_do_nothing (ModestWindow *window)