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_insert_text (GtkTextBuffer *buffer,
109 GtkTextIter *location,
112 ModestMsgEditWindow *window);
113 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
114 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
115 static void subject_field_insert_text (GtkEditable *editable,
117 gint new_text_length,
119 ModestMsgEditWindow *window);
120 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
122 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
124 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
126 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
127 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
128 GdkEventWindowState *event,
130 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
131 ModestRecptEditor *editor);
132 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
133 ModestMsgEditWindow *window);
135 /* ModestWindow methods implementation */
136 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
137 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
138 gboolean show_toolbar);
139 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
141 ModestMsgEditWindow *window);
142 static void modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window);
143 static void subject_field_move_cursor (GtkEntry *entry,
144 GtkMovementStep step,
148 static void update_window_title (ModestMsgEditWindow *window);
151 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
152 ModestMsgEditWindow *window);
153 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
154 ModestMsgEditWindow *window);
155 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
157 GtkTextIter *match_start,
158 GtkTextIter *match_end);
160 static void remove_tags (WPTextBuffer *buffer);
162 static void on_account_removed (TnyAccountStore *account_store,
166 static gboolean on_zoom_minus_plus_not_implemented (ModestWindow *window);
167 static void set_zoom_do_nothing (ModestWindow *window, gdouble zoom);
168 static gdouble get_zoom_do_nothing (ModestWindow *window);
170 static void init_window (ModestMsgEditWindow *obj);
172 gboolean scroll_drag_timeout (gpointer userdata);
173 static void correct_scroll (ModestMsgEditWindow *w);
174 static void correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused);
175 static void text_buffer_end_user_action (GtkTextBuffer *buffer,
176 ModestMsgEditWindow *userdata);
177 static void text_buffer_mark_set (GtkTextBuffer *buffer,
180 ModestMsgEditWindow *userdata);
181 void vadj_changed (GtkAdjustment *adj,
182 ModestMsgEditWindow *window);
184 static ModestPair *find_transport_from_message_sender (ModestPairList *transports,
190 static void DEBUG_BUFFER (WPTextBuffer *buffer)
194 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
196 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
197 while (!gtk_text_iter_is_end (&iter)) {
198 GString *output = g_string_new ("");
199 GSList *toggled_tags;
202 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
203 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
204 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
205 GtkTextTag *tag = (GtkTextTag *) node->data;
207 g_object_get (G_OBJECT (tag), "name", &name, NULL);
208 output = g_string_append (output, name);
209 g_string_append (output, " ");
211 output = g_string_append (output, "] OPENED [ ");
212 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
213 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
214 GtkTextTag *tag = (GtkTextTag *) node->data;
216 g_object_get (G_OBJECT (tag), "name", &name, NULL);
217 output = g_string_append (output, name);
218 g_string_append (output, " ");
220 output = g_string_append (output, "]\n");
221 g_message ("%s", output->str);
222 g_string_free (output, TRUE);
223 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
225 g_message ("END BUFFER");
230 /* static gboolean */
231 /* on_key_pressed (GtkWidget *self, */
232 /* GdkEventKey *event, */
233 /* gpointer user_data); */
235 /* list my signals */
242 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
243 struct _ModestMsgEditWindowPrivate {
246 GtkWidget *header_box;
248 ModestPairList *from_field_protos;
249 GtkWidget *from_field;
250 const gchar *original_account_name;
254 GtkWidget *bcc_field;
255 GtkWidget *subject_field;
256 GtkWidget *attachments_view;
257 GtkWidget *priority_icon;
258 GtkWidget *add_attachment_button;
260 GtkWidget *cc_caption;
261 GtkWidget *bcc_caption;
262 gboolean update_caption_visibility;
263 GtkWidget *attachments_caption;
265 GtkTextBuffer *text_buffer;
267 GtkWidget *font_size_toolitem;
268 GtkWidget *font_face_toolitem;
269 GtkWidget *font_color_button;
270 GSList *font_items_group;
271 GtkWidget *font_tool_button_label;
272 GSList *size_items_group;
273 GtkWidget *size_tool_button_label;
275 GtkWidget *find_toolbar;
279 guint scroll_drag_timeout_id;
283 TnyList *attachments;
288 TnyHeaderFlags priority_flags;
290 gboolean can_undo, can_redo;
291 gulong clipboard_change_handler_id;
292 gulong default_clipboard_change_handler_id;
293 gulong account_removed_handler_id;
294 guint clipboard_owner_idle;
295 gchar *clipboard_text;
304 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
305 MODEST_TYPE_MSG_EDIT_WINDOW, \
306 ModestMsgEditWindowPrivate))
308 static GtkWindowClass *parent_class = NULL;
310 /* uncomment the following if you have defined any signals */
311 /* static guint signals[LAST_SIGNAL] = {0}; */
314 modest_msg_edit_window_get_type (void)
316 static GType my_type = 0;
318 static const GTypeInfo my_info = {
319 sizeof(ModestMsgEditWindowClass),
320 NULL, /* base init */
321 NULL, /* base finalize */
322 (GClassInitFunc) modest_msg_edit_window_class_init,
323 NULL, /* class finalize */
324 NULL, /* class data */
325 sizeof(ModestMsgEditWindow),
327 (GInstanceInitFunc) modest_msg_edit_window_init,
330 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
331 "ModestMsgEditWindow",
339 save_state (ModestWindow *self)
341 modest_widget_memory_save (modest_runtime_get_conf(),
342 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
347 restore_settings (ModestMsgEditWindow *self)
349 ModestConf *conf = NULL;
351 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (self);
353 conf = modest_runtime_get_conf ();
354 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
355 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu");
356 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
357 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL));
358 action = gtk_ui_manager_get_action (parent_priv->ui_manager,
359 "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu");
360 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
361 modest_conf_get_bool (conf, MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR_FULLSCREEN, NULL));
363 /* set initial state of cc and bcc */
364 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
365 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
366 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
367 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
368 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
369 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
371 /* Dim at start clipboard actions */
372 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
373 gtk_action_set_sensitive (action, FALSE);
374 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
375 gtk_action_set_sensitive (action, FALSE);
376 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
377 gtk_action_set_sensitive (action, FALSE);
379 modest_widget_memory_restore (conf,
380 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
385 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
387 GObjectClass *gobject_class;
388 ModestWindowClass *modest_window_class;
389 gobject_class = (GObjectClass*) klass;
390 modest_window_class = (ModestWindowClass*) klass;
392 parent_class = g_type_class_peek_parent (klass);
393 gobject_class->finalize = modest_msg_edit_window_finalize;
395 modest_window_class->set_zoom_func = set_zoom_do_nothing;
396 modest_window_class->get_zoom_func = get_zoom_do_nothing;
397 modest_window_class->zoom_plus_func = on_zoom_minus_plus_not_implemented;
398 modest_window_class->zoom_minus_func = on_zoom_minus_plus_not_implemented;
399 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
400 modest_window_class->save_state_func = save_state;
401 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
403 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
407 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
409 ModestMsgEditWindowPrivate *priv;
410 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
412 priv->msg_body = NULL;
414 priv->from_field = NULL;
415 priv->to_field = NULL;
416 priv->cc_field = NULL;
417 priv->bcc_field = NULL;
418 priv->subject_field = NULL;
419 priv->attachments = TNY_LIST (tny_simple_list_new ());
420 priv->images = TNY_LIST (tny_simple_list_new ());
421 priv->images_size = 0;
422 priv->images_count = 0;
425 priv->cc_caption = NULL;
426 priv->bcc_caption = NULL;
427 priv->update_caption_visibility = FALSE;
429 priv->priority_flags = 0;
431 priv->find_toolbar = NULL;
432 priv->last_search = NULL;
434 priv->draft_msg = NULL;
435 priv->outbox_msg = NULL;
436 priv->msg_uid = NULL;
438 priv->can_undo = FALSE;
439 priv->can_redo = FALSE;
440 priv->clipboard_change_handler_id = 0;
441 priv->default_clipboard_change_handler_id = 0;
442 priv->account_removed_handler_id = 0;
443 priv->clipboard_owner_idle = 0;
444 priv->clipboard_text = NULL;
447 priv->scroll_drag_timeout_id = 0;
448 priv->last_upper = 0.0;
450 modest_window_mgr_register_help_id (modest_runtime_get_window_mgr(),
451 GTK_WINDOW(obj),"applications_email_editor");
453 if (!is_wp_text_buffer_started) {
454 is_wp_text_buffer_started = TRUE;
455 wp_text_buffer_library_init ();
460 hildon_program_add_window (hildon_program_get_instance(),
465 /* FIXME: this is a dup from the one in gtk/ */
468 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
470 static ModestPairList*
471 get_transports (void)
473 GSList *transports = NULL;
475 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
476 GSList *accounts = modest_account_mgr_account_names (account_mgr,
477 TRUE /* only enabled accounts. */);
479 GSList *cursor = accounts;
481 gchar *account_name = cursor->data;
482 gchar *from_string = NULL;
484 from_string = modest_account_mgr_get_from_string (account_mgr,
488 if (from_string && account_name) {
489 gchar *name = account_name;
490 ModestPair *pair = modest_pair_new ((gpointer) name,
491 (gpointer) from_string , TRUE);
492 transports = g_slist_prepend (transports, pair);
495 cursor = cursor->next;
497 g_slist_free (accounts); /* only free the accounts, not the elements,
498 * because they are used in the pairlist */
503 * Search an (account, address) ModestPairList for a pair whose
504 * address matches the one in the From: header of a TnyMsg
506 * @result: A ModestPair * with a matching address, or NULL if none found
509 find_transport_from_message_sender (ModestPairList *transports, TnyMsg *msg)
511 g_return_val_if_fail (transports, NULL);
512 g_return_val_if_fail (msg, NULL);
514 ModestPair *account_pair = NULL;
515 TnyHeader *header = tny_msg_get_header (msg);
517 if (header != NULL && tny_header_get_from (header)) {
518 char *from_addr = modest_text_utils_get_email_address (tny_header_get_from (header));
520 for (iter = transports; iter && !account_pair; iter = iter->next) {
521 ModestPair *pair = (ModestPair *) iter->data;
522 char *account_addr = modest_text_utils_get_email_address ((char *) pair->second);
523 if (account_addr && !strcasecmp(from_addr, account_addr)) {
526 g_free (account_addr);
532 g_object_unref (header);
537 static void window_focus (GtkWindow *window,
541 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
545 scroll_drag_timeout (gpointer userdata)
547 ModestMsgEditWindow *win = (ModestMsgEditWindow *) userdata;
548 ModestMsgEditWindowPrivate *priv;
550 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(win);
552 correct_scroll_without_drag_check (win, TRUE);
554 priv->scroll_drag_timeout_id = 0;
560 correct_scroll_without_drag_check (ModestMsgEditWindow *w, gboolean only_if_focused)
562 ModestMsgEditWindowPrivate *priv;
565 GdkRectangle rectangle;
571 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
573 if (only_if_focused && !gtk_widget_is_focus (priv->msg_body))
576 insert = gtk_text_buffer_get_insert (priv->text_buffer);
577 gtk_text_buffer_get_iter_at_mark (priv->text_buffer, &iter, insert);
579 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &iter, &rectangle);
580 vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll));
581 offset = priv->msg_body->allocation.y;
583 new_value = vadj->value;
585 if ((offset + rectangle.y + rectangle.height) >
586 ((gint) (vadj->value +vadj->page_size))) {
587 new_value = (offset + rectangle.y) - vadj->page_size * 0.25;
588 if (new_value > vadj->upper - vadj->page_size)
589 new_value = vadj->upper - vadj->page_size;
590 } else if ((offset + rectangle.y) < ((gint) vadj->value)) {
591 new_value = (offset + rectangle.y - vadj->page_size * 0.75);
592 if (((gint) (new_value + vadj->page_size)) < (offset + rectangle.y + rectangle.height))
593 new_value = offset + rectangle.y + rectangle.height - (gint) vadj->page_size;
596 if (new_value > vadj->value)
597 new_value = vadj->value;
600 if (vadj->value != new_value) {
601 g_signal_emit_by_name (GTK_TEXT_VIEW(priv->msg_body)->layout,
603 vadj->value = new_value;
604 gtk_adjustment_value_changed (vadj);
605 /* invalidate body */
606 window = gtk_widget_get_parent_window (priv->msg_body);
608 gdk_window_invalidate_rect (window, NULL, TRUE);
614 correct_scroll (ModestMsgEditWindow *w)
616 ModestMsgEditWindowPrivate *priv;
618 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(w);
619 if (gtk_grab_get_current () == priv->msg_body) {
620 if (priv->scroll_drag_timeout_id == 0) {
621 priv->scroll_drag_timeout_id = g_timeout_add (500, (GSourceFunc) scroll_drag_timeout,
627 correct_scroll_without_drag_check (w, TRUE);
631 text_buffer_end_user_action (GtkTextBuffer *buffer,
632 ModestMsgEditWindow *userdata)
635 correct_scroll (userdata);
639 text_buffer_mark_set (GtkTextBuffer *buffer,
642 ModestMsgEditWindow *userdata)
644 gtk_text_buffer_begin_user_action (buffer);
645 gtk_text_buffer_end_user_action (buffer);
649 cut_clipboard_check (GtkTextView *text_view,
652 GtkTextBuffer *buffer;
654 buffer = gtk_text_view_get_buffer (text_view);
655 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
656 g_signal_stop_emission_by_name ((gpointer )text_view, "cut-clipboard");
661 copy_clipboard_check (GtkTextView *text_view,
664 GtkTextBuffer *buffer;
666 buffer = gtk_text_view_get_buffer (text_view);
667 if (!modest_text_utils_buffer_selection_is_valid (buffer)) {
668 g_signal_stop_emission_by_name ((gpointer )text_view, "copy-clipboard");
672 void vadj_changed (GtkAdjustment *adj,
673 ModestMsgEditWindow *window)
675 ModestMsgEditWindowPrivate *priv;
677 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
679 if (priv->last_upper != adj->upper) {
680 priv->last_upper = adj->upper;
681 correct_scroll (window);
686 connect_signals (ModestMsgEditWindow *obj)
688 ModestMsgEditWindowPrivate *priv;
690 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
692 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
693 G_CALLBACK (text_buffer_refresh_attributes), obj);
694 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
695 G_CALLBACK (text_buffer_can_undo), obj);
696 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
697 G_CALLBACK (text_buffer_can_redo), obj);
698 g_signal_connect (G_OBJECT (priv->text_buffer), "changed",
699 G_CALLBACK (body_changed), obj);
700 g_signal_connect (G_OBJECT (priv->text_buffer), "modified-changed",
701 G_CALLBACK (body_changed), obj);
702 g_signal_connect (G_OBJECT (priv->text_buffer), "insert-text",
703 G_CALLBACK (text_buffer_insert_text), obj);
704 g_signal_connect (G_OBJECT (obj), "window-state-event",
705 G_CALLBACK (modest_msg_edit_window_window_state_event),
707 g_signal_connect (G_OBJECT (priv->text_buffer), "end-user-action",
708 G_CALLBACK (text_buffer_end_user_action), obj);
709 g_signal_connect (G_OBJECT (priv->text_buffer), "mark-set",
710 G_CALLBACK (text_buffer_mark_set), obj);
711 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
712 G_CALLBACK (text_buffer_apply_tag), obj);
713 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
714 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
715 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
716 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
717 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
718 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
720 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
721 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
723 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
724 G_CALLBACK (msg_body_focus), obj);
725 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
726 G_CALLBACK (msg_body_focus), obj);
727 g_signal_connect (G_OBJECT (obj), "set-focus", G_CALLBACK (window_focus), obj);
728 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
729 "changed", G_CALLBACK (recpt_field_changed), obj);
730 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
731 "changed", G_CALLBACK (recpt_field_changed), obj);
732 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
733 "changed", G_CALLBACK (recpt_field_changed), obj);
734 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
735 g_signal_connect_after (G_OBJECT (priv->subject_field), "move-cursor", G_CALLBACK (subject_field_move_cursor), obj);
736 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
738 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
739 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
741 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
743 G_CALLBACK (vadj_changed),
746 priv->clipboard_change_handler_id =
747 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
748 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
749 priv->default_clipboard_change_handler_id =
750 g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD)), "owner-change",
751 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
753 g_signal_connect (G_OBJECT (priv->msg_body), "cut-clipboard", G_CALLBACK (cut_clipboard_check), NULL);
754 g_signal_connect (G_OBJECT (priv->msg_body), "copy-clipboard", G_CALLBACK (copy_clipboard_check), NULL);
759 init_window (ModestMsgEditWindow *obj)
761 GtkWidget *from_caption, *to_caption, *subject_caption;
762 GtkWidget *main_vbox;
763 ModestMsgEditWindowPrivate *priv;
764 GtkActionGroup *action_group;
765 ModestWindowPrivate *parent_priv;
766 GdkPixbuf *window_icon = NULL;
767 GError *error = NULL;
769 GtkSizeGroup *size_group;
770 GtkWidget *subject_box;
771 GtkWidget *attachment_icon;
772 GtkWidget *window_box;
773 #if (GTK_MINOR_VERSION >= 10)
774 GdkAtom deserialize_type;
776 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
777 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
779 parent_priv->ui_manager = gtk_ui_manager_new();
780 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
781 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
783 /* Add common actions */
784 gtk_action_group_add_actions (action_group,
785 modest_msg_edit_action_entries,
786 G_N_ELEMENTS (modest_msg_edit_action_entries),
788 gtk_action_group_add_toggle_actions (action_group,
789 modest_msg_edit_toggle_action_entries,
790 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
792 gtk_action_group_add_radio_actions (action_group,
793 modest_msg_edit_alignment_radio_action_entries,
794 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
796 G_CALLBACK (modest_ui_actions_on_change_justify),
798 gtk_action_group_add_radio_actions (action_group,
799 modest_msg_edit_priority_action_entries,
800 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
802 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
804 gtk_action_group_add_radio_actions (action_group,
805 modest_msg_edit_file_format_action_entries,
806 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
807 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
808 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
810 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
811 g_object_unref (action_group);
813 /* Load the UI definition */
814 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
817 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
818 g_clear_error (&error);
821 /* Add accelerators */
822 gtk_window_add_accel_group (GTK_WINDOW (obj),
823 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
825 parent_priv->menubar = NULL;
827 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
829 /* Note: This ModestPairList* must exist for as long as the combo
830 * that uses it, because the ModestComboBox uses the ID opaquely,
831 * so it can't know how to manage its memory. */
832 priv->from_field = modest_combo_box_new (NULL, g_str_equal);
834 priv->to_field = modest_recpt_editor_new ();
835 priv->cc_field = modest_recpt_editor_new ();
836 priv->bcc_field = modest_recpt_editor_new ();
837 subject_box = gtk_hbox_new (FALSE, 0);
838 priv->priority_icon = gtk_image_new ();
839 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
840 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
841 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
842 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
843 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
844 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
845 priv->add_attachment_button = gtk_button_new ();
846 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
847 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
848 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
849 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
850 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
851 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
852 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
853 priv->attachments_view = modest_attachments_view_new (NULL);
855 priv->header_box = gtk_vbox_new (FALSE, 0);
857 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
858 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
859 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
860 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
861 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
862 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
863 g_object_unref (size_group);
865 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
866 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
867 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
868 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
869 gtk_size_group_add_widget (size_group, priv->subject_field);
870 gtk_size_group_add_widget (size_group, priv->attachments_view);
871 g_object_unref (size_group);
873 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
874 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
875 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
876 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
877 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
878 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
879 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
882 priv->msg_body = wp_text_view_new ();
883 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
884 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
885 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
886 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
887 #if (GTK_MINOR_VERSION >= 10)
888 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
889 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
891 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
892 deserialize_type, TRUE);
894 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
896 priv->find_toolbar = hildon_find_toolbar_new (NULL);
897 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
899 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
901 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
902 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
903 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
904 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
906 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
908 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
909 priv->frame = gtk_frame_new (NULL);
910 gtk_box_pack_start (GTK_BOX(main_vbox), priv->frame, TRUE, TRUE, 0);
912 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
913 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
914 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
916 window_box = gtk_vbox_new (FALSE, 0);
917 gtk_container_add (GTK_CONTAINER(obj), window_box);
919 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
921 gtk_container_add (GTK_CONTAINER (priv->frame), priv->msg_body);
923 /* Set window icon */
924 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON, MODEST_ICON_SIZE_BIG);
926 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
927 g_object_unref (window_icon);
932 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
934 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
936 if (gtk_clipboard_get (GDK_SELECTION_PRIMARY) &&
937 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
938 priv->clipboard_change_handler_id))
939 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
940 priv->clipboard_change_handler_id);
941 if (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD) &&
942 g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
943 priv->default_clipboard_change_handler_id))
944 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
945 priv->default_clipboard_change_handler_id);
947 if (priv->account_removed_handler_id &&
948 g_signal_handler_is_connected (modest_runtime_get_account_store (),
949 priv->account_removed_handler_id))
950 g_signal_handler_disconnect(modest_runtime_get_account_store (),
951 priv->account_removed_handler_id);
955 modest_msg_edit_window_finalize (GObject *obj)
957 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
959 /* Sanity check: shouldn't be needed, the window mgr should
960 call this function before */
961 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
963 if (priv->clipboard_text != NULL) {
964 g_free (priv->clipboard_text);
965 priv->clipboard_text = NULL;
968 if (priv->draft_msg != NULL) {
969 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
970 if (TNY_IS_HEADER (header)) {
971 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
972 modest_window_mgr_unregister_header (mgr, header);
974 g_object_unref (priv->draft_msg);
975 priv->draft_msg = NULL;
977 if (priv->outbox_msg != NULL) {
978 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
979 if (TNY_IS_HEADER (header)) {
980 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
981 modest_window_mgr_unregister_header (mgr, header);
983 g_object_unref (priv->outbox_msg);
984 priv->outbox_msg = NULL;
986 if (priv->scroll_drag_timeout_id > 0) {
987 g_source_remove (priv->scroll_drag_timeout_id);
988 priv->scroll_drag_timeout_id = 0;
990 if (priv->clipboard_owner_idle > 0) {
991 g_source_remove (priv->clipboard_owner_idle);
992 priv->clipboard_owner_idle = 0;
994 g_free (priv->msg_uid);
995 g_free (priv->last_search);
996 g_slist_free (priv->font_items_group);
997 g_slist_free (priv->size_items_group);
998 g_object_unref (priv->attachments);
999 g_object_unref (priv->images);
1001 /* This had to stay alive for as long as the combobox that used it: */
1002 modest_pair_list_free (priv->from_field_protos);
1004 G_OBJECT_CLASS(parent_class)->finalize (obj);
1008 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type, guint64 *stream_size)
1010 GdkPixbufLoader *loader;
1016 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
1018 if (loader == NULL) {
1024 tny_stream_reset (TNY_STREAM (stream));
1025 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
1026 GError *error = NULL;
1027 unsigned char read_buffer[128];
1029 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
1031 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, &error)) {
1036 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
1038 g_object_ref (pixbuf);
1039 gdk_pixbuf_loader_close (loader, NULL);
1040 g_object_unref (loader);
1045 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
1046 GdkPixbuf *new_pixbuf;
1048 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
1049 gdk_pixbuf_get_width (pixbuf);
1050 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
1051 g_object_unref (pixbuf);
1052 pixbuf = new_pixbuf;
1056 *stream_size = size;
1062 replace_with_images (ModestMsgEditWindow *self, TnyList *attachments)
1064 ModestMsgEditWindowPrivate *priv;
1067 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1069 for (iter = tny_list_create_iterator (attachments);
1070 !tny_iterator_is_done (iter);
1071 tny_iterator_next (iter)) {
1072 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1073 const gchar *cid = tny_mime_part_get_content_id (part);
1074 const gchar *mime_type = tny_mime_part_get_content_type (part);
1075 if ((cid != NULL)&&(mime_type != NULL)) {
1076 guint64 stream_size;
1077 TnyStream *stream = tny_mime_part_get_decoded_stream (part);
1078 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
1081 g_object_unref (stream);
1083 if (pixbuf != NULL) {
1084 priv->images_count ++;
1085 priv->images_size += stream_size;
1086 wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf);
1087 g_object_unref (pixbuf);
1090 g_object_unref (part);
1092 g_object_unref (iter);
1096 get_related_images (ModestMsgEditWindow *self, TnyMsg *msg)
1098 TnyMimePart *parent = NULL;
1099 const gchar *content_type = NULL;
1100 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1102 content_type = tny_mime_part_get_content_type (TNY_MIME_PART (msg));
1104 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1105 parent = g_object_ref (msg);
1106 } else if (content_type && !g_strcasecmp (content_type, "multipart/mixed")) {
1107 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1110 tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
1111 iter = tny_list_create_iterator (parts);
1112 while (!tny_iterator_is_done (iter)) {
1114 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1115 content_type = tny_mime_part_get_content_type (part);
1116 if (content_type && !g_strcasecmp (content_type, "multipart/related")) {
1120 g_object_unref (part);
1122 tny_iterator_next (iter);
1124 g_object_unref (iter);
1125 g_object_unref (parts);
1128 if (parent != NULL) {
1129 TnyList *parts = TNY_LIST (tny_simple_list_new ());
1132 tny_mime_part_get_parts (TNY_MIME_PART (parent), parts);
1133 iter = tny_list_create_iterator (parts);
1134 while (!tny_iterator_is_done (iter)) {
1136 part = TNY_MIME_PART (tny_iterator_get_current (iter));
1137 content_type = tny_mime_part_get_content_type (part);
1138 if (content_type && g_str_has_prefix (content_type, "image/")) {
1139 tny_list_prepend (priv->images, (GObject *) part);
1141 g_object_unref (part);
1142 tny_iterator_next (iter);
1144 g_object_unref (iter);
1145 g_object_unref (parts);
1146 g_object_unref (parent);
1151 update_next_cid (ModestMsgEditWindow *self, TnyList *attachments)
1154 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1156 for (iter = tny_list_create_iterator (attachments) ;
1157 !tny_iterator_is_done (iter);
1158 tny_iterator_next (iter)) {
1159 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (iter);
1160 const gchar *cid = tny_mime_part_get_content_id (part);
1162 char *invalid = NULL;
1163 gint int_cid = strtol (cid, &invalid, 10);
1164 if ((invalid != NULL) && (*invalid == '\0') && (int_cid >= priv->next_cid)) {
1165 priv->next_cid = int_cid + 1;
1168 g_object_unref (part);
1170 g_object_unref (iter);
1174 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
1177 const gchar *to, *cc, *bcc, *subject;
1179 ModestMsgEditWindowPrivate *priv;
1181 TnyHeaderFlags priority_flags;
1182 TnyFolder *msg_folder;
1183 gboolean is_html = FALSE;
1185 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1186 g_return_if_fail (TNY_IS_MSG (msg));
1188 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1190 header = tny_msg_get_header (msg);
1191 to = tny_header_get_to (header);
1192 cc = tny_header_get_cc (header);
1193 bcc = tny_header_get_bcc (header);
1194 subject = tny_header_get_subject (header);
1195 priority_flags = tny_header_get_priority (header);
1198 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
1200 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
1201 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
1202 gtk_widget_show (priv->cc_caption);
1203 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
1204 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
1205 gtk_widget_hide (priv->cc_caption);
1208 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
1209 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
1210 gtk_widget_show (priv->bcc_caption);
1211 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
1212 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
1213 gtk_widget_hide (priv->bcc_caption);
1216 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
1217 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
1220 update_window_title (self);
1222 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1223 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
1225 if ((body == NULL)||(body[0] == '\0')) {
1227 body = modest_text_utils_convert_to_html ("");
1230 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1231 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
1234 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
1237 /* Add attachments to the view */
1238 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
1239 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1240 if (tny_list_get_length (priv->attachments) == 0) {
1241 gtk_widget_hide (priv->attachments_caption);
1243 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1244 gtk_widget_show_all (priv->attachments_caption);
1246 get_related_images (self, msg);
1247 update_next_cid (self, priv->attachments);
1248 update_next_cid (self, priv->images);
1249 replace_with_images (self, priv->images);
1251 if (preserve_is_rich && !is_html) {
1252 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1253 /* Get the default format required from configuration */
1254 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
1255 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1258 /* Set the default focus depending on having already a To: field or not */
1259 if ((!to)||(*to == '\0')) {
1260 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
1262 gtk_widget_grab_focus (priv->msg_body);
1265 /* TODO: lower priority, select in the From: combo to the
1266 value that comes from msg <- not sure, should it be
1269 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
1271 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1272 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
1274 modest_msg_edit_window_set_modified (self, FALSE);
1276 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
1277 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (self));
1278 text_buffer_can_undo (priv->text_buffer, FALSE, self);
1279 text_buffer_can_redo (priv->text_buffer, FALSE, self);
1281 if (priv->msg_uid) {
1282 g_free (priv->msg_uid);
1283 priv->msg_uid = NULL;
1286 /* we should set a reference to the incoming message if it is a draft */
1287 msg_folder = tny_msg_get_folder (msg);
1289 if (modest_tny_folder_is_local_folder (msg_folder)) {
1290 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
1291 if (type == TNY_FOLDER_TYPE_INVALID)
1292 g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1294 if (type == TNY_FOLDER_TYPE_DRAFTS)
1295 priv->draft_msg = g_object_ref(msg);
1296 if (type == TNY_FOLDER_TYPE_OUTBOX)
1297 priv->outbox_msg = g_object_ref(msg);
1298 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1300 g_object_unref (msg_folder);
1305 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
1308 GList *item_children, *node;
1309 GtkWidget *bin_child;
1311 bin_child = gtk_bin_get_child (GTK_BIN(item));
1313 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
1315 for (node = item_children; node != NULL; node = g_list_next (node)) {
1316 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
1317 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
1320 g_list_free (item_children);
1324 menu_tool_button_dont_expand (GtkMenuToolButton *item)
1327 GList *item_children, *node;
1329 box = gtk_bin_get_child (GTK_BIN (item));
1330 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
1331 item_children = gtk_container_get_children (GTK_CONTAINER (box));
1333 for (node = item_children; node != NULL; node = g_list_next (node)) {
1334 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
1335 if (GTK_IS_TOGGLE_BUTTON (node->data))
1336 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
1337 else if (GTK_IS_BUTTON (node->data))
1338 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
1340 g_list_free (item_children);
1345 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
1347 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1348 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1349 GtkWidget *placeholder;
1350 GtkWidget *tool_item;
1355 GtkWidget *sizes_menu;
1356 GtkWidget *fonts_menu;
1357 GSList *radio_group = NULL;
1358 GSList *node = NULL;
1362 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
1363 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
1365 /* Font color placeholder */
1366 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
1367 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1370 tool_item = GTK_WIDGET (gtk_tool_item_new ());
1371 priv->font_color_button = hildon_color_button_new ();
1372 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
1373 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
1374 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
1375 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1376 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1377 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1378 g_signal_connect_swapped (G_OBJECT (priv->font_color_button),
1380 G_CALLBACK (modest_msg_edit_window_color_button_change),
1383 /* Font size and face placeholder */
1384 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
1385 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1387 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1388 priv->size_tool_button_label = gtk_label_new (NULL);
1389 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
1390 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
1391 size_text,"</span>", NULL);
1392 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1394 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
1395 sizes_menu = gtk_menu_new ();
1396 priv->size_items_group = NULL;
1398 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
1399 GtkWidget *size_menu_item;
1401 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
1402 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
1403 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
1404 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
1405 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
1406 gtk_widget_show (size_menu_item);
1408 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
1412 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1413 GtkWidget *item = (GtkWidget *) node->data;
1414 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1418 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1419 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1420 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1421 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1422 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1423 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1424 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1425 priv->font_size_toolitem = tool_item;
1428 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1429 priv->font_tool_button_label = gtk_label_new (NULL);
1430 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1431 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1433 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1434 fonts_menu = gtk_menu_new ();
1435 priv->font_items_group = NULL;
1437 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1438 GtkWidget *font_menu_item;
1439 GtkWidget *child_label;
1441 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1442 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1443 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1444 wp_get_font_name (font_index), "</span>", NULL);
1445 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1448 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1449 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1450 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1451 gtk_widget_show (font_menu_item);
1453 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1456 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1457 GtkWidget *item = (GtkWidget *) node->data;
1458 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1461 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1462 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1463 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1464 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1465 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1466 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1467 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1468 priv->font_face_toolitem = tool_item;
1470 /* Set expand and homogeneous for remaining items */
1471 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1472 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1473 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1474 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1475 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1476 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1477 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1478 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1479 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1481 /* Explicitelly show all the toolbar (a normal gtk_widget_show
1482 will not show the tool items added to the placeholders) */
1483 gtk_widget_show_all (parent_priv->toolbar);
1485 /* Set the no show all *after* showing all items. We do not
1486 want the toolbar to be shown with a show all because it
1487 could go agains the gconf setting regarding showing or not
1488 the toolbar of the editor window */
1489 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1495 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1498 ModestWindowPrivate *parent_priv;
1499 ModestMsgEditWindowPrivate *priv;
1500 ModestPair *account_pair = NULL;
1501 ModestDimmingRulesGroup *menu_rules_group = NULL;
1502 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
1503 ModestDimmingRulesGroup *clipboard_rules_group = NULL;
1504 ModestWindowMgr *mgr = NULL;
1506 g_return_val_if_fail (msg, NULL);
1507 g_return_val_if_fail (account_name, NULL);
1509 mgr = modest_runtime_get_window_mgr ();
1511 obj = G_OBJECT (modest_window_mgr_get_msg_edit_window (mgr));
1513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1514 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1516 /* Menubar. Update the state of some toggles */
1517 parent_priv->menubar = modest_maemo_utils_get_manager_menubar_as_menu (parent_priv->ui_manager, "/MenuBar");
1518 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1519 priv->from_field_protos = get_transports ();
1520 modest_combo_box_set_pair_list (MODEST_COMBO_BOX (priv->from_field), priv->from_field_protos);
1521 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1522 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1525 connect_signals (MODEST_MSG_EDIT_WINDOW(obj));
1527 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1529 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1531 account_pair = find_transport_from_message_sender (priv->from_field_protos, msg);
1532 if (account_pair == NULL) {
1533 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1535 if (account_pair != NULL)
1536 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1538 priv->original_account_name = account_pair ? (const gchar *) account_pair->first : NULL;
1540 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new ();
1541 menu_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_MENU, FALSE);
1542 toolbar_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_TOOLBAR, TRUE);
1543 clipboard_rules_group = modest_dimming_rules_group_new (MODEST_DIMMING_RULES_CLIPBOARD, FALSE);
1544 /* Add common dimming rules */
1545 modest_dimming_rules_group_add_rules (menu_rules_group,
1546 modest_msg_edit_window_menu_dimming_entries,
1547 G_N_ELEMENTS (modest_msg_edit_window_menu_dimming_entries),
1548 MODEST_WINDOW (obj));
1549 modest_dimming_rules_group_add_rules (toolbar_rules_group,
1550 modest_msg_edit_window_toolbar_dimming_entries,
1551 G_N_ELEMENTS (modest_msg_edit_window_toolbar_dimming_entries),
1552 MODEST_WINDOW (obj));
1553 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_color_button,
1554 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1555 MODEST_WINDOW (obj));
1556 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_size_toolitem,
1557 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1558 MODEST_WINDOW (obj));
1559 modest_dimming_rules_group_add_widget_rule (toolbar_rules_group, priv->font_face_toolitem,
1560 G_CALLBACK (modest_ui_dimming_rules_on_set_style),
1561 MODEST_WINDOW (obj));
1562 modest_dimming_rules_group_add_rules (clipboard_rules_group,
1563 modest_msg_edit_window_clipboard_dimming_entries,
1564 G_N_ELEMENTS (modest_msg_edit_window_clipboard_dimming_entries),
1565 MODEST_WINDOW (obj));
1566 /* Insert dimming rules group for this window */
1567 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
1568 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
1569 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, clipboard_rules_group);
1570 /* Checks the dimming rules */
1571 g_object_unref (menu_rules_group);
1572 g_object_unref (toolbar_rules_group);
1573 g_object_unref (clipboard_rules_group);
1574 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1576 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1578 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
1579 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (obj));
1580 modest_window_check_dimming_rules_group (MODEST_WINDOW (obj), MODEST_DIMMING_RULES_CLIPBOARD);
1581 priv->update_caption_visibility = TRUE;
1583 modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (obj), FALSE);
1585 /* Track account-removed signal, this window should be closed
1586 in the case we're creating a mail associated to the account
1588 priv->account_removed_handler_id =
1589 g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
1591 G_CALLBACK(on_account_removed),
1594 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (MODEST_MSG_EDIT_WINDOW (obj));
1596 return (ModestWindow*) obj;
1600 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1602 GString **string_buffer = (GString **) user_data;
1604 *string_buffer = g_string_append (*string_buffer, buffer);
1610 * @result: A new string which should be freed with g_free().
1613 get_formatted_data (ModestMsgEditWindow *edit_window)
1615 ModestMsgEditWindowPrivate *priv;
1616 GString *string_buffer = g_string_new ("");
1618 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1620 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1622 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1624 return g_string_free (string_buffer, FALSE);
1629 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1632 const gchar *account_name;
1633 ModestMsgEditWindowPrivate *priv;
1634 TnyIterator *att_iter;
1636 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1638 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1640 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1641 g_return_val_if_fail (account_name, NULL);
1644 /* don't free these (except from) */
1645 data = g_slice_new0 (MsgData);
1646 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1648 data->account_name = g_strdup (account_name);
1649 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1650 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1651 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1652 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1653 if (priv->draft_msg) {
1654 data->draft_msg = g_object_ref (priv->draft_msg);
1655 } else if (priv->outbox_msg) {
1656 data->draft_msg = g_object_ref (priv->outbox_msg);
1658 data->draft_msg = NULL;
1661 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1663 gtk_text_buffer_get_bounds (buf, &b, &e);
1664 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1666 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1667 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1669 data->html_body = NULL;
1671 /* deep-copy the data */
1672 att_iter = tny_list_create_iterator (priv->attachments);
1673 data->attachments = NULL;
1674 while (!tny_iterator_is_done (att_iter)) {
1675 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1676 if (!(TNY_IS_MIME_PART(part))) {
1677 g_warning ("strange data in attachment list");
1678 g_object_unref (part);
1679 tny_iterator_next (att_iter);
1682 data->attachments = g_list_append (data->attachments,
1684 tny_iterator_next (att_iter);
1686 g_object_unref (att_iter);
1688 GtkTextTagTable *tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (priv->text_buffer));
1689 att_iter = tny_list_create_iterator (priv->images);
1690 data->images = NULL;
1691 while (!tny_iterator_is_done (att_iter)) {
1692 TnyMimePart *part = (TnyMimePart *) tny_iterator_get_current (att_iter);
1694 if (!(TNY_IS_MIME_PART(part))) {
1695 g_warning ("strange data in attachment list");
1696 g_object_unref (part);
1697 tny_iterator_next (att_iter);
1700 cid = tny_mime_part_get_content_id (part);
1702 gchar *image_tag_id;
1703 GtkTextTag *image_tag;
1705 image_tag_id = g_strdup_printf ("image-tag-%s", cid);
1706 image_tag = gtk_text_tag_table_lookup (tag_table, image_tag_id);
1707 g_free (image_tag_id);
1709 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
1711 ((gtk_text_iter_has_tag (&iter, image_tag))||
1712 (gtk_text_iter_forward_to_tag_toggle (&iter, image_tag))))
1713 data->images = g_list_append (data->images,
1714 g_object_ref (part));
1716 g_object_unref (part);
1717 tny_iterator_next (att_iter);
1719 g_object_unref (att_iter);
1721 data->priority_flags = priv->priority_flags;
1728 unref_gobject (GObject *obj, gpointer data)
1730 if (!G_IS_OBJECT(obj))
1732 g_object_unref (obj);
1736 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1739 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1747 g_free (data->from);
1748 g_free (data->subject);
1749 g_free (data->plain_body);
1750 g_free (data->html_body);
1751 g_free (data->account_name);
1753 if (data->draft_msg != NULL) {
1754 g_object_unref (data->draft_msg);
1755 data->draft_msg = NULL;
1758 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1759 g_list_free (data->attachments);
1760 g_list_foreach (data->images, (GFunc)unref_gobject, NULL);
1761 g_list_free (data->images);
1763 g_slice_free (MsgData, data);
1767 modest_msg_edit_window_get_parts_size (ModestMsgEditWindow *window,
1769 guint64 *parts_size)
1771 ModestMsgEditWindowPrivate *priv;
1773 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1775 modest_attachments_view_get_sizes (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), parts_count, parts_size);
1777 /* TODO: add images */
1778 *parts_size += priv->images_size;
1779 *parts_count += priv->images_count;
1784 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1787 ModestMsgEditWindowPrivate *priv = NULL;
1788 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1790 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1792 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1794 return MODEST_MSG_EDIT_FORMAT_HTML;
1796 return MODEST_MSG_EDIT_FORMAT_TEXT;
1800 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1801 ModestMsgEditFormat format)
1803 ModestMsgEditWindowPrivate *priv;
1805 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1806 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1809 case MODEST_MSG_EDIT_FORMAT_HTML:
1810 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1812 case MODEST_MSG_EDIT_FORMAT_TEXT:
1813 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1816 g_return_if_reached ();
1820 ModestMsgEditFormatState *
1821 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1823 ModestMsgEditFormatState *format_state = NULL;
1824 ModestMsgEditWindowPrivate *priv;
1825 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1827 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1828 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1830 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1832 format_state = g_new0 (ModestMsgEditFormatState, 1);
1833 format_state->bold = buffer_format->bold&0x1;
1834 format_state->italics = buffer_format->italic&0x1;
1835 format_state->bullet = buffer_format->bullet&0x1;
1836 format_state->color = buffer_format->color;
1837 format_state->font_size = buffer_format->font_size;
1838 format_state->font_family = wp_get_font_name (buffer_format->font);
1839 format_state->justification = buffer_format->justification;
1840 g_free (buffer_format);
1842 return format_state;
1847 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1848 const ModestMsgEditFormatState *format_state)
1850 ModestMsgEditWindowPrivate *priv;
1851 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1852 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1853 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1854 g_return_if_fail (format_state != NULL);
1856 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1857 gtk_widget_grab_focus (priv->msg_body);
1858 buffer_format->bold = (format_state->bold != FALSE);
1859 buffer_format->italic = (format_state->italics != FALSE);
1860 buffer_format->color = format_state->color;
1861 buffer_format->font_size = format_state->font_size;
1862 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1863 buffer_format->justification = format_state->justification;
1864 buffer_format->bullet = format_state->bullet;
1866 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1868 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1869 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1870 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1871 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1872 buffer_format->cs.font = (buffer_format->font != current_format->font);
1873 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1874 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1876 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1877 if (buffer_format->cs.bold) {
1878 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD,
1879 GINT_TO_POINTER (buffer_format->bold&0x1));
1881 if (buffer_format->cs.italic) {
1882 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC,
1883 GINT_TO_POINTER (buffer_format->italic&0x1));
1885 if (buffer_format->cs.color) {
1886 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
1887 GINT_TO_POINTER (&(buffer_format->color)));
1889 if (buffer_format->cs.font_size) {
1890 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1891 GINT_TO_POINTER (buffer_format->font_size));
1893 if (buffer_format->cs.justification) {
1894 switch (buffer_format->justification) {
1895 case GTK_JUSTIFY_LEFT:
1896 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT,
1897 GINT_TO_POINTER(TRUE));
1899 case GTK_JUSTIFY_CENTER:
1900 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER,
1901 GINT_TO_POINTER(TRUE));
1903 case GTK_JUSTIFY_RIGHT:
1904 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT,
1905 GINT_TO_POINTER(TRUE));
1912 if (buffer_format->cs.font) {
1913 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
1914 GINT_TO_POINTER (buffer_format->font));
1916 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1917 if (buffer_format->cs.bullet) {
1918 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET,
1919 GINT_TO_POINTER ((buffer_format->bullet)?1:0));
1921 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1923 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), self);
1925 g_free (current_format);
1930 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1932 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1934 ModestWindowPrivate *parent_priv;
1935 ModestMsgEditWindowPrivate *priv;
1936 GtkWidget *new_size_menuitem;
1937 GtkWidget *new_font_menuitem;
1939 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1940 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1942 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1943 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1944 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1945 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1947 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1948 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1949 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1952 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1954 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1955 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1957 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1958 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1960 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu"); */
1961 /* modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet); */
1964 switch (buffer_format->justification)
1966 case GTK_JUSTIFY_LEFT:
1967 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
1969 case GTK_JUSTIFY_CENTER:
1970 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
1972 case GTK_JUSTIFY_RIGHT:
1973 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
1980 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1982 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1983 G_CALLBACK (modest_msg_edit_window_color_button_change),
1985 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1986 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1987 G_CALLBACK (modest_msg_edit_window_color_button_change),
1990 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1991 buffer_format->font_size))->data);
1992 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1996 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1997 markup = g_strconcat ("<span font_family='Sans'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1998 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2000 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
2001 G_CALLBACK (modest_msg_edit_window_size_change),
2003 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
2004 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
2005 G_CALLBACK (modest_msg_edit_window_size_change),
2009 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
2010 buffer_format->font))->data);
2011 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
2015 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
2016 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2017 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2019 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
2020 G_CALLBACK (modest_msg_edit_window_font_change),
2022 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
2023 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
2024 G_CALLBACK (modest_msg_edit_window_font_change),
2028 g_free (buffer_format);
2032 #ifdef MODEST_HILDON_VERSION_0
2034 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2037 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2038 ModestMsgEditWindowPrivate *priv;
2039 GtkWidget *dialog = NULL;
2041 GdkColor *new_color = NULL;
2043 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2044 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2046 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2047 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
2048 g_free (buffer_format);
2050 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2051 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2052 if (new_color != NULL) {
2053 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2054 (gpointer) new_color);
2057 gtk_widget_destroy (dialog);
2062 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2065 ModestMsgEditWindowPrivate *priv;
2066 GtkWidget *dialog = NULL;
2068 GdkColor *old_color = NULL;
2069 const GdkColor *new_color = NULL;
2071 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2072 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2074 dialog = hildon_color_selector_new (GTK_WINDOW (window));
2075 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
2077 if (gtk_dialog_run (GTK_DIALOG (dialog) == GTK_RESPONSE_OK)) {
2078 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
2079 if (new_color != NULL)
2080 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
2082 gtk_widget_destroy (dialog);
2088 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
2091 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
2092 ModestMsgEditWindowPrivate *priv;
2093 GtkWidget *dialog = NULL;
2095 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2096 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
2098 dialog = hildon_color_chooser_new ();
2099 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
2100 g_free (buffer_format);
2102 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2104 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2105 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR,
2108 gtk_widget_destroy (dialog);
2113 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
2116 ModestMsgEditWindowPrivate *priv;
2117 GtkWidget *dialog = NULL;
2118 GdkColor *old_color = NULL;
2120 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2121 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
2123 dialog = hildon_color_chooser_new ();
2124 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
2126 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
2128 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
2129 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), &col);
2131 gtk_widget_destroy (dialog);
2134 #endif /*!MODEST_HILDON_VERSION_0*/
2138 static TnyStream* create_stream_for_uri (const gchar* uri)
2143 TnyStream *result = NULL;
2145 GnomeVFSHandle *handle = NULL;
2146 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2147 if (test == GNOME_VFS_OK) {
2148 TnyStream *vfssstream = TNY_STREAM (tny_vfs_stream_new (handle));
2149 /* Streams over OBEX (Bluetooth) are not seekable but
2150 * we expect them to be (we might need to read them
2151 * several times). So if this is a Bluetooth URI just
2152 * read the whole file into memory (this is not a fast
2153 * protocol so we can assume that these files are not
2154 * going to be very big) */
2155 if (g_ascii_strncasecmp (uri, "obex://", 7) == 0) {
2156 TnyStream *memstream = tny_camel_mem_stream_new ();
2157 tny_stream_write_to_stream (vfssstream, memstream);
2158 g_object_unref (vfssstream);
2161 result = vfssstream;
2169 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
2172 ModestMsgEditWindowPrivate *priv;
2173 GtkWidget *dialog = NULL;
2175 GSList *uris = NULL;
2176 GSList *uri_node = NULL;
2178 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2180 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2181 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
2182 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2184 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
2186 response = gtk_dialog_run (GTK_DIALOG (dialog));
2188 case GTK_RESPONSE_OK:
2189 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2194 gtk_widget_destroy (dialog);
2196 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2198 GnomeVFSHandle *handle = NULL;
2199 GnomeVFSResult result;
2200 GtkTextIter position;
2201 GtkTextMark *insert_mark;
2203 uri = (const gchar *) uri_node->data;
2204 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2205 if (result == GNOME_VFS_OK) {
2207 GnomeVFSFileInfo *info;
2208 gchar *filename, *basename, *escaped_filename;
2209 TnyMimePart *mime_part;
2211 const gchar *mime_type = NULL;
2212 GnomeVFSURI *vfs_uri;
2213 guint64 stream_size;
2215 gnome_vfs_close (handle);
2216 vfs_uri = gnome_vfs_uri_new (uri);
2218 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2219 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2220 g_free (escaped_filename);
2221 gnome_vfs_uri_unref (vfs_uri);
2222 info = gnome_vfs_file_info_new ();
2224 if (gnome_vfs_get_file_info (uri, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
2225 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
2227 mime_type = gnome_vfs_file_info_get_mime_type (info);
2229 mime_part = tny_platform_factory_new_mime_part
2230 (modest_runtime_get_platform_factory ());
2232 TnyStream *stream = create_stream_for_uri (uri);
2233 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2235 content_id = g_strdup_printf ("%d", priv->next_cid);
2236 tny_mime_part_set_content_id (mime_part, content_id);
2237 g_free (content_id);
2240 basename = g_path_get_basename (filename);
2241 tny_mime_part_set_filename (mime_part, basename);
2244 pixbuf = pixbuf_from_stream (stream, mime_type, &stream_size);
2246 if (pixbuf != NULL) {
2247 priv->images_size += stream_size;
2248 priv->images_count ++;
2249 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
2250 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
2251 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
2254 tny_list_prepend (priv->images, (GObject *) mime_part);
2255 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2257 g_object_unref (mime_part);
2258 gnome_vfs_file_info_unref (info);
2267 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
2269 GtkWidget *dialog = NULL;
2271 GSList *uris = NULL;
2274 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
2275 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
2276 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
2278 response = gtk_dialog_run (GTK_DIALOG (dialog));
2280 case GTK_RESPONSE_OK:
2281 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
2286 gtk_widget_destroy (dialog);
2288 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
2289 const gchar *uri = (const gchar *) uri_node->data;
2290 modest_msg_edit_window_attach_file_one (window, uri);
2292 g_slist_foreach (uris, (GFunc) g_free, NULL);
2293 g_slist_free (uris);
2297 modest_msg_edit_window_attach_file_one (
2298 ModestMsgEditWindow *window,
2301 GnomeVFSHandle *handle = NULL;
2302 ModestMsgEditWindowPrivate *priv;
2303 GnomeVFSResult result;
2305 g_return_if_fail (window);
2306 g_return_if_fail (uri);
2308 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2310 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
2311 if (result == GNOME_VFS_OK) {
2312 TnyMimePart *mime_part;
2314 const gchar *mime_type = NULL;
2316 gchar *escaped_filename;
2319 GnomeVFSFileInfo *info;
2320 GnomeVFSURI *vfs_uri;
2322 gnome_vfs_close (handle);
2323 vfs_uri = gnome_vfs_uri_new (uri);
2326 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
2327 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
2328 g_free (escaped_filename);
2329 gnome_vfs_uri_unref (vfs_uri);
2331 info = gnome_vfs_file_info_new ();
2333 if (gnome_vfs_get_file_info (uri,
2335 GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
2337 mime_type = gnome_vfs_file_info_get_mime_type (info);
2338 mime_part = tny_platform_factory_new_mime_part
2339 (modest_runtime_get_platform_factory ());
2340 stream = create_stream_for_uri (uri);
2342 tny_mime_part_construct (mime_part, stream, mime_type, "base64");
2344 g_object_unref (stream);
2346 content_id = g_strdup_printf ("%d", priv->next_cid);
2347 tny_mime_part_set_content_id (mime_part, content_id);
2348 g_free (content_id);
2351 basename = g_path_get_basename (filename);
2352 tny_mime_part_set_filename (mime_part, basename);
2355 tny_list_prepend (priv->attachments, (GObject *) mime_part);
2356 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2358 info->size == 0, info->size);
2359 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
2360 gtk_widget_show_all (priv->attachments_caption);
2361 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2363 g_object_unref (mime_part);
2364 gnome_vfs_file_info_unref (info);
2369 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
2372 ModestMsgEditWindowPrivate *priv;
2375 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2376 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2378 if (att_list == NULL) {
2379 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2381 g_object_ref (att_list);
2384 if (tny_list_get_length (att_list) == 0) {
2385 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
2387 GtkWidget *confirmation_dialog = NULL;
2388 gboolean dialog_response;
2389 gchar *message = NULL;
2390 gchar *filename = NULL;
2392 if (tny_list_get_length (att_list) == 1) {
2394 iter = tny_list_create_iterator (att_list);
2395 part = (TnyMimePart *) tny_iterator_get_current (iter);
2396 g_object_unref (iter);
2397 if (TNY_IS_MSG (part)) {
2398 TnyHeader *header = tny_msg_get_header (TNY_MSG (part));
2400 filename = g_strdup (tny_header_get_subject (header));
2401 g_object_unref (header);
2403 if (filename == NULL) {
2404 filename = g_strdup (_("mail_va_no_subject"));
2407 filename = g_strdup (tny_mime_part_get_filename (TNY_MIME_PART (part)));
2409 g_object_unref (part);
2411 filename = g_strdup ("");
2413 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
2414 tny_list_get_length (att_list)), filename);
2416 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
2418 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
2419 gtk_widget_destroy (confirmation_dialog);
2420 if (!dialog_response) {
2421 g_object_unref (att_list);
2424 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
2426 for (iter = tny_list_create_iterator (att_list);
2427 !tny_iterator_is_done (iter);
2428 tny_iterator_next (iter)) {
2429 TnyMimePart *mime_part = (TnyMimePart *) tny_iterator_get_current (iter);
2430 const gchar *att_id;
2431 tny_list_remove (priv->attachments, (GObject *) mime_part);
2433 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
2435 if (tny_list_get_length (priv->attachments) == 0)
2436 gtk_widget_hide (priv->attachments_caption);
2437 att_id = tny_mime_part_get_content_id (mime_part);
2439 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
2441 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2442 g_object_unref (mime_part);
2444 g_object_unref (iter);
2447 g_object_unref (att_list);
2449 /* if the last attachment has been removed, focus the Subject: field */
2450 if (!modest_attachments_view_has_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view)))
2451 gtk_widget_grab_focus (priv->subject_field);
2455 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
2458 ModestMsgEditWindowPrivate *priv;
2459 GdkColor *new_color;
2460 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2462 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2463 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
2466 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
2468 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
2470 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
2472 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
2477 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
2480 ModestMsgEditWindowPrivate *priv;
2481 gint new_size_index;
2482 ModestMsgEditWindow *window;
2485 window = MODEST_MSG_EDIT_WINDOW (userdata);
2486 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2487 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2489 if (gtk_check_menu_item_get_active (menu_item)) {
2491 WPTextBufferFormat format;
2493 memset (&format, 0, sizeof (format));
2494 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
2496 label = gtk_bin_get_child (GTK_BIN (menu_item));
2498 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
2499 format.cs.font_size = TRUE;
2500 format.cs.text_position = TRUE;
2501 format.cs.font = TRUE;
2502 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
2503 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
2505 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
2506 GINT_TO_POINTER (wp_get_font_size_index (new_size_index, 12))))
2507 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2509 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2510 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
2511 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
2517 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
2520 ModestMsgEditWindowPrivate *priv;
2521 gint new_font_index;
2522 ModestMsgEditWindow *window;
2525 window = MODEST_MSG_EDIT_WINDOW (userdata);
2526 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2527 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2529 if (gtk_check_menu_item_get_active (menu_item)) {
2532 label = gtk_bin_get_child (GTK_BIN (menu_item));
2534 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2536 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2537 GINT_TO_POINTER(new_font_index)))
2538 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2540 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2541 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2542 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2548 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2550 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2551 ModestWindowPrivate *parent_priv;
2552 ModestWindowMgr *mgr;
2553 gboolean is_fullscreen;
2554 GtkAction *fs_toggle_action;
2557 mgr = modest_runtime_get_window_mgr ();
2558 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2560 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2562 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2563 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2564 if (is_fullscreen != active)
2565 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2573 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2576 ModestMsgEditWindowPrivate *priv = NULL;
2577 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2579 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2580 if (!priv->update_caption_visibility)
2583 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2585 gtk_widget_show (priv->cc_caption);
2587 gtk_widget_hide (priv->cc_caption);
2589 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2593 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2596 ModestMsgEditWindowPrivate *priv = NULL;
2597 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2599 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2600 if (!priv->update_caption_visibility)
2603 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2605 gtk_widget_show (priv->bcc_caption);
2607 gtk_widget_hide (priv->bcc_caption);
2609 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2613 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2614 ModestRecptEditor *editor)
2616 ModestMsgEditWindowPrivate *priv;
2618 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2619 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2620 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2622 if (editor == NULL) {
2623 GtkWidget *view_focus;
2624 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2626 /* This code should be kept in sync with ModestRecptEditor. The
2627 textview inside the recpt editor is the one that really gets the
2628 focus. As it's inside a scrolled window, and this one inside the
2629 hbox recpt editor inherits from, we'll need to go up in the
2630 hierarchy to know if the text view is part of the recpt editor
2631 or if it's a different text entry */
2633 if (gtk_widget_get_parent (view_focus)) {
2634 GtkWidget *first_parent;
2636 first_parent = gtk_widget_get_parent (view_focus);
2637 if (gtk_widget_get_parent (first_parent) &&
2638 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2639 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2644 editor = MODEST_RECPT_EDITOR (priv->to_field);
2648 modest_address_book_select_addresses (editor);
2653 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2655 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2657 modest_msg_edit_window_open_addressbook (window, NULL);
2661 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2662 gboolean show_toolbar)
2664 ModestWindowPrivate *parent_priv;
2665 const gchar *action_name;
2668 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2669 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2671 /* We can not just use the code of
2672 modest_msg_edit_window_setup_toolbar because it has a
2673 mixture of both initialization and creation code. */
2675 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2677 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2679 /* Update also the actions (to update the toggles in the
2680 menus), we have to do it manually because some other window
2681 of the same time could have changed it (remember that the
2682 toolbar fullscreen mode is shared by all the windows of the
2684 if (modest_window_mgr_get_fullscreen_mode (modest_runtime_get_window_mgr ()))
2685 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarFullScreenMenu";
2687 action_name = "/MenuBar/ViewMenu/ShowToolbarMenu/ViewShowToolbarNormalScreenMenu";
2689 action = gtk_ui_manager_get_action (parent_priv->ui_manager, action_name);
2690 modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
2696 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2697 TnyHeaderFlags priority_flags)
2699 ModestMsgEditWindowPrivate *priv;
2700 ModestWindowPrivate *parent_priv;
2702 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2704 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2705 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2707 if (priv->priority_flags != priority_flags) {
2708 GtkAction *priority_action = NULL;
2710 priv->priority_flags = priority_flags;
2712 switch (priority_flags) {
2713 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2714 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2715 gtk_widget_show (priv->priority_icon);
2716 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2717 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2719 case TNY_HEADER_FLAG_LOW_PRIORITY:
2720 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2721 gtk_widget_show (priv->priority_icon);
2722 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2723 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2726 gtk_widget_hide (priv->priority_icon);
2727 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2728 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2731 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2732 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2737 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2740 ModestMsgEditWindowPrivate *priv;
2741 ModestWindowPrivate *parent_priv;
2742 gint current_format;
2744 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2746 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2747 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2749 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2750 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2752 if (current_format != file_format) {
2753 switch (file_format) {
2754 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2755 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2756 remove_tags (WP_TEXT_BUFFER (priv->text_buffer));
2758 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2762 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2763 response = gtk_dialog_run (GTK_DIALOG (dialog));
2764 gtk_widget_destroy (dialog);
2765 if (response == GTK_RESPONSE_OK) {
2766 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2768 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2769 modest_utils_toggle_action_set_active_block_notify (action, TRUE);
2774 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2775 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2780 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2783 ModestMsgEditWindowPrivate *priv;
2784 WPTextBufferFormat oldfmt, fmt;
2785 gint old_position = 0;
2789 GdkColor *color = NULL;
2790 gboolean bold, bold_set, italic, italic_set;
2791 gboolean underline, underline_set;
2792 gboolean strikethrough, strikethrough_set;
2793 gboolean position_set;
2794 gboolean font_size_set, font_set, color_set;
2797 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2798 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2800 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2802 /* First we get the currently selected font information */
2803 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2805 switch (oldfmt.text_position) {
2806 case TEXT_POSITION_NORMAL:
2809 case TEXT_POSITION_SUPERSCRIPT:
2817 g_object_set (G_OBJECT (dialog),
2818 "bold", oldfmt.bold != FALSE,
2819 "bold-set", !oldfmt.cs.bold,
2820 "underline", oldfmt.underline != FALSE,
2821 "underline-set", !oldfmt.cs.underline,
2822 "italic", oldfmt.italic != FALSE,
2823 "italic-set", !oldfmt.cs.italic,
2824 "strikethrough", oldfmt.strikethrough != FALSE,
2825 "strikethrough-set", !oldfmt.cs.strikethrough,
2826 "color", &oldfmt.color,
2827 "color-set", !oldfmt.cs.color,
2828 "size", wp_font_size[oldfmt.font_size],
2829 "size-set", !oldfmt.cs.font_size,
2830 "position", old_position,
2831 "position-set", !oldfmt.cs.text_position,
2832 "family", wp_get_font_name (oldfmt.font),
2833 "family-set", !oldfmt.cs.font,
2836 gtk_widget_show_all (dialog);
2837 response = gtk_dialog_run (GTK_DIALOG (dialog));
2838 if (response == GTK_RESPONSE_OK) {
2840 g_object_get( dialog,
2842 "bold-set", &bold_set,
2843 "underline", &underline,
2844 "underline-set", &underline_set,
2846 "italic-set", &italic_set,
2847 "strikethrough", &strikethrough,
2848 "strikethrough-set", &strikethrough_set,
2850 "color-set", &color_set,
2852 "size-set", &font_size_set,
2853 "family", &font_name,
2854 "family-set", &font_set,
2855 "position", &position,
2856 "position-set", &position_set,
2861 if (response == GTK_RESPONSE_OK) {
2862 memset(&fmt, 0, sizeof(fmt));
2868 fmt.italic = italic;
2869 fmt.cs.italic = TRUE;
2871 if (underline_set) {
2872 fmt.underline = underline;
2873 fmt.cs.underline = TRUE;
2875 if (strikethrough_set) {
2876 fmt.strikethrough = strikethrough;
2877 fmt.cs.strikethrough = TRUE;
2882 ? TEXT_POSITION_NORMAL
2883 : ( ( position == 1 )
2884 ? TEXT_POSITION_SUPERSCRIPT
2885 : TEXT_POSITION_SUBSCRIPT );
2886 fmt.cs.text_position = TRUE;
2887 fmt.font_size = oldfmt.font_size;
2891 fmt.cs.color = TRUE;
2894 fmt.font = wp_get_font_index(font_name,
2899 if (font_size_set) {
2900 fmt.cs.font_size = TRUE;
2901 fmt.font_size = wp_get_font_size_index(font_size, DEFAULT_FONT_SIZE);
2903 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2904 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), window);
2906 gtk_widget_destroy (dialog);
2908 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2912 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2914 ModestMsgEditWindowPrivate *priv;
2916 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2917 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2919 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2921 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2922 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2927 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2929 ModestMsgEditWindowPrivate *priv;
2931 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2932 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2934 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2936 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
2937 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2942 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2944 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2946 priv->can_undo = can_undo;
2950 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2952 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2954 priv->can_redo = can_redo;
2958 modest_msg_edit_window_can_undo (ModestMsgEditWindow *window)
2960 ModestMsgEditWindowPrivate *priv;
2961 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2962 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2964 return priv->can_undo;
2968 modest_msg_edit_window_can_redo (ModestMsgEditWindow *window)
2970 ModestMsgEditWindowPrivate *priv;
2971 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2972 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2974 return priv->can_redo;
2979 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2982 GtkTextIter match_start, match_end;
2984 if (image_id == NULL)
2987 gtk_text_buffer_get_start_iter (buffer, &iter);
2989 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2990 GSList *tags = gtk_text_iter_get_tags (&match_start);
2992 for (node = tags; node != NULL; node = g_slist_next (node)) {
2993 GtkTextTag *tag = (GtkTextTag *) node->data;
2994 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2995 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2996 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2998 offset = gtk_text_iter_get_offset (&match_start);
2999 gtk_text_buffer_delete (buffer, &match_start, &match_end);
3000 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
3004 gtk_text_iter_forward_char (&iter);
3009 message_is_empty (ModestMsgEditWindow *window)
3011 ModestMsgEditWindowPrivate *priv = NULL;
3013 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3014 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3016 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
3017 * so we can ignore markup.
3019 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
3022 count = gtk_text_buffer_get_char_count (buf);
3028 msg_body_focus (GtkWidget *focus,
3029 GdkEventFocus *event,
3033 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (userdata));
3034 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (userdata));
3035 modest_window_check_dimming_rules_group (MODEST_WINDOW (userdata), MODEST_DIMMING_RULES_CLIPBOARD);
3040 recpt_field_changed (GtkTextBuffer *buffer,
3041 ModestMsgEditWindow *editor)
3043 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3044 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3048 body_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor)
3050 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (editor));
3051 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (editor));
3055 modest_msg_edit_window_set_modified (ModestMsgEditWindow *editor,
3058 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3059 GtkTextBuffer *buffer;
3061 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3062 gtk_text_buffer_set_modified (buffer, modified);
3063 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3064 gtk_text_buffer_set_modified (buffer, modified);
3065 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3066 gtk_text_buffer_set_modified (buffer, modified);
3067 gtk_text_buffer_set_modified (priv->text_buffer, modified);
3071 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
3073 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
3074 const char *account_name;
3075 GtkTextBuffer *buffer;
3077 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
3078 if (gtk_text_buffer_get_modified (buffer))
3080 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
3081 if (gtk_text_buffer_get_modified (buffer))
3083 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
3084 if (gtk_text_buffer_get_modified (buffer))
3086 if (gtk_text_buffer_get_modified (priv->text_buffer))
3088 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
3089 if (!priv->original_account_name || strcmp(account_name, priv->original_account_name)) {
3100 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
3102 ModestMsgEditWindowPrivate *priv = NULL;
3104 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3105 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3107 /* check if there's no recipient added */
3108 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
3109 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
3110 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
3111 /* no recipient contents, then select contacts */
3112 modest_msg_edit_window_open_addressbook (window, NULL);
3116 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
3117 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3120 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
3121 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
3124 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
3125 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
3129 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
3130 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
3131 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
3138 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
3139 ModestMsgEditWindow *window)
3141 modest_msg_edit_window_offer_attach_file (window);
3145 modest_msg_edit_window_get_clipboard_text (ModestMsgEditWindow *win)
3147 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3149 return priv->clipboard_text;
3153 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
3155 ModestMsgEditWindow *window)
3157 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3158 GtkClipboard *selection_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3160 if (!GTK_WIDGET_VISIBLE (window))
3163 g_object_ref (window);
3164 text = gtk_clipboard_wait_for_text (selection_clipboard);
3166 if (priv->clipboard_text != NULL) {
3167 g_free (priv->clipboard_text);
3169 priv->clipboard_text = text;
3171 if (GTK_WIDGET_VISIBLE (window)) {
3172 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3174 g_object_unref (window);
3177 static gboolean clipboard_owner_change_idle (gpointer userdata)
3179 ModestMsgEditWindow *window = (ModestMsgEditWindow *) userdata;
3180 ModestMsgEditWindowPrivate *priv;
3182 gdk_threads_enter ();
3183 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3184 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3186 priv->clipboard_owner_idle = 0;
3187 modest_msg_edit_window_clipboard_owner_change (NULL, NULL, window);
3188 gdk_threads_leave ();
3194 modest_msg_edit_window_clipboard_owner_handle_change_in_idle (ModestMsgEditWindow *window)
3196 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3197 if (priv->clipboard_owner_idle == 0) {
3198 priv->clipboard_owner_idle = g_idle_add (clipboard_owner_change_idle, window);
3203 subject_field_move_cursor (GtkEntry *entry,
3204 GtkMovementStep step,
3209 if (!GTK_WIDGET_VISIBLE (window))
3212 modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD);
3216 update_window_title (ModestMsgEditWindow *window)
3218 ModestMsgEditWindowPrivate *priv = NULL;
3219 const gchar *subject;
3221 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3222 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
3223 if (subject == NULL || subject[0] == '\0')
3224 subject = _("mail_va_new_email");
3226 gtk_window_set_title (GTK_WINDOW (window), subject);
3231 subject_field_changed (GtkEditable *editable,
3232 ModestMsgEditWindow *window)
3234 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3235 update_window_title (window);
3236 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3237 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3238 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
3242 subject_field_insert_text (GtkEditable *editable,
3244 gint new_text_length,
3246 ModestMsgEditWindow *window)
3248 GString *result = g_string_new ("");
3250 gint result_len = 0;
3251 const gchar *entry_text = NULL;
3254 entry_text = gtk_entry_get_text (GTK_ENTRY (editable));
3255 old_length = g_utf8_strlen (entry_text, -1);
3257 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3258 gunichar c = g_utf8_get_char_validated (current, 8);
3259 /* Invalid unichar, stop */
3265 result = g_string_append_unichar (result, c);
3269 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
3270 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
3273 /* Prevent endless recursion */
3274 g_signal_handlers_block_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3275 g_signal_emit_by_name (editable, "insert-text",
3276 (gpointer) result->str, (gpointer) result->len,
3277 (gpointer) position, (gpointer) window);
3278 g_signal_handlers_unblock_by_func(G_OBJECT(editable), G_CALLBACK(subject_field_insert_text), window);
3282 if (result_len + old_length > 1000) {
3283 hildon_banner_show_information (GTK_WIDGET (window), NULL,
3284 dgettext("hildon-common-strings",
3285 "ckdg_ib_maximum_characters_reached"));
3288 g_string_free (result, TRUE);
3292 text_buffer_insert_text (GtkTextBuffer *buffer,
3295 gint new_text_length,
3296 ModestMsgEditWindow *window)
3298 GString *result = g_string_new ("");
3300 gint result_len = 0;
3301 gboolean changed = FALSE;
3303 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
3304 gunichar c = g_utf8_get_char_validated (current, 8);
3305 /* Invalid unichar, stop */
3311 result = g_string_append_c (result, ' ');
3315 result = g_string_append_unichar (result, c);
3321 g_signal_stop_emission_by_name (G_OBJECT (buffer), "insert-text");
3322 g_signal_handlers_block_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3323 g_signal_emit_by_name (buffer, "insert-text",
3325 (gpointer) result->str, (gpointer) result->len,
3327 g_signal_handlers_unblock_by_func(G_OBJECT(buffer), G_CALLBACK(text_buffer_insert_text), window);
3330 g_string_free (result, TRUE);
3334 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
3337 ModestMsgEditWindowPrivate *priv = NULL;
3339 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3340 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3342 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
3345 gtk_widget_show_all (priv->find_toolbar);
3346 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
3348 gtk_widget_hide_all (priv->find_toolbar);
3349 gtk_widget_grab_focus (priv->msg_body);
3355 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
3357 GtkTextIter *match_start,
3358 GtkTextIter *match_end)
3360 GtkTextIter end_iter;
3361 gchar *str_casefold;
3364 gchar *range_casefold;
3367 gboolean result = FALSE;
3374 gtk_text_iter_forward_to_end (&end_iter);
3376 str_casefold = g_utf8_casefold (str, -1);
3377 str_chars_n = strlen (str);
3379 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
3380 range_casefold = g_utf8_casefold (range_text, -1);
3381 range_chars_n = strlen (range_casefold);
3383 if (range_chars_n < str_chars_n) {
3384 g_free (str_casefold);
3385 g_free (range_text);
3386 g_free (range_casefold);
3390 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
3391 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
3392 if (!g_utf8_collate (range_subtext, str_casefold)) {
3393 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
3395 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
3396 match_start, match_end, NULL);
3397 g_free (found_text);
3399 g_free (range_subtext);
3403 g_free (str_casefold);
3404 g_free (range_text);
3405 g_free (range_casefold);
3412 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
3413 ModestMsgEditWindow *window)
3415 gchar *current_search = NULL;
3416 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3418 GtkTextIter selection_start, selection_end;
3419 GtkTextIter match_start, match_end;
3420 gboolean continue_search = FALSE;
3422 if (message_is_empty (window)) {
3423 g_free (priv->last_search);
3424 priv->last_search = NULL;
3425 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
3429 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
3430 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
3431 g_free (current_search);
3432 g_free (priv->last_search);
3433 priv->last_search = NULL;
3434 /* Information banner about empty search */
3435 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
3439 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
3440 continue_search = TRUE;
3442 g_free (priv->last_search);
3443 priv->last_search = g_strdup (current_search);
3446 if (continue_search) {
3447 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
3448 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
3449 &match_start, &match_end);
3451 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
3453 GtkTextIter buffer_start;
3454 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
3455 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
3456 &match_start, &match_end);
3458 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3461 /* Mark as selected the string found in search */
3463 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3464 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3465 correct_scroll_without_drag_check (MODEST_MSG_EDIT_WINDOW (window), FALSE);
3467 g_free (priv->last_search);
3468 priv->last_search = NULL;
3470 g_free (current_search);
3474 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3475 ModestMsgEditWindow *window)
3477 GtkToggleAction *toggle;
3478 ModestWindowPrivate *parent_priv;
3479 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3481 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3482 gtk_toggle_action_set_active (toggle, FALSE);
3486 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3488 ModestMsgEditWindowPrivate *priv;
3490 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3495 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3498 ModestMsgEditWindowPrivate *priv;
3500 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3506 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3509 ModestMsgEditWindowPrivate *priv;
3510 TnyHeader *header = NULL;
3512 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3513 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3515 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3516 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3518 if (priv->draft_msg != NULL) {
3519 g_object_unref (priv->draft_msg);
3522 if (draft != NULL) {
3523 g_object_ref (draft);
3524 header = tny_msg_get_header (draft);
3525 if (priv->msg_uid) {
3526 g_free (priv->msg_uid);
3527 priv->msg_uid = NULL;
3529 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3530 if (GTK_WIDGET_REALIZED (window))
3531 modest_window_mgr_register_window (mgr, MODEST_WINDOW (window));
3534 priv->draft_msg = draft;
3538 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3539 GtkTextIter *start, GtkTextIter *end,
3542 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3543 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3546 if (tag == NULL+13) return;
3547 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3548 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3549 replace_with_images (window, priv->images);
3554 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3557 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3559 g_return_if_fail (TNY_IS_MIME_PART (part));
3560 tny_list_prepend (priv->attachments, (GObject *) part);
3561 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part, TRUE, 0);
3562 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3563 gtk_widget_show_all (priv->attachments_caption);
3564 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3568 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3570 ModestMsgEditWindowPrivate *priv;
3572 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3573 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3575 return priv->msg_uid;
3579 modest_msg_edit_window_get_child_widget (ModestMsgEditWindow *win,
3580 ModestMsgEditWindowWidgetType widget_type)
3582 ModestMsgEditWindowPrivate *priv;
3584 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (win), NULL);
3585 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (win);
3587 switch (widget_type) {
3588 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BODY:
3589 return priv->msg_body;
3591 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_TO:
3592 return priv->to_field;
3594 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_CC:
3595 return priv->cc_field;
3597 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_BCC:
3598 return priv->bcc_field;
3600 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_SUBJECT:
3601 return priv->subject_field;
3603 case MODEST_MSG_EDIT_WINDOW_WIDGET_TYPE_ATTACHMENTS:
3604 return priv->attachments_view;
3612 remove_tags (WPTextBuffer *buffer)
3614 GtkTextIter start, end;
3616 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &start);
3617 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &end);
3619 gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end);
3623 on_account_removed (TnyAccountStore *account_store,
3624 TnyAccount *account,
3627 /* Do nothing if it's a store account, because we use the
3628 transport to send the messages */
3629 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) {
3630 const gchar *parent_acc = NULL;
3631 const gchar *our_acc = NULL;
3633 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
3634 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
3635 /* Close this window if I'm showing a message of the removed account */
3636 if (strcmp (parent_acc, our_acc) == 0)
3637 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
3642 on_zoom_minus_plus_not_implemented (ModestWindow *window)
3644 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
3646 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
3652 set_zoom_do_nothing (ModestWindow *window,
3658 get_zoom_do_nothing (ModestWindow *window)