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>
38 #include <tny-camel-mem-stream.h>
42 #include <modest-account-mgr.h>
43 #include <modest-account-mgr-helpers.h>
45 #include <widgets/modest-msg-edit-window.h>
46 #include <widgets/modest-combo-box.h>
47 #include <widgets/modest-recpt-editor.h>
48 #include <widgets/modest-attachments-view.h>
50 #include <modest-runtime.h>
52 #include "modest-platform.h"
53 #include "modest-icon-names.h"
54 #include "modest-widget-memory.h"
55 #include "modest-window-priv.h"
56 #include "modest-mail-operation.h"
57 #include "modest-tny-platform-factory.h"
58 #include "modest-tny-msg.h"
59 #include "modest-tny-folder.h"
60 #include "modest-tny-account.h"
61 #include "modest-address-book.h"
62 #include "modest-text-utils.h"
63 #include <tny-simple-list.h>
64 #include <wptextview.h>
65 #include <wptextbuffer.h>
66 #include "modest-scroll-area.h"
67 #include "modest-msg-edit-window-ui-dimming.h"
69 #include "modest-hildon-includes.h"
70 #ifdef MODEST_HAVE_HILDON0_WIDGETS
71 #include <hildon-widgets/hildon-color-chooser.h>
73 #include "widgets/modest-msg-edit-window-ui.h"
74 #ifdef MODEST_HAVE_HILDON0_WIDGETS
75 #include <libgnomevfs/gnome-vfs-mime-utils.h>
77 #include <libgnomevfs/gnome-vfs-mime.h>
79 #include <modest-utils.h>
80 #include "modest-maemo-utils.h"
83 #define DEFAULT_FONT_SIZE 3
84 #define DEFAULT_FONT 2
85 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
86 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
87 #define DEFAULT_MAIN_VBOX_SPACING 6
88 #define SUBJECT_MAX_LENGTH 1000
89 #define IMAGE_MAX_WIDTH 560
90 #define DEFAULT_FONT_SCALE 1.5
92 static gboolean is_wp_text_buffer_started = FALSE;
94 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
95 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
96 static void modest_msg_edit_window_finalize (GObject *obj);
98 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
99 static void body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
100 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
102 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
103 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
104 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
105 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
106 GtkTextIter *start, GtkTextIter *end,
108 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
109 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
110 static void subject_field_insert_text (GtkEditable *editable,
112 gint new_text_length,
114 ModestMsgEditWindow *window);
115 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
117 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
119 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
121 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
122 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
123 GdkEventWindowState *event,
125 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
126 ModestRecptEditor *editor);
127 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
128 ModestMsgEditWindow *window);
130 /* ModestWindow methods implementation */
131 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
132 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
133 gboolean show_toolbar);
134 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
136 ModestMsgEditWindow *window);
137 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
138 static void subject_field_move_cursor (GtkEntry *entry,
139 GtkMovementStep step,
143 static void update_window_title (ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
149 ModestMsgEditWindow *window);
150 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
152 GtkTextIter *match_start,
153 GtkTextIter *match_end);
155 static void remove_tags (WPTextBuffer *buffer);
157 static void on_account_removed (TnyAccountStore *account_store,
161 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
162 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
163 static gdouble get_zoom_do_nothing (ModestWindow *window);
165 static void init_window (ModestMsgEditWindow *obj);
167 gboolean scroll_drag_timeout (gpointer userdata);
168 static void correct_scroll (ModestMsgEditWindow *w);
169 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
170 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
171 ModestMsgEditWindow *userdata);
172 static void text_buffer_mark_set (GtkTextBuffer *buffer,
175 ModestMsgEditWindow *userdata);
176 void vadj_changed (GtkAdjustment *adj,
177 ModestMsgEditWindow *window);
179 static void DEBUG_BUFFER (WPTextBuffer *buffer)
183 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
185 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
186 while (!gtk_text_iter_is_end (&iter)) {
187 GString *output = g_string_new ("");
188 GSList *toggled_tags;
191 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
192 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
193 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
194 GtkTextTag *tag = (GtkTextTag *) node->data;
196 g_object_get (G_OBJECT (tag), "name", &name, NULL);
197 output = g_string_append (output, name);
198 g_string_append (output, " ");
200 output = g_string_append (output, "] OPENED [ ");
201 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
202 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
203 GtkTextTag *tag = (GtkTextTag *) node->data;
205 g_object_get (G_OBJECT (tag), "name", &name, NULL);
206 output = g_string_append (output, name);
207 g_string_append (output, " ");
209 output = g_string_append (output, "]\n");
210 g_message ("%s", output->str);
211 g_string_free (output, TRUE);
212 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
214 g_message ("END BUFFER");
219 /* static gboolean */
220 /* on_key_pressed (GtkWidget *self, */
221 /* GdkEventKey *event, */
222 /* gpointer user_data); */
224 /* list my signals */
231 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
232 struct _ModestMsgEditWindowPrivate {
235 GtkWidget *header_box;
237 ModestPairList *from_field_protos;
238 GtkWidget *from_field;
239 gchar *original_account_name;
243 GtkWidget *bcc_field;
244 GtkWidget *subject_field;
245 GtkWidget *attachments_view;
246 GtkWidget *priority_icon;
247 GtkWidget *add_attachment_button;
249 GtkWidget *cc_caption;
250 GtkWidget *bcc_caption;
251 gboolean update_caption_visibility;
252 GtkWidget *attachments_caption;
254 GtkTextBuffer *text_buffer;
256 GtkWidget *font_size_toolitem;
257 GtkWidget *font_face_toolitem;
258 GtkWidget *font_color_button;
259 GSList *font_items_group;
260 GtkWidget *font_tool_button_label;
261 GSList *size_items_group;
262 GtkWidget *size_tool_button_label;
264 GtkWidget *find_toolbar;
267 GtkWidget *font_dialog;
270 guint scroll_drag_timeout_id;
274 TnyList *attachments;
279 TnyHeaderFlags priority_flags;
281 gboolean can_undo, can_redo;
282 gulong clipboard_change_handler_id;
283 gulong default_clipboard_change_handler_id;
284 gulong account_removed_handler_id;
285 guint clipboard_owner_idle;
286 gchar *clipboard_text;
295 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
296 MODEST_TYPE_MSG_EDIT_WINDOW, \
297 ModestMsgEditWindowPrivate))
299 static GtkWindowClass *parent_class = NULL;
301 /* uncomment the following if you have defined any signals */
302 /* static guint signals[LAST_SIGNAL] = {0}; */
305 modest_msg_edit_window_get_type (void)
307 static GType my_type = 0;
309 static const GTypeInfo my_info = {
310 sizeof(ModestMsgEditWindowClass),
311 NULL, /* base init */
312 NULL, /* base finalize */
313 (GClassInitFunc) modest_msg_edit_window_class_init,
314 NULL, /* class finalize */
315 NULL, /* class data */
316 sizeof(ModestMsgEditWindow),
318 (GInstanceInitFunc) modest_msg_edit_window_init,
321 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
322 "ModestMsgEditWindow",
330 save_state (ModestWindow *self)
332 modest_widget_memory_save (modest_runtime_get_conf(),
333 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
338 restore_settings (ModestMsgEditWindow *self)
340 ModestConf *conf = NULL;
342 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
344 conf = modest_runtime_get_conf ();
345 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
346 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
347 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
348 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
349 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
350 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
351 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
352 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
354 /* set initial state of cc and bcc */
355 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
356 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
357 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
359 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
360 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
362 /* Dim at start clipboard actions */
363 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
364 gtk_action_set_sensitive (action, FALSE);
365 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
366 gtk_action_set_sensitive (action, FALSE);
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
368 gtk_action_set_sensitive (action, FALSE);
370 modest_widget_memory_restore (conf,
371 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
376 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
378 GObjectClass *gobject_class;
379 ModestWindowClass *modest_window_class;
380 gobject_class = (GObjectClass*) klass;
381 modest_window_class = (ModestWindowClass*) klass;
383 parent_class = g_type_class_peek_parent (klass);
384 gobject_class->finalize = modest_msg_edit_window_finalize;
386 modest_window_class->set_zoom_func = set_zoom_do_nothing;
387 modest_window_class->get_zoom_func = get_zoom_do_nothing;
388 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
389 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
390 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
391 modest_window_class->save_state_func = save_state;
392 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
394 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
398 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
400 ModestMsgEditWindowPrivate *priv;
401 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
403 priv->msg_body = NULL;
405 priv->from_field = NULL;
406 priv->to_field = NULL;
407 priv->cc_field = NULL;
408 priv->bcc_field = NULL;
409 priv->subject_field = NULL;
410 priv->attachments = TNY_LIST (tny_simple_list_new ());
411 priv->images = TNY_LIST (tny_simple_list_new ());
412 priv->images_size = 0;
413 priv->images_count = 0;
416 priv->cc_caption = NULL;
417 priv->bcc_caption = NULL;
418 priv->update_caption_visibility = FALSE;
420 priv->priority_flags = 0;
422 priv->find_toolbar = NULL;
423 priv->last_search = NULL;
425 priv->draft_msg = NULL;
426 priv->outbox_msg = NULL;
427 priv->msg_uid = NULL;
429 priv->can_undo = FALSE;
430 priv->can_redo = FALSE;
431 priv->clipboard_change_handler_id = 0;
432 priv->default_clipboard_change_handler_id = 0;
433 priv->account_removed_handler_id = 0;
434 priv->clipboard_owner_idle = 0;
435 priv->clipboard_text = NULL;
438 priv->scroll_drag_timeout_id = 0;
439 priv->last_upper = 0.0;
441 priv->font_dialog = NULL;
443 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
444 GTK_WINDOW(obj),"applications_email_editor");
446 if (!is_wp_text_buffer_started) {
447 is_wp_text_buffer_started = TRUE;
448 wp_text_buffer_library_init ();
453 hildon_program_add_window (hildon_program_get_instance(),
458 /* FIXME: this is a dup from the one in gtk/ */
461 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
463 static ModestPairList*
464 get_transports (void)
466 GSList *transports = NULL;
468 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
469 GSList *accounts = modest_account_mgr_account_names (account_mgr,
470 TRUE /* only enabled accounts. */);
472 GSList *cursor = accounts;
474 gchar *account_name = cursor->data;
475 gchar *from_string = NULL;
477 from_string = modest_account_mgr_get_from_string (account_mgr,
481 if (from_string && account_name) {
482 gchar *name = account_name;
483 ModestPair *pair = modest_pair_new ((gpointer) name,
484 (gpointer) from_string , TRUE);
485 transports = g_slist_prepend (transports, pair);
488 cursor = cursor->next;
490 g_slist_free (accounts); /* only free the accounts, not the elements,
491 * because they are used in the pairlist */
495 static void window_focus (GtkWindow *window,
499 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
503 scroll_drag_timeout (gpointer userdata)
505 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
506 ModestMsgEditWindowPrivate *priv;
508 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
510 correct_scroll_without_drag_check (win, TRUE);
512 priv->scroll_drag_timeout_id = 0;
518 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
520 ModestMsgEditWindowPrivate *priv;
523 GdkRectangle rectangle;
529 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
531 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
534 insert = gtk_text_buffer_get_insert (priv->text_buffer);
535 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
537 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
538 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
539 offset = priv->msg_body->allocation.y;
541 new_value = vadj->value;
543 if ((offset + rectangle.y + rectangle.height) >
544 ((gint) (vadj->value +vadj->page_size))) {
545 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
546 if (new_value > vadj->upper - vadj->page_size)
547 new_value = vadj->upper - vadj->page_size;
548 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
549 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
550 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
551 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
554 if (new_value > vadj->value)
555 new_value = vadj->value;
558 if (vadj->value != new_value) {
559 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
561 vadj->value = new_value;
562 gtk_adjustment_value_changed (vadj);
563 /* invalidate body */
564 window = gtk_widget_get_parent_window (priv->msg_body);
566 gdk_window_invalidate_rect (window, NULL, TRUE);
572 correct_scroll (ModestMsgEditWindow *w)
574 ModestMsgEditWindowPrivate *priv;
576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
577 if (gtk_grab_get_current () == priv->msg_body) {
578 if (priv->scroll_drag_timeout_id == 0) {
579 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
585 correct_scroll_without_drag_check (w, TRUE);
589 text_buffer_end_user_action (GtkTextBuffer *buffer,
590 ModestMsgEditWindow *userdata)
593 correct_scroll (userdata);
597 text_buffer_mark_set (GtkTextBuffer *buffer,
600 ModestMsgEditWindow *userdata)
602 gtk_text_buffer_begin_user_action (buffer);
603 gtk_text_buffer_end_user_action (buffer);
607 cut_clipboard_check (GtkTextView *text_view,
610 GtkTextBuffer *buffer;
612 buffer = gtk_text_view_get_buffer (text_view);
613 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
614 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
619 copy_clipboard_check (GtkTextView *text_view,
622 GtkTextBuffer *buffer;
624 buffer = gtk_text_view_get_buffer (text_view);
625 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
626 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
630 void vadj_changed (GtkAdjustment *adj,
631 ModestMsgEditWindow *window)
633 ModestMsgEditWindowPrivate *priv;
635 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
637 if (priv->last_upper != adj->upper) {
638 priv->last_upper = adj->upper;
639 correct_scroll (window);
644 connect_signals (ModestMsgEditWindow *obj)
646 ModestMsgEditWindowPrivate *priv;
648 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
650 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
651 G_CALLBACK (text_buffer_refresh_attributes), obj);
652 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
653 G_CALLBACK (text_buffer_can_undo), obj);
654 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
655 G_CALLBACK (text_buffer_can_redo), obj);
656 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
657 G_CALLBACK (body_changed), obj);
658 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
659 G_CALLBACK (body_changed), obj);
660 g_signal_connect (G_OBJECT (obj), "window-state-event",
661 G_CALLBACK (modest_msg_edit_window_window_state_event),
663 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
664 G_CALLBACK (text_buffer_end_user_action), obj);
665 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
666 G_CALLBACK (text_buffer_mark_set), obj);
667 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
668 G_CALLBACK (text_buffer_apply_tag), obj);
669 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
670 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
671 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
672 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
673 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
674 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
676 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
677 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
679 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
680 G_CALLBACK (msg_body_focus), obj);
681 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
682 G_CALLBACK (msg_body_focus), obj);
683 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
684 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
685 "changed", G_CALLBACK (recpt_field_changed), obj);
686 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
687 "changed", G_CALLBACK (recpt_field_changed), obj);
688 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
689 "changed", G_CALLBACK (recpt_field_changed), obj);
690 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
691 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
692 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
694 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
695 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
697 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
699 G_CALLBACK (vadj_changed),
702 priv->clipboard_change_handler_id =
703 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
704 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
705 priv->default_clipboard_change_handler_id =
706 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
707 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
709 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
710 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
715 init_window (ModestMsgEditWindow *obj)
717 GtkWidget *from_caption, *to_caption, *subject_caption;
718 GtkWidget *main_vbox;
719 ModestMsgEditWindowPrivate *priv;
720 GtkActionGroup *action_group;
721 ModestWindowPrivate *parent_priv;
722 GdkPixbuf *window_icon = NULL;
723 GError *error = NULL;
725 GtkSizeGroup *size_group;
726 GtkWidget *subject_box;
727 GtkWidget *attachment_icon;
728 GtkWidget *window_box;
729 #if (GTK_MINOR_VERSION >= 10)
730 GdkAtom deserialize_type;
732 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
733 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
735 parent_priv->ui_manager = gtk_ui_manager_new();
736 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
737 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
739 /* Add common actions */
740 gtk_action_group_add_actions (action_group,
741 modest_msg_edit_action_entries,
742 G_N_ELEMENTS (modest_msg_edit_action_entries),
744 gtk_action_group_add_toggle_actions (action_group,
745 modest_msg_edit_toggle_action_entries,
746 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
748 gtk_action_group_add_radio_actions (action_group,
749 modest_msg_edit_alignment_radio_action_entries,
750 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
752 G_CALLBACK (modest_ui_actions_on_change_justify),
754 gtk_action_group_add_radio_actions (action_group,
755 modest_msg_edit_priority_action_entries,
756 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
758 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
760 gtk_action_group_add_radio_actions (action_group,
761 modest_msg_edit_file_format_action_entries,
762 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
763 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
764 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
766 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
767 g_object_unref (action_group);
769 /* Load the UI definition */
770 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
773 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
774 g_clear_error (&error);
777 /* Add accelerators */
778 gtk_window_add_accel_group (GTK_WINDOW (obj),
779 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
781 parent_priv->menubar = NULL;
783 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
785 /* Note: This ModestPairList* must exist for as long as the combo
786 * that uses it, because the ModestComboBox uses the ID opaquely,
787 * so it can't know how to manage its memory. */
788 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
790 priv->to_field = modest_recpt_editor_new ();
791 priv->cc_field = modest_recpt_editor_new ();
792 priv->bcc_field = modest_recpt_editor_new ();
793 subject_box = gtk_hbox_new (FALSE, 0);
794 priv->priority_icon = gtk_image_new ();
795 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
796 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
797 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
798 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
799 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
800 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
801 priv->add_attachment_button = gtk_button_new ();
802 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
803 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
804 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
805 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
806 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
807 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
808 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
809 priv->attachments_view = modest_attachments_view_new (NULL);
811 priv->header_box = gtk_vbox_new (FALSE, 0);
813 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
814 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
815 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
816 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
817 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
818 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
819 g_object_unref (size_group);
821 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
822 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
823 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
824 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
825 gtk_size_group_add_widget (size_group, priv->subject_field);
826 gtk_size_group_add_widget (size_group, priv->attachments_view);
827 g_object_unref (size_group);
829 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
830 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
831 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
832 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
833 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
834 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
835 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
838 priv->msg_body = wp_text_view_new ();
839 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
840 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
841 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
842 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
843 #if (GTK_MINOR_VERSION >= 10)
844 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
845 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
847 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
848 deserialize_type, TRUE);
850 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
852 priv->find_toolbar = hildon_find_toolbar_new (NULL);
853 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
855 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
857 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
858 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
859 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
860 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
862 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
864 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
865 priv->frame = gtk_frame_new (NULL);
866 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
868 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
869 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
870 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
872 window_box = gtk_vbox_new (FALSE, 0);
873 gtk_container_add (GTK_CONTAINER(obj), window_box);
875 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
877 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
879 /* Set window icon */
880 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
882 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
883 g_object_unref (window_icon);
888 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
890 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
892 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
893 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
894 priv->clipboard_change_handler_id))
895 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
896 priv->clipboard_change_handler_id);
897 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
898 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
899 priv->default_clipboard_change_handler_id))
900 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
901 priv->default_clipboard_change_handler_id);
903 if (priv->account_removed_handler_id &&
904 g_signal_handler_is_connected (modest_runtime_get_account_store (),
905 priv->account_removed_handler_id))
906 g_signal_handler_disconnect(modest_runtime_get_account_store (),
907 priv->account_removed_handler_id);
911 modest_msg_edit_window_finalize (GObject *obj)
913 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
915 /* Sanity check: shouldn't be needed, the window mgr should
916 call this function before */
917 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
919 if (priv->font_dialog != NULL) {
920 gtk_dialog_response (GTK_DIALOG (priv->font_dialog), GTK_RESPONSE_NONE);
923 if (priv->clipboard_text != NULL) {
924 g_free (priv->clipboard_text);
925 priv->clipboard_text = NULL;
928 if (priv->draft_msg != NULL) {
929 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
930 if (TNY_IS_HEADER (header)) {
931 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
932 modest_window_mgr_unregister_header (mgr, header);
934 g_object_unref (priv->draft_msg);
935 priv->draft_msg = NULL;
937 if (priv->outbox_msg != NULL) {
938 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
939 if (TNY_IS_HEADER (header)) {
940 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
941 modest_window_mgr_unregister_header (mgr, header);
943 g_object_unref (priv->outbox_msg);
944 priv->outbox_msg = NULL;
946 if (priv->scroll_drag_timeout_id > 0) {
947 g_source_remove (priv->scroll_drag_timeout_id);
948 priv->scroll_drag_timeout_id = 0;
950 if (priv->clipboard_owner_idle > 0) {
951 g_source_remove (priv->clipboard_owner_idle);
952 priv->clipboard_owner_idle = 0;
954 if (priv->original_account_name)
955 g_free (priv->original_account_name);
956 g_free (priv->msg_uid);
957 g_free (priv->last_search);
958 g_slist_free (priv->font_items_group);
959 g_slist_free (priv->size_items_group);
960 g_object_unref (priv->attachments);
961 g_object_unref (priv->images);
963 /* This had to stay alive for as long as the combobox that used it: */
964 modest_pair_list_free (priv->from_field_protos);
966 G_OBJECT_CLASS(parent_class)->finalize (obj);
970 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
972 GdkPixbufLoader *loader;
978 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
980 if (loader == NULL) {
986 tny_stream_reset (TNY_STREAM (stream));
987 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
988 GError *error = NULL;
989 unsigned char read_buffer[128];
991 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
993 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
998 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1000 g_object_ref (pixbuf);
1001 gdk_pixbuf_loader_close (loader, NULL);
1002 g_object_unref (loader);
1007 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1008 GdkPixbuf *new_pixbuf;
1010 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1011 gdk_pixbuf_get_width (pixbuf);
1012 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1013 g_object_unref (pixbuf);
1014 pixbuf = new_pixbuf;
1018 *stream_size = size;
1024 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1026 ModestMsgEditWindowPrivate *priv;
1029 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1031 for (iter = tny_list_create_iterator (attachments);
1032 !tny_iterator_is_done (iter);
1033 tny_iterator_next (iter)) {
1034 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1035 const gchar *cid = tny_mime_part_get_content_id (part);
1036 const gchar *mime_type = tny_mime_part_get_content_type (part);
1037 if ((cid != NULL)&&(mime_type != NULL)) {
1038 guint64 stream_size;
1039 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1040 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1043 g_object_unref (stream);
1045 if (pixbuf != NULL) {
1046 priv->images_count ++;
1047 priv->images_size += stream_size;
1048 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1049 g_object_unref (pixbuf);
1052 g_object_unref (part);
1054 g_object_unref (iter);
1058 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1060 TnyMimePart *parent = NULL;
1061 const gchar *content_type = NULL;
1062 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1064 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1066 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1067 parent = g_object_ref (msg);
1068 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1069 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1072 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1073 iter = tny_list_create_iterator (parts);
1074 while (!tny_iterator_is_done (iter)) {
1076 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1077 content_type = tny_mime_part_get_content_type (part);
1078 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1082 g_object_unref (part);
1084 tny_iterator_next (iter);
1086 g_object_unref (iter);
1087 g_object_unref (parts);
1090 if (parent != NULL) {
1091 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1094 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1095 iter = tny_list_create_iterator (parts);
1096 while (!tny_iterator_is_done (iter)) {
1098 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1099 content_type = tny_mime_part_get_content_type (part);
1100 if (content_type && g_str_has_prefix (content_type, "image/")) {
1101 tny_list_prepend (priv->images, (GObject *) part);
1103 g_object_unref (part);
1104 tny_iterator_next (iter);
1106 g_object_unref (iter);
1107 g_object_unref (parts);
1108 g_object_unref (parent);
1113 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1116 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1118 for (iter = tny_list_create_iterator (attachments) ;
1119 !tny_iterator_is_done (iter);
1120 tny_iterator_next (iter)) {
1121 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1122 const gchar *cid = tny_mime_part_get_content_id (part);
1124 char *invalid = NULL;
1125 gint int_cid = strtol (cid, &invalid, 10);
1126 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1127 priv->next_cid = int_cid + 1;
1130 g_object_unref (part);
1132 g_object_unref (iter);
1136 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1139 gchar *to, *cc, *bcc, *subject;
1141 ModestMsgEditWindowPrivate *priv;
1143 TnyHeaderFlags priority_flags;
1144 TnyFolder *msg_folder;
1145 gboolean is_html = FALSE;
1147 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1148 g_return_if_fail (TNY_IS_MSG (msg));
1150 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1152 header = tny_msg_get_header (msg);
1153 to = tny_header_dup_to (header);
1154 cc = tny_header_dup_cc (header);
1155 bcc = tny_header_dup_bcc (header);
1156 subject = tny_header_dup_subject (header);
1157 priority_flags = tny_header_get_priority (header);
1160 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1162 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1163 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1164 gtk_widget_show (priv->cc_caption);
1165 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1166 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1167 gtk_widget_hide (priv->cc_caption);
1170 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1171 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1172 gtk_widget_show (priv->bcc_caption);
1173 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1174 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1175 gtk_widget_hide (priv->bcc_caption);
1178 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1179 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1182 update_window_title (self);
1184 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1185 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1187 if ((body == NULL)||(body[0] == '\0')) {
1189 body = modest_text_utils_convert_to_html ("");
1192 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1193 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1196 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1199 /* Add attachments to the view */
1200 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1201 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1202 if (tny_list_get_length (priv->attachments) == 0) {
1203 gtk_widget_hide (priv->attachments_caption);
1205 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1206 gtk_widget_show_all (priv->attachments_caption);
1208 get_related_images (self, msg);
1209 update_next_cid (self, priv->attachments);
1210 update_next_cid (self, priv->images);
1211 replace_with_images (self, priv->images);
1213 if (preserve_is_rich && !is_html) {
1214 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1215 /* Get the default format required from configuration */
1216 } else if (!preserve_is_rich && !modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1217 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1220 /* Set the default focus depending on having already a To: field or not */
1221 if ((!to)||(*to == '\0')) {
1222 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1224 gtk_widget_grab_focus (priv->msg_body);
1227 /* TODO: lower priority, select in the From: combo to the
1228 value that comes from msg <- not sure, should it be
1231 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1233 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1234 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1236 modest_msg_edit_window_set_modified (self, FALSE);
1238 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1239 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1240 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1241 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1243 if (priv->msg_uid) {
1244 g_free (priv->msg_uid);
1245 priv->msg_uid = NULL;
1248 /* we should set a reference to the incoming message if it is a draft */
1249 msg_folder = tny_msg_get_folder (msg);
1251 if (modest_tny_folder_is_local_folder (msg_folder)) {
1252 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1253 if (type == TNY_FOLDER_TYPE_INVALID)
1254 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1256 if (type == TNY_FOLDER_TYPE_DRAFTS)
1257 priv->draft_msg = g_object_ref(msg);
1258 if (type == TNY_FOLDER_TYPE_OUTBOX)
1259 priv->outbox_msg = g_object_ref(msg);
1260 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1262 g_object_unref (msg_folder);
1272 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1275 GList *item_children, *node;
1276 GtkWidget *bin_child;
1278 bin_child = gtk_bin_get_child (GTK_BIN(item));
1280 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1282 for (node = item_children; node != NULL; node = g_list_next (node)) {
1283 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1284 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1287 g_list_free (item_children);
1291 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1294 GList *item_children, *node;
1296 box = gtk_bin_get_child (GTK_BIN (item));
1297 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1298 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1300 for (node = item_children; node != NULL; node = g_list_next (node)) {
1301 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1302 if (GTK_IS_TOGGLE_BUTTON (node->data))
1303 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1304 else if (GTK_IS_BUTTON (node->data))
1305 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1307 g_list_free (item_children);
1312 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1314 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1315 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1316 GtkWidget *placeholder;
1317 GtkWidget *tool_item;
1322 GtkWidget *sizes_menu;
1323 GtkWidget *fonts_menu;
1324 GSList *radio_group = NULL;
1325 GSList *node = NULL;
1329 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1330 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1332 /* Font color placeholder */
1333 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1334 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1337 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1338 priv->font_color_button = hildon_color_button_new ();
1339 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1340 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1341 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1342 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1343 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1344 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1345 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1347 G_CALLBACK (modest_msg_edit_window_color_button_change),
1350 /* Font size and face placeholder */
1351 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1352 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1354 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1355 priv->size_tool_button_label = gtk_label_new (NULL);
1356 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1357 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1358 size_text,"</span>", NULL);
1359 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1361 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1362 sizes_menu = gtk_menu_new ();
1363 priv->size_items_group = NULL;
1365 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1366 GtkWidget *size_menu_item;
1368 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1369 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1370 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1371 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1372 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1373 gtk_widget_show (size_menu_item);
1375 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1379 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1380 GtkWidget *item = (GtkWidget *) node->data;
1381 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1385 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1386 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1387 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1388 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1389 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1390 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1391 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1392 priv->font_size_toolitem = tool_item;
1395 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1396 priv->font_tool_button_label = gtk_label_new (NULL);
1397 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1398 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1400 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1401 fonts_menu = gtk_menu_new ();
1402 priv->font_items_group = NULL;
1404 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1405 GtkWidget *font_menu_item;
1406 GtkWidget *child_label;
1408 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1409 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1410 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1411 wp_get_font_name (font_index), "</span>", NULL);
1412 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1415 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1416 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1417 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1418 gtk_widget_show (font_menu_item);
1420 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1423 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1424 GtkWidget *item = (GtkWidget *) node->data;
1425 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1428 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1429 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1430 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1431 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1432 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1433 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1434 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1435 priv->font_face_toolitem = tool_item;
1437 /* Set expand and homogeneous for remaining items */
1438 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1439 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1440 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1441 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1442 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1443 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1444 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1445 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1446 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1448 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1449 will not show the tool items added to the placeholders) */
1450 gtk_widget_show_all (parent_priv->toolbar);
1452 /* Set the no show all *after* showing all items. We do not
1453 want the toolbar to be shown with a show all because it
1454 could go agains the gconf setting regarding showing or not
1455 the toolbar of the editor window */
1456 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1462 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1465 ModestWindowPrivate *parent_priv;
1466 ModestMsgEditWindowPrivate *priv;
1467 ModestDimmingRulesGroup *menu_rules_group = NULL;
1468 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1469 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1470 ModestWindowMgr *mgr = NULL;
1472 g_return_val_if_fail (msg, NULL);
1473 g_return_val_if_fail (account_name, NULL);
1475 mgr = modest_runtime_get_window_mgr ();
1477 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1479 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1480 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1482 /* Menubar. Update the state of some toggles */
1483 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1484 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1485 priv->from_field_protos = get_transports ();
1486 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1487 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), (gpointer) account_name);
1488 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1489 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1492 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1494 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1496 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1498 priv->original_account_name = (account_name) ? g_strdup (account_name) : NULL;
1500 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1501 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1502 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1503 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1504 /* Add common dimming rules */
1505 modest_dimming_rules_group_add_rules (menu_rules_group,
1506 modest_msg_edit_window_menu_dimming_entries,
1507 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1508 MODEST_WINDOW (obj));
1509 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1510 modest_msg_edit_window_toolbar_dimming_entries,
1511 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1512 MODEST_WINDOW (obj));
1513 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1514 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1515 MODEST_WINDOW (obj));
1516 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1517 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1518 MODEST_WINDOW (obj));
1519 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1520 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1521 MODEST_WINDOW (obj));
1522 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1523 modest_msg_edit_window_clipboard_dimming_entries,
1524 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1525 MODEST_WINDOW (obj));
1526 /* Insert dimming rules group for this window */
1527 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1528 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1529 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1530 /* Checks the dimming rules */
1531 g_object_unref (menu_rules_group);
1532 g_object_unref (toolbar_rules_group);
1533 g_object_unref (clipboard_rules_group);
1534 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1536 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1538 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1539 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1540 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1541 priv->update_caption_visibility = TRUE;
1543 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1545 /* Track account-removed signal, this window should be closed
1546 in the case we're creating a mail associated to the account
1548 priv->account_removed_handler_id =
1549 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1551 G_CALLBACK(on_account_removed),
1554 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1556 return (ModestWindow*) obj;
1560 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1562 GString **string_buffer = (GString **) user_data;
1564 *string_buffer = g_string_append (*string_buffer, buffer);
1570 * @result: A new string which should be freed with g_free().
1573 get_formatted_data (ModestMsgEditWindow *edit_window)
1575 ModestMsgEditWindowPrivate *priv;
1576 GString *string_buffer = g_string_new ("");
1578 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1580 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1582 modest_text_utils_hyperlinkify (string_buffer);
1584 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1586 return g_string_free (string_buffer, FALSE);
1591 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1594 const gchar *account_name;
1595 ModestMsgEditWindowPrivate *priv;
1596 TnyIterator *att_iter;
1598 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1600 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1602 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1603 g_return_val_if_fail (account_name, NULL);
1606 /* don't free these (except from) */
1607 data = g_slice_new0 (MsgData);
1608 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1610 data->account_name = g_strdup (account_name);
1611 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1612 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1613 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1614 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1615 if (priv->draft_msg) {
1616 data->draft_msg = g_object_ref (priv->draft_msg);
1617 } else if (priv->outbox_msg) {
1618 data->draft_msg = g_object_ref (priv->outbox_msg);
1620 data->draft_msg = NULL;
1623 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1625 gtk_text_buffer_get_bounds (buf, &b, &e);
1626 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1628 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1629 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1631 data->html_body = NULL;
1633 /* deep-copy the data */
1634 att_iter = tny_list_create_iterator (priv->attachments);
1635 data->attachments = NULL;
1636 while (!tny_iterator_is_done (att_iter)) {
1637 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1638 if (!(TNY_IS_MIME_PART(part))) {
1639 g_warning ("strange data in attachment list");
1640 g_object_unref (part);
1641 tny_iterator_next (att_iter);
1644 data->attachments = g_list_append (data->attachments,
1646 tny_iterator_next (att_iter);
1648 g_object_unref (att_iter);
1650 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1651 att_iter = tny_list_create_iterator (priv->images);
1652 data->images = NULL;
1653 while (!tny_iterator_is_done (att_iter)) {
1654 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1656 if (!(TNY_IS_MIME_PART(part))) {
1657 g_warning ("strange data in attachment list");
1658 g_object_unref (part);
1659 tny_iterator_next (att_iter);
1662 cid = tny_mime_part_get_content_id (part);
1664 gchar *image_tag_id;
1665 GtkTextTag *image_tag;
1667 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1668 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1669 g_free (image_tag_id);
1671 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1673 ((gtk_text_iter_has_tag (&iter, image_tag))||
1674 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1675 data->images = g_list_append (data->images,
1676 g_object_ref (part));
1678 g_object_unref (part);
1679 tny_iterator_next (att_iter);
1681 g_object_unref (att_iter);
1683 data->priority_flags = priv->priority_flags;
1690 unref_gobject (GObject *obj, gpointer data)
1692 if (!G_IS_OBJECT(obj))
1694 g_object_unref (obj);
1698 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1701 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1709 g_free (data->from);
1710 g_free (data->subject);
1711 g_free (data->plain_body);
1712 g_free (data->html_body);
1713 g_free (data->account_name);
1715 if (data->draft_msg != NULL) {
1716 g_object_unref (data->draft_msg);
1717 data->draft_msg = NULL;
1720 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1721 g_list_free (data->attachments);
1722 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1723 g_list_free (data->images);
1725 g_slice_free (MsgData, data);
1729 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1731 guint64 *parts_size)
1733 ModestMsgEditWindowPrivate *priv;
1735 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1737 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1739 /* TODO: add images */
1740 *parts_size += priv->images_size;
1741 *parts_count += priv->images_count;
1746 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1749 ModestMsgEditWindowPrivate *priv = NULL;
1750 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1752 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1754 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1756 return MODEST_MSG_EDIT_FORMAT_HTML;
1758 return MODEST_MSG_EDIT_FORMAT_TEXT;
1762 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1763 ModestMsgEditFormat format)
1765 ModestMsgEditWindowPrivate *priv;
1767 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1768 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1771 case MODEST_MSG_EDIT_FORMAT_HTML:
1772 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1774 case MODEST_MSG_EDIT_FORMAT_TEXT:
1775 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1778 g_return_if_reached ();
1782 ModestMsgEditFormatState *
1783 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1785 ModestMsgEditFormatState *format_state = NULL;
1786 ModestMsgEditWindowPrivate *priv;
1787 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1789 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1792 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1794 format_state = g_new0 (ModestMsgEditFormatState, 1);
1795 format_state->bold = buffer_format->bold&0x1;
1796 format_state->italics = buffer_format->italic&0x1;
1797 format_state->bullet = buffer_format->bullet&0x1;
1798 format_state->color = buffer_format->color;
1799 format_state->font_size = buffer_format->font_size;
1800 format_state->font_family = wp_get_font_name (buffer_format->font);
1801 format_state->justification = buffer_format->justification;
1802 g_free (buffer_format);
1804 return format_state;
1809 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1810 const ModestMsgEditFormatState *format_state)
1812 ModestMsgEditWindowPrivate *priv;
1813 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1814 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1815 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1816 g_return_if_fail (format_state != NULL);
1818 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1819 gtk_widget_grab_focus (priv->msg_body);
1820 buffer_format->bold = (format_state->bold != FALSE);
1821 buffer_format->italic = (format_state->italics != FALSE);
1822 buffer_format->color = format_state->color;
1823 buffer_format->font_size = format_state->font_size;
1824 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1825 buffer_format->justification = format_state->justification;
1826 buffer_format->bullet = format_state->bullet;
1828 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1830 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1831 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1832 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1833 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1834 buffer_format->cs.font = (buffer_format->font != current_format->font);
1835 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1836 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1838 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1839 if (buffer_format->cs.bold) {
1840 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1841 GINT_TO_POINTER (buffer_format->bold&0x1));
1843 if (buffer_format->cs.italic) {
1844 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1845 GINT_TO_POINTER (buffer_format->italic&0x1));
1847 if (buffer_format->cs.color) {
1848 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1849 GINT_TO_POINTER (&(buffer_format->color)));
1851 if (buffer_format->cs.font_size) {
1852 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1853 GINT_TO_POINTER (buffer_format->font_size));
1855 if (buffer_format->cs.justification) {
1856 switch (buffer_format->justification) {
1857 case GTK_JUSTIFY_LEFT:
1858 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1859 GINT_TO_POINTER(TRUE));
1861 case GTK_JUSTIFY_CENTER:
1862 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1863 GINT_TO_POINTER(TRUE));
1865 case GTK_JUSTIFY_RIGHT:
1866 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1867 GINT_TO_POINTER(TRUE));
1874 if (buffer_format->cs.font) {
1875 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1876 GINT_TO_POINTER (buffer_format->font));
1878 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1879 if (buffer_format->cs.bullet) {
1880 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1881 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1883 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1885 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1887 g_free (current_format);
1892 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1894 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1896 ModestWindowPrivate *parent_priv;
1897 ModestMsgEditWindowPrivate *priv;
1898 GtkWidget *new_size_menuitem;
1899 GtkWidget *new_font_menuitem;
1901 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1902 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1904 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1905 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1906 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1907 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1909 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1910 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1911 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1914 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1916 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1917 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1919 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1920 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1922 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1923 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1926 switch (buffer_format->justification)
1928 case GTK_JUSTIFY_LEFT:
1929 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1931 case GTK_JUSTIFY_CENTER:
1932 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1934 case GTK_JUSTIFY_RIGHT:
1935 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1942 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1944 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1945 G_CALLBACK (modest_msg_edit_window_color_button_change),
1947 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1948 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1949 G_CALLBACK (modest_msg_edit_window_color_button_change),
1952 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1953 buffer_format->font_size))->data);
1954 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1958 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1959 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1960 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1962 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1963 G_CALLBACK (modest_msg_edit_window_size_change),
1965 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1966 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1967 G_CALLBACK (modest_msg_edit_window_size_change),
1971 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1972 buffer_format->font))->data);
1973 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1977 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1978 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1979 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1981 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1982 G_CALLBACK (modest_msg_edit_window_font_change),
1984 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1985 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1986 G_CALLBACK (modest_msg_edit_window_font_change),
1990 g_free (buffer_format);
1994 #ifdef MODEST_HILDON_VERSION_0
1996 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1999 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2000 ModestMsgEditWindowPrivate *priv;
2001 GtkWidget *dialog = NULL;
2003 GdkColor *new_color = NULL;
2005 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2006 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2008 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2009 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2010 g_free (buffer_format);
2012 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2013 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2014 if (new_color != NULL) {
2015 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2016 (gpointer) new_color);
2019 gtk_widget_destroy (dialog);
2024 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2027 ModestMsgEditWindowPrivate *priv;
2028 GtkWidget *dialog = NULL;
2030 GdkColor *old_color = NULL;
2031 const GdkColor *new_color = NULL;
2033 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2034 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2036 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2037 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2039 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2040 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2041 if (new_color != NULL)
2042 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2044 gtk_widget_destroy (dialog);
2050 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2053 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2054 ModestMsgEditWindowPrivate *priv;
2055 GtkWidget *dialog = NULL;
2057 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2058 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2060 dialog = hildon_color_chooser_new ();
2061 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2062 g_free (buffer_format);
2064 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2066 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2067 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2070 gtk_widget_destroy (dialog);
2075 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2078 ModestMsgEditWindowPrivate *priv;
2079 GtkWidget *dialog = NULL;
2080 GdkColor *old_color = NULL;
2082 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2083 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2085 dialog = hildon_color_chooser_new ();
2086 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2088 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2090 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2091 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2093 gtk_widget_destroy (dialog);
2096 #endif /*!MODEST_HILDON_VERSION_0*/
2101 create_stream_for_uri (const gchar* uri)
2106 TnyStream *result = NULL;
2108 GnomeVFSHandle *handle = NULL;
2109 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2110 if (test == GNOME_VFS_OK) {
2111 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2112 /* Streams over OBEX (Bluetooth) are not seekable but
2113 * we expect them to be (we might need to read them
2114 * several times). So if this is a Bluetooth URI just
2115 * read the whole file into memory (this is not a fast
2116 * protocol so we can assume that these files are not
2117 * going to be very big) */
2118 if ((g_ascii_strncasecmp (uri, "obex://", 7) == 0)||
2119 (g_ascii_strncasecmp (uri, "upnpav://", 9) == 0)) {
2120 TnyStream *memstream = tny_camel_mem_stream_new ();
2121 tny_stream_write_to_stream (vfssstream, memstream);
2122 g_object_unref (vfssstream);
2125 result = vfssstream;
2133 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2136 ModestMsgEditWindowPrivate *priv;
2137 GtkWidget *dialog = NULL;
2139 GSList *uris = NULL;
2140 GSList *uri_node = NULL;
2142 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2144 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2145 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2146 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2148 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2150 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2151 GTK_WINDOW (dialog));
2153 response = gtk_dialog_run (GTK_DIALOG (dialog));
2155 case GTK_RESPONSE_OK:
2156 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2161 gtk_widget_destroy (dialog);
2163 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2165 GnomeVFSHandle *handle = NULL;
2166 GnomeVFSResult result;
2167 GtkTextIter position;
2168 GtkTextMark *insert_mark;
2170 uri = (const gchar *) uri_node->data;
2171 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2172 if (result == GNOME_VFS_OK) {
2174 GnomeVFSFileInfo *info;
2175 gchar *filename, *basename, *escaped_filename;
2176 TnyMimePart *mime_part;
2178 const gchar *mime_type = NULL;
2179 GnomeVFSURI *vfs_uri;
2180 guint64 stream_size;
2182 gnome_vfs_close (handle);
2183 vfs_uri = gnome_vfs_uri_new (uri);
2185 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2186 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2187 g_free (escaped_filename);
2188 gnome_vfs_uri_unref (vfs_uri);
2189 info = gnome_vfs_file_info_new ();
2191 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2192 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2194 mime_type = gnome_vfs_file_info_get_mime_type (info);
2196 mime_part = tny_platform_factory_new_mime_part
2197 (modest_runtime_get_platform_factory ());
2199 TnyStream *stream = create_stream_for_uri (uri);
2201 if (stream == NULL) {
2203 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2205 g_object_unref (mime_part);
2206 gnome_vfs_file_info_unref (info);
2210 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2212 content_id = g_strdup_printf ("%d", priv->next_cid);
2213 tny_mime_part_set_content_id (mime_part, content_id);
2214 g_free (content_id);
2217 basename = g_path_get_basename (filename);
2218 tny_mime_part_set_filename (mime_part, basename);
2221 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2223 if (pixbuf != NULL) {
2224 priv->images_size += stream_size;
2225 priv->images_count ++;
2226 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2227 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2228 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2231 tny_list_prepend (priv->images, (GObject *) mime_part);
2232 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2234 g_object_unref (mime_part);
2235 gnome_vfs_file_info_unref (info);
2244 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2246 GtkWidget *dialog = NULL;
2248 GSList *uris = NULL;
2250 GnomeVFSFileSize total_size, allowed_size;
2251 ModestMsgEditWindowPrivate *priv;
2255 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(window));
2257 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2259 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2262 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2263 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2264 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2265 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
2267 response = gtk_dialog_run (GTK_DIALOG (dialog));
2269 case GTK_RESPONSE_OK:
2270 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2275 gtk_widget_destroy (dialog);
2277 /* allowed size is the maximum size - what's already there */
2278 modest_attachments_view_get_sizes (
2279 MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2280 &att_num, &att_size);
2281 allowed_size = MODEST_MAX_ATTACHMENT_SIZE - att_size;
2284 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2286 const gchar *uri = (const gchar *) uri_node->data;
2288 total_size += modest_msg_edit_window_attach_file_one
2289 (window, uri, allowed_size);
2291 if (total_size > allowed_size) {
2292 g_warning ("%s: total size: %u",
2293 __FUNCTION__, (unsigned int)total_size);
2297 allowed_size -= total_size;
2301 g_slist_foreach (uris, (GFunc) g_free, NULL);
2302 g_slist_free (uris);
2307 modest_msg_edit_window_attach_file_one (ModestMsgEditWindow *window,
2309 GnomeVFSFileSize allowed_size)
2312 GnomeVFSHandle *handle = NULL;
2313 ModestMsgEditWindowPrivate *priv;
2314 GnomeVFSResult result;
2315 GnomeVFSFileSize size = 0;
2317 g_return_val_if_fail (window, 0);
2318 g_return_val_if_fail (uri, 0);
2320 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2322 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2323 if (result == GNOME_VFS_OK) {
2324 TnyMimePart *mime_part;
2326 const gchar *mime_type = NULL;
2328 gchar *escaped_filename;
2331 GnomeVFSFileInfo *info;
2332 GnomeVFSURI *vfs_uri;
2334 gnome_vfs_close (handle);
2335 vfs_uri = gnome_vfs_uri_new (uri);
2338 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2339 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2340 g_free (escaped_filename);
2341 gnome_vfs_uri_unref (vfs_uri);
2343 info = gnome_vfs_file_info_new ();
2345 if (gnome_vfs_get_file_info (uri,
2347 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2349 mime_type = gnome_vfs_file_info_get_mime_type (info);
2350 mime_part = tny_platform_factory_new_mime_part
2351 (modest_runtime_get_platform_factory ());
2353 /* try to get the attachment's size; this may fail for weird
2354 * file systems, like obex, upnp... */
2355 if (allowed_size != 0 &&
2356 info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
2358 if (size > allowed_size) {
2359 g_warning ("%s: attachment too big", __FUNCTION__);
2360 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2364 g_warning ("%s: could not get attachment size", __FUNCTION__);
2366 stream = create_stream_for_uri (uri);
2368 if (stream == NULL) {
2370 modest_platform_information_banner (NULL, NULL, dgettext("hildon-fm", "sfil_ib_opening_not_allowed"));
2372 g_object_unref (mime_part);
2373 gnome_vfs_file_info_unref (info);
2377 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2378 g_object_unref (stream);
2380 content_id = g_strdup_printf ("%d", priv->next_cid);
2381 tny_mime_part_set_content_id (mime_part, content_id);
2382 g_free (content_id);
2385 basename = g_path_get_basename (filename);
2386 tny_mime_part_set_filename (mime_part, basename);
2389 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2390 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2392 info->size == 0, info->size);
2393 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2394 gtk_widget_show_all (priv->attachments_caption);
2395 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2397 g_object_unref (mime_part);
2398 gnome_vfs_file_info_unref (info);
2405 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2408 ModestMsgEditWindowPrivate *priv;
2411 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2412 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2414 if (att_list == NULL) {
2415 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2417 g_object_ref (att_list);
2420 if (tny_list_get_length (att_list) == 0) {
2421 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2423 gboolean dialog_response;
2424 gchar *message = NULL;
2425 gchar *filename = NULL;
2427 if (tny_list_get_length (att_list) == 1) {
2429 iter = tny_list_create_iterator (att_list);
2430 part = (TnyMimePart *) tny_iterator_get_current (iter);
2431 g_object_unref (iter);
2432 if (TNY_IS_MSG (part)) {
2433 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2435 filename = tny_header_dup_subject (header);
2436 g_object_unref (header);
2438 if (filename == NULL) {
2439 filename = g_strdup (_("mail_va_no_subject"));
2442 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2444 g_object_unref (part);
2446 filename = g_strdup ("");
2448 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2449 tny_list_get_length (att_list)), filename);
2452 dialog_response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), message);
2455 if (dialog_response != GTK_RESPONSE_OK) {
2456 g_object_unref (att_list);
2459 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2461 for (iter = tny_list_create_iterator (att_list);
2462 !tny_iterator_is_done (iter);
2463 tny_iterator_next (iter)) {
2464 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2465 const gchar *att_id;
2466 tny_list_remove (priv->attachments, (GObject *) mime_part);
2468 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2470 if (tny_list_get_length (priv->attachments) == 0)
2471 gtk_widget_hide (priv->attachments_caption);
2472 att_id = tny_mime_part_get_content_id (mime_part);
2474 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2476 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2477 g_object_unref (mime_part);
2479 g_object_unref (iter);
2482 g_object_unref (att_list);
2484 /* if the last attachment has been removed, focus the Subject: field */
2485 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2486 gtk_widget_grab_focus (priv->subject_field);
2490 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2493 ModestMsgEditWindowPrivate *priv;
2494 GdkColor *new_color;
2495 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2497 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2498 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2501 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2503 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2505 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2507 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2512 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2515 ModestMsgEditWindowPrivate *priv;
2516 gint new_size_index;
2517 ModestMsgEditWindow *window;
2520 window = MODEST_MSG_EDIT_WINDOW (userdata);
2521 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2522 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2524 if (gtk_check_menu_item_get_active (menu_item)) {
2526 WPTextBufferFormat format;
2528 memset (&format, 0, sizeof (format));
2529 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2531 label = gtk_bin_get_child (GTK_BIN (menu_item));
2533 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2534 format.cs.font_size = TRUE;
2535 format.cs.text_position = TRUE;
2536 format.cs.font = TRUE;
2537 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2538 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2540 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2541 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2542 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2544 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2545 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2546 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2552 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2555 ModestMsgEditWindowPrivate *priv;
2556 gint new_font_index;
2557 ModestMsgEditWindow *window;
2560 window = MODEST_MSG_EDIT_WINDOW (userdata);
2561 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2562 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2564 if (gtk_check_menu_item_get_active (menu_item)) {
2567 label = gtk_bin_get_child (GTK_BIN (menu_item));
2569 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2571 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2572 GINT_TO_POINTER(new_font_index)))
2573 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2575 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2576 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2577 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2583 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2585 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2586 ModestWindowPrivate *parent_priv;
2587 ModestWindowMgr *mgr;
2588 gboolean is_fullscreen;
2589 GtkAction *fs_toggle_action;
2592 mgr = modest_runtime_get_window_mgr ();
2593 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2595 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2597 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2598 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2599 if (is_fullscreen != active)
2600 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2608 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2611 ModestMsgEditWindowPrivate *priv = NULL;
2612 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2614 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2615 if (!priv->update_caption_visibility)
2618 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2620 gtk_widget_show (priv->cc_caption);
2622 gtk_widget_hide (priv->cc_caption);
2624 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2628 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2631 ModestMsgEditWindowPrivate *priv = NULL;
2632 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2634 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2635 if (!priv->update_caption_visibility)
2638 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2640 gtk_widget_show (priv->bcc_caption);
2642 gtk_widget_hide (priv->bcc_caption);
2644 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2648 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2649 ModestRecptEditor *editor)
2651 ModestMsgEditWindowPrivate *priv;
2653 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2654 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2656 /* we check for low-mem; in that case, show a warning, and don't allow
2657 * for the addressbook
2659 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2662 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2664 if (editor == NULL) {
2665 GtkWidget *view_focus;
2666 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2668 /* This code should be kept in sync with ModestRecptEditor. The
2669 textview inside the recpt editor is the one that really gets the
2670 focus. As it's inside a scrolled window, and this one inside the
2671 hbox recpt editor inherits from, we'll need to go up in the
2672 hierarchy to know if the text view is part of the recpt editor
2673 or if it's a different text entry */
2675 if (gtk_widget_get_parent (view_focus)) {
2676 GtkWidget *first_parent;
2678 first_parent = gtk_widget_get_parent (view_focus);
2679 if (gtk_widget_get_parent (first_parent) &&
2680 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2681 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2686 editor = MODEST_RECPT_EDITOR (priv->to_field);
2690 modest_address_book_select_addresses (editor);
2695 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2697 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2699 modest_msg_edit_window_open_addressbook (window, NULL);
2703 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2704 gboolean show_toolbar)
2706 ModestWindowPrivate *parent_priv;
2707 const gchar *action_name;
2710 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2711 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2713 /* We can not just use the code of
2714 modest_msg_edit_window_setup_toolbar because it has a
2715 mixture of both initialization and creation code. */
2717 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2719 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2721 /* Update also the actions (to update the toggles in the
2722 menus), we have to do it manually because some other window
2723 of the same time could have changed it (remember that the
2724 toolbar fullscreen mode is shared by all the windows of the
2726 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2727 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2729 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2731 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2732 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2738 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2739 TnyHeaderFlags priority_flags)
2741 ModestMsgEditWindowPrivate *priv;
2742 ModestWindowPrivate *parent_priv;
2744 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2746 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2747 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2749 if (priv->priority_flags != priority_flags) {
2750 GtkAction *priority_action = NULL;
2752 priv->priority_flags = priority_flags;
2754 switch (priority_flags) {
2755 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2756 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2757 gtk_widget_show (priv->priority_icon);
2758 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2759 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2761 case TNY_HEADER_FLAG_LOW_PRIORITY:
2762 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2763 gtk_widget_show (priv->priority_icon);
2764 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2765 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2768 gtk_widget_hide (priv->priority_icon);
2769 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2770 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2773 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2774 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2779 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2782 ModestMsgEditWindowPrivate *priv;
2783 ModestWindowPrivate *parent_priv;
2784 gint current_format;
2786 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2788 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2789 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2791 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2792 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2794 if (current_format != file_format) {
2795 switch (file_format) {
2796 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2797 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2798 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2800 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2804 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2805 response = gtk_dialog_run (GTK_DIALOG (dialog));
2806 gtk_widget_destroy (dialog);
2807 if (response == GTK_RESPONSE_OK) {
2808 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2810 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2811 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2816 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2817 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2822 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2825 ModestMsgEditWindowPrivate *priv;
2826 WPTextBufferFormat oldfmt, fmt;
2827 gint old_position = 0;
2831 GdkColor *color = NULL;
2832 gboolean bold, bold_set, italic, italic_set;
2833 gboolean underline, underline_set;
2834 gboolean strikethrough, strikethrough_set;
2835 gboolean position_set;
2836 gboolean font_size_set, font_set, color_set;
2839 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2840 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2842 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2843 modest_window_mgr_set_modal (modest_runtime_get_window_mgr(),
2844 GTK_WINDOW(dialog));
2846 /* First we get the currently selected font information */
2847 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2849 switch (oldfmt.text_position) {
2850 case TEXT_POSITION_NORMAL:
2853 case TEXT_POSITION_SUPERSCRIPT:
2861 g_object_set (G_OBJECT (dialog),
2862 "bold", oldfmt.bold != FALSE,
2863 "bold-set", !oldfmt.cs.bold,
2864 "underline", oldfmt.underline != FALSE,
2865 "underline-set", !oldfmt.cs.underline,
2866 "italic", oldfmt.italic != FALSE,
2867 "italic-set", !oldfmt.cs.italic,
2868 "strikethrough", oldfmt.strikethrough != FALSE,
2869 "strikethrough-set", !oldfmt.cs.strikethrough,
2870 "color", &oldfmt.color,
2871 "color-set", !oldfmt.cs.color,
2872 "size", wp_font_size[oldfmt.font_size],
2873 "size-set", !oldfmt.cs.font_size,
2874 "position", old_position,
2875 "position-set", !oldfmt.cs.text_position,
2876 "family", wp_get_font_name (oldfmt.font),
2877 "family-set", !oldfmt.cs.font,
2880 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
2881 GTK_WINDOW (dialog));
2882 gtk_widget_show_all (dialog);
2883 priv->font_dialog = dialog;
2884 response = gtk_dialog_run (GTK_DIALOG (dialog));
2885 priv->font_dialog = NULL;
2886 if (response == GTK_RESPONSE_OK) {
2888 g_object_get( dialog,
2890 "bold-set", &bold_set,
2891 "underline", &underline,
2892 "underline-set", &underline_set,
2894 "italic-set", &italic_set,
2895 "strikethrough", &strikethrough,
2896 "strikethrough-set", &strikethrough_set,
2898 "color-set", &color_set,
2900 "size-set", &font_size_set,
2901 "family", &font_name,
2902 "family-set", &font_set,
2903 "position", &position,
2904 "position-set", &position_set,
2909 if (response == GTK_RESPONSE_OK) {
2910 memset(&fmt, 0, sizeof(fmt));
2916 fmt.italic = italic;
2917 fmt.cs.italic = TRUE;
2919 if (underline_set) {
2920 fmt.underline = underline;
2921 fmt.cs.underline = TRUE;
2923 if (strikethrough_set) {
2924 fmt.strikethrough = strikethrough;
2925 fmt.cs.strikethrough = TRUE;
2930 ? TEXT_POSITION_NORMAL
2931 : ( ( position == 1 )
2932 ? TEXT_POSITION_SUPERSCRIPT
2933 : TEXT_POSITION_SUBSCRIPT );
2934 fmt.cs.text_position = TRUE;
2935 fmt.font_size = oldfmt.font_size;
2939 fmt.cs.color = TRUE;
2942 fmt.font = wp_get_font_index(font_name,
2947 if (font_size_set) {
2948 fmt.cs.font_size = TRUE;
2949 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2951 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2952 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2954 gtk_widget_destroy (dialog);
2956 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2960 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2962 ModestMsgEditWindowPrivate *priv;
2964 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2965 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2967 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2969 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2970 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2975 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2977 ModestMsgEditWindowPrivate *priv;
2979 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2980 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2982 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2984 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2985 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2990 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2992 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2994 priv->can_undo = can_undo;
2998 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
3000 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3002 priv->can_redo = can_redo;
3006 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
3008 ModestMsgEditWindowPrivate *priv;
3009 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3010 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3012 return priv->can_undo;
3016 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
3018 ModestMsgEditWindowPrivate *priv;
3019 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3020 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3022 return priv->can_redo;
3027 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
3030 GtkTextIter match_start, match_end;
3032 if (image_id == NULL)
3035 gtk_text_buffer_get_start_iter (buffer, &iter);
3037 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
3038 GSList *tags = gtk_text_iter_get_tags (&match_start);
3040 for (node = tags; node != NULL; node = g_slist_next (node)) {
3041 GtkTextTag *tag = (GtkTextTag *) node->data;
3042 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
3043 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
3044 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
3046 offset = gtk_text_iter_get_offset (&match_start);
3047 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3048 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3052 gtk_text_iter_forward_char (&iter);
3057 message_is_empty (ModestMsgEditWindow *window)
3059 ModestMsgEditWindowPrivate *priv = NULL;
3061 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3062 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3064 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3065 * so we can ignore markup.
3067 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3070 count = gtk_text_buffer_get_char_count (buf);
3076 msg_body_focus (GtkWidget *focus,
3077 GdkEventFocus *event,
3081 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3082 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3083 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3088 recpt_field_changed (GtkTextBuffer *buffer,
3089 ModestMsgEditWindow *editor)
3091 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3092 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3096 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3098 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3099 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3103 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3106 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3107 GtkTextBuffer *buffer;
3109 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3110 gtk_text_buffer_set_modified (buffer, modified);
3111 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3112 gtk_text_buffer_set_modified (buffer, modified);
3113 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3114 gtk_text_buffer_set_modified (buffer, modified);
3115 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3119 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3121 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3122 const char *account_name;
3123 GtkTextBuffer *buffer;
3125 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3126 if (gtk_text_buffer_get_modified (buffer))
3128 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3129 if (gtk_text_buffer_get_modified (buffer))
3131 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3132 if (gtk_text_buffer_get_modified (buffer))
3134 if (gtk_text_buffer_get_modified (priv->text_buffer))
3136 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3137 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3148 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3150 ModestMsgEditWindowPrivate *priv = NULL;
3152 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3155 /* check if there's no recipient added */
3156 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3157 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3158 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3159 /* no recipient contents, then select contacts */
3160 modest_msg_edit_window_open_addressbook (window, NULL);
3164 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3165 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3168 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3169 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3172 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3173 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3177 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3178 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3179 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3186 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3187 ModestMsgEditWindow *window)
3189 modest_msg_edit_window_offer_attach_file (window);
3193 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3195 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3197 return priv->clipboard_text;
3201 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3203 ModestMsgEditWindow *window)
3205 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3206 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3208 if (!GTK_WIDGET_VISIBLE (window))
3211 g_object_ref (window);
3212 text = gtk_clipboard_wait_for_text (selection_clipboard);
3214 if (priv->clipboard_text != NULL) {
3215 g_free (priv->clipboard_text);
3217 priv->clipboard_text = text;
3219 if (GTK_WIDGET_VISIBLE (window)) {
3220 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3222 g_object_unref (window);
3225 static gboolean clipboard_owner_change_idle (gpointer userdata)
3227 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3228 ModestMsgEditWindowPrivate *priv;
3230 gdk_threads_enter ();
3231 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3232 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3234 priv->clipboard_owner_idle = 0;
3235 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3236 gdk_threads_leave ();
3242 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3244 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3245 if (priv->clipboard_owner_idle == 0) {
3246 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3251 subject_field_move_cursor (GtkEntry *entry,
3252 GtkMovementStep step,
3257 if (!GTK_WIDGET_VISIBLE (window))
3260 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3264 update_window_title (ModestMsgEditWindow *window)
3266 ModestMsgEditWindowPrivate *priv = NULL;
3267 const gchar *subject;
3269 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3270 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3271 if (subject == NULL || subject[0] == '\0')
3272 subject = _("mail_va_new_email");
3274 gtk_window_set_title (GTK_WINDOW (window), subject);
3279 subject_field_changed (GtkEditable *editable,
3280 ModestMsgEditWindow *window)
3282 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3283 update_window_title (window);
3284 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3285 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3286 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3290 subject_field_insert_text (GtkEditable *editable,
3292 gint new_text_length,
3294 ModestMsgEditWindow *window)
3296 GString *result = g_string_new ("");
3298 gint result_len = 0;
3299 const gchar *entry_text = NULL;
3302 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3303 old_length = g_utf8_strlen (entry_text, -1);
3305 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3306 gunichar c = g_utf8_get_char_validated (current, 8);
3307 /* Invalid unichar, stop */
3313 result = g_string_append_unichar (result, c);
3317 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3318 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3321 /* Prevent endless recursion */
3322 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3323 g_signal_emit_by_name (editable, "insert-text",
3324 (gpointer) result->str, (gpointer) result->len,
3325 (gpointer) position, (gpointer) window);
3326 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3330 if (result_len + old_length > 1000) {
3331 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3332 dgettext("hildon-common-strings",
3333 "ckdg_ib_maximum_characters_reached"));
3336 g_string_free (result, TRUE);
3340 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3343 ModestMsgEditWindowPrivate *priv = NULL;
3345 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3346 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3348 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3351 gtk_widget_show_all (priv->find_toolbar);
3352 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3354 gtk_widget_hide_all (priv->find_toolbar);
3355 gtk_widget_grab_focus (priv->msg_body);
3361 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3363 GtkTextIter *match_start,
3364 GtkTextIter *match_end)
3366 GtkTextIter end_iter;
3367 gchar *str_casefold;
3370 gchar *range_casefold;
3373 gboolean result = FALSE;
3380 gtk_text_iter_forward_to_end (&end_iter);
3382 str_casefold = g_utf8_casefold (str, -1);
3383 str_chars_n = strlen (str);
3385 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3386 range_casefold = g_utf8_casefold (range_text, -1);
3387 range_chars_n = strlen (range_casefold);
3389 if (range_chars_n < str_chars_n) {
3390 g_free (str_casefold);
3391 g_free (range_text);
3392 g_free (range_casefold);
3396 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3397 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3398 if (!g_utf8_collate (range_subtext, str_casefold)) {
3399 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3401 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3402 match_start, match_end, NULL);
3403 g_free (found_text);
3405 g_free (range_subtext);
3409 g_free (str_casefold);
3410 g_free (range_text);
3411 g_free (range_casefold);
3418 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3419 ModestMsgEditWindow *window)
3421 gchar *current_search = NULL;
3422 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3424 GtkTextIter selection_start, selection_end;
3425 GtkTextIter match_start, match_end;
3426 gboolean continue_search = FALSE;
3428 if (message_is_empty (window)) {
3429 g_free (priv->last_search);
3430 priv->last_search = NULL;
3431 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3435 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3436 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3437 g_free (current_search);
3438 g_free (priv->last_search);
3439 priv->last_search = NULL;
3440 /* Information banner about empty search */
3441 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3445 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3446 continue_search = TRUE;
3448 g_free (priv->last_search);
3449 priv->last_search = g_strdup (current_search);
3452 if (continue_search) {
3453 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3454 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3455 &match_start, &match_end);
3457 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3459 GtkTextIter buffer_start;
3460 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3461 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3462 &match_start, &match_end);
3464 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3467 /* Mark as selected the string found in search */
3469 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3470 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3471 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3473 g_free (priv->last_search);
3474 priv->last_search = NULL;
3476 g_free (current_search);
3480 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3481 ModestMsgEditWindow *window)
3483 GtkToggleAction *toggle;
3484 ModestWindowPrivate *parent_priv;
3485 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3487 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3488 gtk_toggle_action_set_active (toggle, FALSE);
3492 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3494 ModestMsgEditWindowPrivate *priv;
3496 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3501 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3504 ModestMsgEditWindowPrivate *priv;
3506 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3512 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3515 ModestMsgEditWindowPrivate *priv;
3516 TnyHeader *header = NULL;
3518 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3519 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3521 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3522 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3524 if (priv->draft_msg != NULL) {
3525 g_object_unref (priv->draft_msg);
3528 if (draft != NULL) {
3529 g_object_ref (draft);
3530 header = tny_msg_get_header (draft);
3531 if (priv->msg_uid) {
3532 g_free (priv->msg_uid);
3533 priv->msg_uid = NULL;
3535 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3536 if (GTK_WIDGET_REALIZED (window))
3537 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3540 priv->draft_msg = draft;
3544 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3545 GtkTextIter *start, GtkTextIter *end,
3548 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3549 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3552 if (tag == NULL+13) return;
3553 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3554 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3555 replace_with_images (window, priv->images);
3560 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3563 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3565 g_return_if_fail (TNY_IS_MIME_PART (part));
3566 tny_list_prepend (priv->attachments, (GObject *) part);
3567 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3568 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3569 gtk_widget_show_all (priv->attachments_caption);
3570 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3574 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3576 ModestMsgEditWindowPrivate *priv;
3578 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3579 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3581 return priv->msg_uid;
3585 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3586 ModestMsgEditWindowWidgetType widget_type)
3588 ModestMsgEditWindowPrivate *priv;
3590 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3591 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3593 switch (widget_type) {
3594 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3595 return priv->msg_body;
3597 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3598 return priv->to_field;
3600 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3601 return priv->cc_field;
3603 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3604 return priv->bcc_field;
3606 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3607 return priv->subject_field;
3609 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3610 return priv->attachments_view;
3618 remove_tags (WPTextBuffer *buffer)
3620 GtkTextIter start, end;
3622 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3623 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3625 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3629 on_account_removed (TnyAccountStore *account_store,
3630 TnyAccount *account,
3633 /* Do nothing if it's a store account, because we use the
3634 transport to send the messages */
3635 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3636 const gchar *parent_acc = NULL;
3637 const gchar *our_acc = NULL;
3639 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3640 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3641 /* Close this window if I'm showing a message of the removed account */
3642 if (strcmp (parent_acc, our_acc) == 0)
3643 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3648 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3650 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3652 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3658 set_zoom_do_nothing (ModestWindow *window,
3664 get_zoom_do_nothing (ModestWindow *window)