1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <glib/gi18n.h>
33 #include <glib/gstdio.h>
35 #include <tny-account-store.h>
36 #include <tny-fs-stream.h>
37 #include <tny-vfs-stream.h>
41 #include <modest-account-mgr.h>
42 #include <modest-account-mgr-helpers.h>
44 #include <widgets/modest-msg-edit-window.h>
45 #include <widgets/modest-combo-box.h>
46 #include <widgets/modest-recpt-editor.h>
47 #include <widgets/modest-attachments-view.h>
49 #include <modest-runtime.h>
51 #include "modest-platform.h"
52 #include "modest-icon-names.h"
53 #include "modest-widget-memory.h"
54 #include "modest-window-priv.h"
55 #include "modest-mail-operation.h"
56 #include "modest-tny-platform-factory.h"
57 #include "modest-tny-msg.h"
58 #include "modest-tny-folder.h"
59 #include "modest-address-book.h"
60 #include "modest-text-utils.h"
61 #include <tny-simple-list.h>
62 #include <wptextview.h>
63 #include <wptextbuffer.h>
64 #include "modest-scroll-area.h"
66 #include "modest-hildon-includes.h"
67 #ifdef MODEST_HAVE_HILDON0_WIDGETS
68 #include <hildon-widgets/hildon-color-chooser.h>
70 #include "widgets/modest-msg-edit-window-ui.h"
71 #ifdef MODEST_HAVE_HILDON0_WIDGETS
72 #include <libgnomevfs/gnome-vfs-mime-utils.h>
74 #include <libgnomevfs/gnome-vfs-mime.h>
76 #include "modest-maemo-utils.h"
79 #define DEFAULT_FONT_SIZE 3
80 #define DEFAULT_FONT 2
81 #define DEFAULT_SIZE_BUTTON_FONT_FAMILY "Sans"
82 #define DEFAULT_SIZE_COMBOBOX_WIDTH 80
83 #define DEFAULT_MAIN_VBOX_SPACING 6
84 #define SUBJECT_MAX_LENGTH 1000
85 #define IMAGE_MAX_WIDTH 560
86 #define DEFAULT_FONT_SCALE 1.5
88 static void modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass);
89 static void modest_msg_edit_window_init (ModestMsgEditWindow *obj);
90 static void modest_msg_edit_window_finalize (GObject *obj);
92 static gboolean msg_body_focus (GtkWidget *focus, GdkEventFocus *event, gpointer userdata);
93 static void recpt_field_changed (GtkTextBuffer *buffer, ModestMsgEditWindow *editor);
94 static void send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
95 static void style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor);
96 static void setup_insensitive_handlers (ModestMsgEditWindow *editor);
97 static void reset_modified (ModestMsgEditWindow *editor);
99 static void text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window);
100 static void text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window);
101 static void text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window);
102 static void text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
103 GtkTextIter *start, GtkTextIter *end,
105 static void text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id);
106 static void subject_field_changed (GtkEditable *editable, ModestMsgEditWindow *window);
107 static void subject_field_insert_text (GtkEditable *editable,
109 gint new_text_length,
111 ModestMsgEditWindow *window);
112 static void modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
114 static void modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
116 static void modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
118 static void modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window);
119 static gboolean modest_msg_edit_window_window_state_event (GtkWidget *widget,
120 GdkEventWindowState *event,
122 static void modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
123 ModestRecptEditor *editor);
124 static void modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
125 ModestMsgEditWindow *window);
127 /* ModestWindow methods implementation */
128 static void modest_msg_edit_window_disconnect_signals (ModestWindow *window);
129 static void modest_msg_edit_window_set_zoom (ModestWindow *window, gdouble zoom);
130 static gdouble modest_msg_edit_window_get_zoom (ModestWindow *window);
131 static gboolean modest_msg_edit_window_zoom_minus (ModestWindow *window);
132 static gboolean modest_msg_edit_window_zoom_plus (ModestWindow *window);
133 static void modest_msg_edit_window_show_toolbar (ModestWindow *window,
134 gboolean show_toolbar);
135 static void modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
137 ModestMsgEditWindow *window);
138 static void update_window_title (ModestMsgEditWindow *window);
139 static void update_dimmed (ModestMsgEditWindow *window);
140 static void update_paste_dimming (ModestMsgEditWindow *window);
141 static void update_copy_cut_dimming (ModestMsgEditWindow *window);
142 static void update_select_all_dimming (ModestMsgEditWindow *window);
143 static void update_zoom_dimming (ModestMsgEditWindow *window);
146 static void modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
147 ModestMsgEditWindow *window);
148 static void modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
149 ModestMsgEditWindow *window);
150 static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
152 GtkTextIter *match_start,
153 GtkTextIter *match_end);
155 static void DEBUG_BUFFER (WPTextBuffer *buffer)
160 g_message ("BEGIN BUFFER OF SIZE %d", gtk_text_buffer_get_char_count (GTK_TEXT_BUFFER (buffer)));
161 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (buffer), &iter);
162 while (!gtk_text_iter_is_end (&iter)) {
163 GString *output = g_string_new ("");
164 GSList *toggled_tags;
167 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, FALSE);
168 g_string_append_printf (output, "%d: CLOSED [ ", gtk_text_iter_get_offset (&iter));
169 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
170 GtkTextTag *tag = (GtkTextTag *) node->data;
172 g_object_get (G_OBJECT (tag), "name", &name, NULL);
173 output = g_string_append (output, name);
174 g_string_append (output, " ");
176 output = g_string_append (output, "] OPENED [ ");
177 toggled_tags = gtk_text_iter_get_toggled_tags (&iter, TRUE);
178 for (node = toggled_tags; node != NULL; node = g_slist_next (node)) {
179 GtkTextTag *tag = (GtkTextTag *) node->data;
181 g_object_get (G_OBJECT (tag), "name", &name, NULL);
182 output = g_string_append (output, name);
183 g_string_append (output, " ");
185 output = g_string_append (output, "]\n");
186 g_message ("%s", output->str);
187 g_string_free (output, TRUE);
188 gtk_text_iter_forward_to_tag_toggle (&iter, NULL);
190 g_message ("END BUFFER");
195 /* static gboolean */
196 /* on_key_pressed (GtkWidget *self, */
197 /* GdkEventKey *event, */
198 /* gpointer user_data); */
200 static void edit_menu_activated (GtkAction *action,
202 static void view_menu_activated (GtkAction *action,
205 /* list my signals */
212 typedef struct _ModestMsgEditWindowPrivate ModestMsgEditWindowPrivate;
213 struct _ModestMsgEditWindowPrivate {
215 GtkWidget *header_box;
217 ModestPairList *from_field_protos;
218 GtkWidget *from_field;
222 GtkWidget *bcc_field;
223 GtkWidget *subject_field;
224 GtkWidget *attachments_view;
225 GtkWidget *priority_icon;
226 GtkWidget *add_attachment_button;
228 GtkWidget *cc_caption;
229 GtkWidget *bcc_caption;
230 gboolean update_caption_visibility;
231 GtkWidget *attachments_caption;
233 GtkTextBuffer *text_buffer;
235 GtkWidget *font_size_toolitem;
236 GtkWidget *font_face_toolitem;
237 GtkWidget *font_color_button;
238 GSList *font_items_group;
239 GtkWidget *font_tool_button_label;
240 GSList *size_items_group;
241 GtkWidget *size_tool_button_label;
243 GtkWidget *find_toolbar;
247 GtkWidget *scroll_area;
248 gint last_vadj_upper;
253 TnyHeaderFlags priority_flags;
257 gulong clipboard_change_handler_id;
266 #define MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
267 MODEST_TYPE_MSG_EDIT_WINDOW, \
268 ModestMsgEditWindowPrivate))
270 static GtkWindowClass *parent_class = NULL;
272 /* uncomment the following if you have defined any signals */
273 /* static guint signals[LAST_SIGNAL] = {0}; */
276 modest_msg_edit_window_get_type (void)
278 static GType my_type = 0;
280 static const GTypeInfo my_info = {
281 sizeof(ModestMsgEditWindowClass),
282 NULL, /* base init */
283 NULL, /* base finalize */
284 (GClassInitFunc) modest_msg_edit_window_class_init,
285 NULL, /* class finalize */
286 NULL, /* class data */
287 sizeof(ModestMsgEditWindow),
289 (GInstanceInitFunc) modest_msg_edit_window_init,
292 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
293 "ModestMsgEditWindow",
296 wp_text_buffer_library_init ();
302 save_state (ModestWindow *self)
304 modest_widget_memory_save (modest_runtime_get_conf(),
305 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
310 restore_settings (ModestMsgEditWindow *self)
312 modest_widget_memory_restore (modest_runtime_get_conf(),
313 G_OBJECT(self), MODEST_CONF_EDIT_WINDOW_KEY);
318 modest_msg_edit_window_class_init (ModestMsgEditWindowClass *klass)
320 GObjectClass *gobject_class;
321 ModestWindowClass *modest_window_class;
322 gobject_class = (GObjectClass*) klass;
323 modest_window_class = (ModestWindowClass*) klass;
325 parent_class = g_type_class_peek_parent (klass);
326 gobject_class->finalize = modest_msg_edit_window_finalize;
328 modest_window_class->set_zoom_func = modest_msg_edit_window_set_zoom;
329 modest_window_class->get_zoom_func = modest_msg_edit_window_get_zoom;
330 modest_window_class->zoom_plus_func = modest_msg_edit_window_zoom_plus;
331 modest_window_class->zoom_minus_func = modest_msg_edit_window_zoom_minus;
332 modest_window_class->show_toolbar_func = modest_msg_edit_window_show_toolbar;
333 modest_window_class->save_state_func = save_state;
334 modest_window_class->disconnect_signals_func = modest_msg_edit_window_disconnect_signals;
336 g_type_class_add_private (gobject_class, sizeof(ModestMsgEditWindowPrivate));
340 modest_msg_edit_window_init (ModestMsgEditWindow *obj)
342 ModestMsgEditWindowPrivate *priv;
343 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
345 priv->msg_body = NULL;
346 priv->from_field = NULL;
347 priv->to_field = NULL;
348 priv->cc_field = NULL;
349 priv->bcc_field = NULL;
350 priv->subject_field = NULL;
351 priv->attachments = NULL;
353 priv->zoom_level = 1.0;
355 priv->cc_caption = NULL;
356 priv->bcc_caption = NULL;
357 priv->update_caption_visibility = FALSE;
359 priv->priority_flags = 0;
361 priv->find_toolbar = NULL;
362 priv->last_search = NULL;
364 priv->draft_msg = NULL;
365 priv->outbox_msg = NULL;
366 priv->msg_uid = NULL;
367 priv->clipboard_change_handler_id = 0;
370 priv->last_vadj_upper = 0;
374 /* FIXME: this is a dup from the one in gtk/ */
377 * @result: A ModestPairList, which must be freed with modest_pair_list_free().
379 static ModestPairList*
380 get_transports (void)
382 GSList *transports = NULL;
384 ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
385 GSList *accounts = modest_account_mgr_account_names (account_mgr,
386 TRUE /* only enabled accounts. */);
388 GSList *cursor = accounts;
390 gchar *account_name = cursor->data;
391 gchar *from_string = NULL;
393 from_string = modest_account_mgr_get_from_string (account_mgr,
397 if (from_string && account_name) {
398 gchar *name = account_name;
399 ModestPair *pair = modest_pair_new ((gpointer) name,
400 (gpointer) from_string , TRUE);
401 transports = g_slist_prepend (transports, pair);
404 cursor = cursor->next;
406 g_slist_free (accounts); /* only free the accounts, not the elements,
407 * because they are used in the pairlist */
411 void vadj_changed (GtkAdjustment *adj,
412 ModestMsgEditWindow *window)
414 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
416 GdkRectangle rectangle, cursor_rectangle;
417 GtkTextIter position;
421 /* We detect if cursor is visible using the full height, not only the center. This
423 gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (priv->msg_body), &rectangle);
424 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer),
426 gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer)));
427 gtk_text_view_get_iter_location (GTK_TEXT_VIEW (priv->msg_body), &position, &cursor_rectangle);
429 cursor_bottom = (cursor_rectangle.y + cursor_rectangle.height);
430 visible = (cursor_rectangle.y >= rectangle.y) && (cursor_bottom < (rectangle.y + rectangle.height));
432 if (gtk_widget_is_focus (priv->msg_body) &&
434 if (priv->last_vadj_upper != adj->upper) {
437 insert = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
438 gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (priv->msg_body),
439 insert, 0.1, FALSE, 0.0, 0.0);
442 priv->last_vadj_upper = adj->upper;
447 init_window (ModestMsgEditWindow *obj)
449 GtkWidget *from_caption, *to_caption, *subject_caption;
450 GtkWidget *main_vbox;
451 ModestMsgEditWindowPrivate *priv;
453 GtkSizeGroup *size_group;
455 GtkWidget *subject_box;
456 GtkWidget *attachment_icon;
457 GtkWidget *window_box;
458 #if (GTK_MINOR_VERSION >= 10)
459 GdkAtom deserialize_type;
461 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(obj);
463 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
465 /* Note: This ModestPairList* must exist for as long as the combo
466 * that uses it, because the ModestComboBox uses the ID opaquely,
467 * so it can't know how to manage its memory. */
468 priv->from_field_protos = get_transports ();
470 priv->from_field = modest_combo_box_new (priv->from_field_protos, g_str_equal);
472 priv->to_field = modest_recpt_editor_new ();
473 priv->cc_field = modest_recpt_editor_new ();
474 priv->bcc_field = modest_recpt_editor_new ();
475 subject_box = gtk_hbox_new (FALSE, 0);
476 priv->priority_icon = gtk_image_new ();
477 gtk_box_pack_start (GTK_BOX (subject_box), priv->priority_icon, FALSE, FALSE, 0);
478 priv->subject_field = gtk_entry_new_with_max_length (SUBJECT_MAX_LENGTH);
479 g_object_set (G_OBJECT (priv->subject_field), "truncate-multiline", TRUE, NULL);
480 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->subject_field),
481 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_AUTOCAP);
482 gtk_box_pack_start (GTK_BOX (subject_box), priv->subject_field, TRUE, TRUE, 0);
483 priv->add_attachment_button = gtk_button_new ();
484 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (priv->add_attachment_button), GTK_CAN_FOCUS);
485 gtk_button_set_relief (GTK_BUTTON (priv->add_attachment_button), GTK_RELIEF_NONE);
486 gtk_button_set_focus_on_click (GTK_BUTTON (priv->add_attachment_button), FALSE);
487 gtk_button_set_alignment (GTK_BUTTON (priv->add_attachment_button), 1.0, 1.0);
488 attachment_icon = gtk_image_new_from_icon_name (MODEST_HEADER_ICON_ATTACH, GTK_ICON_SIZE_BUTTON);
489 gtk_container_add (GTK_CONTAINER (priv->add_attachment_button), attachment_icon);
490 gtk_box_pack_start (GTK_BOX (subject_box), priv->add_attachment_button, FALSE, FALSE, 0);
491 priv->attachments_view = modest_attachments_view_new (NULL);
493 priv->header_box = gtk_vbox_new (FALSE, 0);
495 from_caption = hildon_caption_new (size_group, _("mail_va_from"), priv->from_field, NULL, 0);
496 to_caption = hildon_caption_new (size_group, _("mail_va_to"), priv->to_field, NULL, 0);
497 priv->cc_caption = hildon_caption_new (size_group, _("mail_va_cc"), priv->cc_field, NULL, 0);
498 priv->bcc_caption = hildon_caption_new (size_group, _("mail_va_hotfix1"), priv->bcc_field, NULL, 0);
499 subject_caption = hildon_caption_new (size_group, _("mail_va_subject"), subject_box, NULL, 0);
500 priv->attachments_caption = hildon_caption_new (size_group, _("mail_va_attachment"), priv->attachments_view, NULL, 0);
501 g_object_unref (size_group);
503 size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
504 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->to_field), size_group);
505 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->cc_field), size_group);
506 modest_recpt_editor_set_field_size_group (MODEST_RECPT_EDITOR (priv->bcc_field), size_group);
507 gtk_size_group_add_widget (size_group, priv->subject_field);
508 gtk_size_group_add_widget (size_group, priv->attachments_view);
509 g_object_unref (size_group);
511 gtk_box_pack_start (GTK_BOX (priv->header_box), from_caption, FALSE, FALSE, 0);
512 gtk_box_pack_start (GTK_BOX (priv->header_box), to_caption, FALSE, FALSE, 0);
513 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->cc_caption, FALSE, FALSE, 0);
514 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->bcc_caption, FALSE, FALSE, 0);
515 gtk_box_pack_start (GTK_BOX (priv->header_box), subject_caption, FALSE, FALSE, 0);
516 gtk_box_pack_start (GTK_BOX (priv->header_box), priv->attachments_caption, FALSE, FALSE, 0);
517 gtk_widget_set_no_show_all (priv->attachments_caption, TRUE);
520 priv->msg_body = wp_text_view_new ();
521 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->msg_body), GTK_WRAP_WORD_CHAR);
522 priv->text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
523 g_object_set (priv->text_buffer, "font_scale", DEFAULT_FONT_SCALE, NULL);
524 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
525 #if (GTK_MINOR_VERSION >= 10)
526 gtk_text_buffer_register_serialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer), "wp-text-buffer");
527 deserialize_type = gtk_text_buffer_register_deserialize_tagset(GTK_TEXT_BUFFER(priv->text_buffer),
529 gtk_text_buffer_deserialize_set_can_create_tags (GTK_TEXT_BUFFER (priv->text_buffer),
530 deserialize_type, TRUE);
532 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
534 priv->find_toolbar = hildon_find_toolbar_new (NULL);
535 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
537 /* g_signal_connect (G_OBJECT (obj), "key_pressed", G_CALLBACK (on_key_pressed), NULL) */
539 g_signal_connect (G_OBJECT (priv->text_buffer), "refresh_attributes",
540 G_CALLBACK (text_buffer_refresh_attributes), obj);
541 g_signal_connect (G_OBJECT (priv->text_buffer), "can-undo",
542 G_CALLBACK (text_buffer_can_undo), obj);
543 g_signal_connect (G_OBJECT (priv->text_buffer), "can-redo",
544 G_CALLBACK (text_buffer_can_redo), obj);
545 g_signal_connect (G_OBJECT (obj), "window-state-event",
546 G_CALLBACK (modest_msg_edit_window_window_state_event),
548 g_signal_connect_after (G_OBJECT (priv->text_buffer), "apply-tag",
549 G_CALLBACK (text_buffer_apply_tag), obj);
550 g_signal_connect_swapped (G_OBJECT (priv->to_field), "open-addressbook",
551 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
552 g_signal_connect_swapped (G_OBJECT (priv->cc_field), "open-addressbook",
553 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
554 g_signal_connect_swapped (G_OBJECT (priv->bcc_field), "open-addressbook",
555 G_CALLBACK (modest_msg_edit_window_open_addressbook), obj);
557 g_signal_connect (G_OBJECT (priv->add_attachment_button), "clicked",
558 G_CALLBACK (modest_msg_edit_window_add_attachment_clicked), obj);
560 g_signal_connect (G_OBJECT (priv->msg_body), "focus-in-event",
561 G_CALLBACK (msg_body_focus), obj);
562 g_signal_connect (G_OBJECT (priv->msg_body), "focus-out-event",
563 G_CALLBACK (msg_body_focus), obj);
564 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))),
565 "changed", G_CALLBACK (recpt_field_changed), obj);
566 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))),
567 "changed", G_CALLBACK (recpt_field_changed), obj);
568 g_signal_connect (G_OBJECT (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))),
569 "changed", G_CALLBACK (recpt_field_changed), obj);
570 recpt_field_changed (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field)), MODEST_MSG_EDIT_WINDOW (obj));
571 g_signal_connect (G_OBJECT (priv->subject_field), "changed", G_CALLBACK (subject_field_changed), obj);
572 g_signal_connect (G_OBJECT (priv->subject_field), "insert-text", G_CALLBACK (subject_field_insert_text), obj);
574 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_edit_window_find_toolbar_close), obj);
575 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_edit_window_find_toolbar_search), obj);
577 priv->scroll = gtk_scrolled_window_new (NULL, NULL);
578 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
579 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->scroll), GTK_SHADOW_NONE);
580 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->scroll), TRUE);
582 main_vbox = gtk_vbox_new (FALSE, DEFAULT_MAIN_VBOX_SPACING);
584 gtk_box_pack_start (GTK_BOX(main_vbox), priv->header_box, FALSE, FALSE, 0);
585 frame = gtk_frame_new (NULL);
586 gtk_box_pack_start (GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);
588 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (priv->scroll), main_vbox);
589 gtk_container_set_focus_vadjustment (GTK_CONTAINER (main_vbox), gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll)));
590 g_signal_connect (G_OBJECT (gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scroll))),
592 G_CALLBACK (vadj_changed),
594 gtk_widget_show_all (GTK_WIDGET(priv->scroll));
596 window_box = gtk_vbox_new (FALSE, 0);
597 gtk_box_pack_start (GTK_BOX (window_box), priv->scroll, TRUE, TRUE, 0);
598 gtk_container_add (GTK_CONTAINER(obj), window_box);
599 priv->scroll_area = modest_scroll_area_new (priv->scroll, priv->msg_body);
600 gtk_container_add (GTK_CONTAINER (frame), priv->scroll_area);
602 priv->clipboard_change_handler_id = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change",
603 G_CALLBACK (modest_msg_edit_window_clipboard_owner_change), obj);
608 modest_msg_edit_window_disconnect_signals (ModestWindow *window)
610 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
612 if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
613 priv->clipboard_change_handler_id))
614 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
615 priv->clipboard_change_handler_id);
619 modest_msg_edit_window_finalize (GObject *obj)
621 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
623 /* Sanity check: shouldn't be needed, the window mgr should
624 call this function before */
625 modest_msg_edit_window_disconnect_signals (MODEST_WINDOW (obj));
627 if (priv->draft_msg != NULL) {
628 TnyHeader *header = tny_msg_get_header (priv->draft_msg);
629 if (TNY_IS_HEADER (header)) {
630 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
631 modest_window_mgr_unregister_header (mgr, header);
633 g_object_unref (priv->draft_msg);
634 priv->draft_msg = NULL;
636 if (priv->outbox_msg != NULL) {
637 TnyHeader *header = tny_msg_get_header (priv->outbox_msg);
638 if (TNY_IS_HEADER (header)) {
639 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
640 modest_window_mgr_unregister_header (mgr, header);
642 g_object_unref (priv->outbox_msg);
643 priv->outbox_msg = NULL;
645 if (priv->msg_uid != NULL) {
646 g_free (priv->msg_uid);
647 priv->msg_uid = NULL;
650 /* This had to stay alive for as long as the combobox that used it: */
651 modest_pair_list_free (priv->from_field_protos);
653 G_OBJECT_CLASS(parent_class)->finalize (obj);
657 menubar_to_menu (GtkUIManager *ui_manager)
659 GtkWidget *main_menu;
663 /* Create new main menu */
664 main_menu = gtk_menu_new();
666 /* Get the menubar from the UI manager */
667 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
669 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
673 menu = GTK_WIDGET (iter->data);
674 gtk_widget_reparent(menu, main_menu);
676 iter = g_list_next (iter);
682 pixbuf_from_stream (TnyStream *stream, const gchar *mime_type)
684 GdkPixbufLoader *loader;
687 loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
692 tny_stream_reset (TNY_STREAM (stream));
693 while (!tny_stream_is_eos (TNY_STREAM (stream))) {
694 unsigned char read_buffer[128];
696 readed = tny_stream_read (TNY_STREAM (stream), (char *) read_buffer, 128);
697 if (!gdk_pixbuf_loader_write (loader, read_buffer, readed, NULL))
701 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
702 g_object_ref (pixbuf);
703 gdk_pixbuf_loader_close (loader, NULL);
704 g_object_unref (loader);
706 if (gdk_pixbuf_get_width (pixbuf) > IMAGE_MAX_WIDTH) {
707 GdkPixbuf *new_pixbuf;
709 new_height = (gdk_pixbuf_get_height (pixbuf) * IMAGE_MAX_WIDTH) /
710 gdk_pixbuf_get_width (pixbuf);
711 new_pixbuf = gdk_pixbuf_scale_simple (pixbuf, IMAGE_MAX_WIDTH, new_height, GDK_INTERP_BILINEAR);
712 g_object_unref (pixbuf);
720 replace_with_attachments (ModestMsgEditWindow *self, GList *attachments)
722 ModestMsgEditWindowPrivate *priv;
725 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
727 for (node = attachments; node != NULL; node = g_list_next (node)) {
728 TnyMimePart *part = (TnyMimePart *) node->data;
729 const gchar *cid = tny_mime_part_get_content_id (part);
730 const gchar *mime_type = tny_mime_part_get_content_type (part);
731 if ((cid != NULL)&&(mime_type != NULL)) {
732 TnyStream *stream = tny_mime_part_get_stream (part);
733 GdkPixbuf *pixbuf = pixbuf_from_stream (stream, mime_type);
734 g_object_unref (stream);
736 if (pixbuf != NULL) {
737 /* wp_text_buffer_replace_image (WP_TEXT_BUFFER (priv->text_buffer), cid, pixbuf); */
738 g_object_unref (pixbuf);
745 update_last_cid (ModestMsgEditWindow *self, GList *attachments)
748 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
750 for (node = attachments; node != NULL; node = g_list_next (node)) {
751 TnyMimePart *part = (TnyMimePart *) node->data;
752 const gchar *cid = tny_mime_part_get_content_id (part);
754 char *invalid = NULL;
755 gint int_cid = strtol (cid, &invalid, 10);
756 if ((invalid != NULL) && (*invalid == '\0') && (int_cid > priv->last_cid)) {
757 priv->last_cid = int_cid;
765 set_msg (ModestMsgEditWindow *self, TnyMsg *msg, gboolean preserve_is_rich)
768 const gchar *to, *cc, *bcc, *subject;
770 ModestMsgEditWindowPrivate *priv;
772 TnyHeaderFlags priority_flags;
773 TnyFolder *msg_folder;
774 gboolean is_html = FALSE;
776 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
777 g_return_if_fail (TNY_IS_MSG (msg));
779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
781 header = tny_msg_get_header (msg);
782 to = tny_header_get_to (header);
783 cc = tny_header_get_cc (header);
784 bcc = tny_header_get_bcc (header);
785 subject = tny_header_get_subject (header);
786 priority_flags = tny_header_get_flags (header) & TNY_HEADER_FLAG_PRIORITY;
789 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->to_field), to);
791 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->cc_field), cc);
792 gtk_widget_set_no_show_all (priv->cc_caption, FALSE);
793 gtk_widget_show (priv->cc_caption);
794 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_CC, NULL)) {
795 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
796 gtk_widget_hide (priv->cc_caption);
799 modest_recpt_editor_set_recipients (MODEST_RECPT_EDITOR (priv->bcc_field), bcc);
800 gtk_widget_set_no_show_all (priv->bcc_caption, FALSE);
801 gtk_widget_show (priv->bcc_caption);
802 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_BCC, NULL)) {
803 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
804 gtk_widget_hide (priv->bcc_caption);
807 gtk_entry_set_text (GTK_ENTRY(priv->subject_field), subject);
808 modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW(self),
811 update_window_title (self);
813 wp_text_buffer_reset_buffer (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
814 body = modest_tny_msg_get_body (msg, TRUE, &is_html);
816 if ((body == NULL)||(body[0] == '\0')) {
818 body = modest_text_utils_convert_to_html ("");
821 wp_text_buffer_load_document_begin (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
822 wp_text_buffer_load_document_write (WP_TEXT_BUFFER (priv->text_buffer),
825 wp_text_buffer_load_document_end (WP_TEXT_BUFFER (priv->text_buffer));
828 if (preserve_is_rich && !is_html) {
829 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
830 /* Get the default format required from configuration */
831 } else if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL)) {
832 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
835 /* Set the default focus depending on having already a To: field or not */
836 if ((!to)||(*to == '\0')) {
837 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
839 gtk_widget_grab_focus (priv->msg_body);
842 /* TODO: lower priority, select in the From: combo to the
843 value that comes from msg <- not sure, should it be
846 /* Add attachments to the view */
847 modest_attachments_view_set_message (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), msg);
848 priv->attachments = modest_attachments_view_get_attachments (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
849 if (priv->attachments == NULL) {
850 gtk_widget_hide (priv->attachments_caption);
852 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
853 gtk_widget_show_all (priv->attachments_caption);
854 replace_with_attachments (self, priv->attachments);
856 update_last_cid (self, priv->attachments);
858 DEBUG_BUFFER (WP_TEXT_BUFFER (priv->text_buffer));
860 gtk_text_buffer_get_start_iter (priv->text_buffer, &iter);
861 gtk_text_buffer_place_cursor (priv->text_buffer, &iter);
863 reset_modified (self);
865 update_dimmed (self);
866 text_buffer_can_undo (priv->text_buffer, FALSE, self);
867 text_buffer_can_redo (priv->text_buffer, FALSE, self);
870 g_free (priv->msg_uid);
871 priv->msg_uid = NULL;
874 /* we should set a reference to the incoming message if it is a draft */
875 msg_folder = tny_msg_get_folder (msg);
877 if (modest_tny_folder_is_local_folder (msg_folder)) {
878 TnyFolderType type = modest_tny_folder_get_local_or_mmc_folder_type (msg_folder);
879 if (type == TNY_FOLDER_TYPE_DRAFTS)
880 priv->draft_msg = g_object_ref(msg);
881 if (type == TNY_FOLDER_TYPE_OUTBOX)
882 priv->outbox_msg = g_object_ref(msg);
883 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
885 g_object_unref (msg_folder);
890 menu_tool_button_clicked_popup (GtkMenuToolButton *item,
893 GList *item_children, *node;
894 GtkWidget *bin_child;
896 bin_child = gtk_bin_get_child (GTK_BIN(item));
898 item_children = gtk_container_get_children (GTK_CONTAINER (bin_child));
900 for (node = item_children; node != NULL; node = g_list_next (node)) {
901 if (GTK_IS_TOGGLE_BUTTON (node->data)) {
902 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (node->data), TRUE);
905 g_list_free (item_children);
909 menu_tool_button_dont_expand (GtkMenuToolButton *item)
912 GList *item_children, *node;
914 box = gtk_bin_get_child (GTK_BIN (item));
915 gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
916 item_children = gtk_container_get_children (GTK_CONTAINER (box));
918 for (node = item_children; node != NULL; node = g_list_next (node)) {
919 gtk_box_set_child_packing (GTK_BOX (box), GTK_WIDGET (node->data), TRUE, TRUE, 0, GTK_PACK_START);
920 if (GTK_IS_TOGGLE_BUTTON (node->data))
921 gtk_button_set_alignment (GTK_BUTTON (node->data), 0.0, 0.5);
922 else if (GTK_IS_BUTTON (node->data))
923 gtk_button_set_alignment (GTK_BUTTON (node->data), 1.0, 0.5);
925 g_list_free (item_children);
930 modest_msg_edit_window_setup_toolbar (ModestMsgEditWindow *window)
932 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
933 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
934 GtkWidget *placeholder;
935 GtkWidget *tool_item;
940 GtkWidget *sizes_menu;
941 GtkWidget *fonts_menu;
942 GSList *radio_group = NULL;
947 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar");
948 hildon_window_add_toolbar (HILDON_WINDOW (window), GTK_TOOLBAR (parent_priv->toolbar));
950 /* should we hide the toolbar? */
951 if (!modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_SHOW_TOOLBAR, NULL))
952 gtk_widget_hide (parent_priv->toolbar);
954 /* Font color placeholder */
955 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontColor");
956 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
959 tool_item = GTK_WIDGET (gtk_tool_item_new ());
960 priv->font_color_button = hildon_color_button_new ();
961 GTK_WIDGET_UNSET_FLAGS (tool_item, GTK_CAN_FOCUS);
962 GTK_WIDGET_UNSET_FLAGS (priv->font_color_button, GTK_CAN_FOCUS);
963 gtk_container_add (GTK_CONTAINER (tool_item), priv->font_color_button);
964 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
965 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
966 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
967 g_signal_connect_swapped (G_OBJECT (priv->font_color_button), "notify::color", G_CALLBACK (modest_msg_edit_window_color_button_change), window);
969 /* Font size and face placeholder */
970 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FontAttributes");
971 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
973 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
974 priv->size_tool_button_label = gtk_label_new (NULL);
975 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[DEFAULT_FONT_SIZE]);
976 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>",
977 size_text,"</span>", NULL);
978 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
980 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->size_tool_button_label);
981 sizes_menu = gtk_menu_new ();
982 priv->size_items_group = NULL;
984 for (size_index = 0; size_index < WP_FONT_SIZE_COUNT; size_index++) {
985 GtkWidget *size_menu_item;
987 snprintf(size_text, sizeof(size_text), "%d", wp_font_size[size_index]);
988 size_menu_item = gtk_radio_menu_item_new_with_label (radio_group, size_text);
989 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (size_menu_item));
990 gtk_menu_shell_append (GTK_MENU_SHELL (sizes_menu), size_menu_item);
991 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (size_menu_item), (wp_font_size[size_index] == 12));
992 gtk_widget_show (size_menu_item);
994 priv->size_items_group = g_slist_prepend (priv->size_items_group, size_menu_item);
998 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
999 GtkWidget *item = (GtkWidget *) node->data;
1000 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_size_change),
1004 priv->size_items_group = g_slist_reverse (priv->size_items_group);
1005 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), sizes_menu);
1006 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1007 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1008 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1009 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1010 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1011 priv->font_size_toolitem = tool_item;
1014 tool_item = GTK_WIDGET (gtk_menu_tool_button_new (NULL, NULL));
1015 priv->font_tool_button_label = gtk_label_new (NULL);
1016 markup = g_strconcat ("<span font_family='", wp_get_font_name(DEFAULT_FONT), "'>Tt</span>", NULL);
1017 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1019 gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (tool_item), priv->font_tool_button_label);
1020 fonts_menu = gtk_menu_new ();
1021 priv->font_items_group = NULL;
1023 for (font_index = 0; font_index < wp_get_font_count (); font_index++) {
1024 GtkWidget *font_menu_item;
1025 GtkWidget *child_label;
1027 font_menu_item = gtk_radio_menu_item_new_with_label (radio_group, "");
1028 child_label = gtk_bin_get_child (GTK_BIN (font_menu_item));
1029 markup = g_strconcat ("<span font_family='", wp_get_font_name (font_index),"'>",
1030 wp_get_font_name (font_index), "</span>", NULL);
1031 gtk_label_set_markup (GTK_LABEL (child_label), markup);
1034 radio_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (font_menu_item));
1035 gtk_menu_shell_append (GTK_MENU_SHELL (fonts_menu), font_menu_item);
1036 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (font_menu_item), (font_index == DEFAULT_FONT));
1037 gtk_widget_show (font_menu_item);
1039 priv->font_items_group = g_slist_prepend (priv->font_items_group, font_menu_item);
1042 for (node = radio_group; node != NULL; node = g_slist_next (node)) {
1043 GtkWidget *item = (GtkWidget *) node->data;
1044 g_signal_connect (G_OBJECT (item), "toggled", G_CALLBACK (modest_msg_edit_window_font_change),
1047 priv->font_items_group = g_slist_reverse (priv->font_items_group);
1048 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), fonts_menu);
1049 g_signal_connect (G_OBJECT (tool_item), "clicked", G_CALLBACK (menu_tool_button_clicked_popup), NULL);
1050 gtk_toolbar_insert (GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM (tool_item), insert_index);
1051 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1052 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1053 menu_tool_button_dont_expand (GTK_MENU_TOOL_BUTTON (tool_item));
1054 priv->font_face_toolitem = tool_item;
1056 /* Set expand and homogeneous for remaining items */
1057 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
1058 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1059 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1060 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1061 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1062 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1063 tool_item = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1064 gtk_tool_item_set_expand (GTK_TOOL_ITEM (tool_item), TRUE);
1065 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (tool_item), TRUE);
1073 modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean preserve_is_rich)
1076 ModestWindowPrivate *parent_priv;
1077 ModestMsgEditWindowPrivate *priv;
1078 GtkActionGroup *action_group;
1079 GError *error = NULL;
1080 GdkPixbuf *window_icon = NULL;
1083 gboolean prefer_formatted;
1085 ModestPair *account_pair = NULL;
1087 g_return_val_if_fail (msg, NULL);
1088 g_return_val_if_fail (account_name, NULL);
1090 obj = g_object_new(MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
1092 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (obj);
1093 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
1095 parent_priv->ui_manager = gtk_ui_manager_new();
1096 action_group = gtk_action_group_new ("ModestMsgEditWindowActions");
1097 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
1099 /* Add common actions */
1100 gtk_action_group_add_actions (action_group,
1101 modest_msg_edit_action_entries,
1102 G_N_ELEMENTS (modest_msg_edit_action_entries),
1104 gtk_action_group_add_toggle_actions (action_group,
1105 modest_msg_edit_toggle_action_entries,
1106 G_N_ELEMENTS (modest_msg_edit_toggle_action_entries),
1108 gtk_action_group_add_radio_actions (action_group,
1109 modest_msg_edit_alignment_radio_action_entries,
1110 G_N_ELEMENTS (modest_msg_edit_alignment_radio_action_entries),
1112 G_CALLBACK (modest_ui_actions_on_change_justify),
1114 gtk_action_group_add_radio_actions (action_group,
1115 modest_msg_edit_zoom_action_entries,
1116 G_N_ELEMENTS (modest_msg_edit_zoom_action_entries),
1118 G_CALLBACK (modest_ui_actions_on_change_zoom),
1120 gtk_action_group_add_radio_actions (action_group,
1121 modest_msg_edit_priority_action_entries,
1122 G_N_ELEMENTS (modest_msg_edit_priority_action_entries),
1124 G_CALLBACK (modest_ui_actions_msg_edit_on_change_priority),
1126 gtk_action_group_add_radio_actions (action_group,
1127 modest_msg_edit_file_format_action_entries,
1128 G_N_ELEMENTS (modest_msg_edit_file_format_action_entries),
1129 modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_PREFER_FORMATTED_TEXT, NULL),
1130 G_CALLBACK (modest_ui_actions_msg_edit_on_change_file_format),
1132 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
1133 g_object_unref (action_group);
1135 /* Load the UI definition */
1136 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-edit-window-ui.xml",
1138 if (error != NULL) {
1139 g_warning ("Could not merge modest-msg-edit-window-ui.xml: %s", error->message);
1140 g_clear_error (&error);
1143 /* Add accelerators */
1144 gtk_window_add_accel_group (GTK_WINDOW (obj),
1145 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
1148 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
1149 hildon_window_set_menu (HILDON_WINDOW (obj), GTK_MENU (parent_priv->menubar));
1152 init_window (MODEST_MSG_EDIT_WINDOW(obj));
1154 restore_settings (MODEST_MSG_EDIT_WINDOW(obj));
1156 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
1158 modest_msg_edit_window_setup_toolbar (MODEST_MSG_EDIT_WINDOW (obj));
1159 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
1161 setup_insensitive_handlers (MODEST_MSG_EDIT_WINDOW (obj));
1163 account_pair = modest_pair_list_find_by_first_as_string (priv->from_field_protos, account_name);
1164 if (account_pair != NULL)
1165 modest_combo_box_set_active_id (MODEST_COMBO_BOX (priv->from_field), account_pair->first);
1167 set_msg (MODEST_MSG_EDIT_WINDOW (obj), msg, preserve_is_rich);
1169 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (obj));
1171 /* Set window icon */
1172 window_icon = modest_platform_get_icon (MODEST_APP_MSG_EDIT_ICON);
1174 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
1175 g_object_unref (window_icon);
1178 /* Dim at start clipboard actions */
1179 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
1180 gtk_action_set_sensitive (action, FALSE);
1181 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
1182 gtk_action_set_sensitive (action, FALSE);
1183 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
1184 gtk_action_set_sensitive (action, FALSE);
1186 /* Update select all */
1187 update_select_all_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1188 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu");
1189 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (edit_menu_activated), obj);
1190 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu");
1191 g_signal_connect (G_OBJECT (action), "activate", G_CALLBACK (view_menu_activated), obj);
1193 /* set initial state of cc and bcc */
1194 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewCcFieldMenu");
1195 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1196 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, NULL));
1197 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewBccFieldMenu");
1198 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action),
1199 modest_conf_get_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, NULL));
1201 /* Setup the file format */
1202 conf = modest_runtime_get_conf ();
1203 prefer_formatted = modest_conf_get_bool (conf, MODEST_CONF_PREFER_FORMATTED_TEXT, &error);
1205 g_clear_error (&error);
1206 file_format = MODEST_FILE_FORMAT_FORMATTED_TEXT;
1208 file_format = (prefer_formatted) ?
1209 MODEST_FILE_FORMAT_FORMATTED_TEXT :
1210 MODEST_FILE_FORMAT_PLAIN_TEXT;
1211 modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (obj), file_format);
1213 update_paste_dimming (MODEST_MSG_EDIT_WINDOW (obj));
1214 priv->update_caption_visibility = TRUE;
1216 reset_modified (MODEST_MSG_EDIT_WINDOW (obj));
1218 return (ModestWindow*) obj;
1222 get_formatted_data_cb (const gchar *buffer, gpointer user_data)
1224 GString **string_buffer = (GString **) user_data;
1226 *string_buffer = g_string_append (*string_buffer, buffer);
1232 * @result: A new string which should be freed with g_free().
1235 get_formatted_data (ModestMsgEditWindow *edit_window)
1237 ModestMsgEditWindowPrivate *priv;
1238 GString *string_buffer = g_string_new ("");
1240 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1242 wp_text_buffer_save_document (WP_TEXT_BUFFER(priv->text_buffer), get_formatted_data_cb, &string_buffer);
1244 return g_string_free (string_buffer, FALSE);
1249 modest_msg_edit_window_get_msg_data (ModestMsgEditWindow *edit_window)
1252 const gchar *account_name;
1253 ModestMsgEditWindowPrivate *priv;
1255 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window), NULL);
1257 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (edit_window);
1259 account_name = modest_combo_box_get_active_id (MODEST_COMBO_BOX (priv->from_field));
1260 g_return_val_if_fail (account_name, NULL);
1263 /* don't free these (except from) */
1264 data = g_slice_new0 (MsgData);
1265 data->from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1267 data->account_name = g_strdup (account_name);
1268 data->to = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->to_field)));
1269 data->cc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->cc_field)));
1270 data->bcc = g_strdup (modest_recpt_editor_get_recipients (MODEST_RECPT_EDITOR (priv->bcc_field)));
1271 data->subject = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->subject_field)));
1272 if (priv->draft_msg) {
1273 data->draft_msg = g_object_ref (priv->draft_msg);
1274 } else if (priv->outbox_msg) {
1275 data->draft_msg = g_object_ref (priv->outbox_msg);
1277 data->draft_msg = NULL;
1280 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
1282 gtk_text_buffer_get_bounds (buf, &b, &e);
1283 data->plain_body = modest_text_utils_text_buffer_get_text (priv->text_buffer); /* returns a copy */
1285 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer)))
1286 data->html_body = get_formatted_data (edit_window); /* returns a copy. */
1288 data->html_body = NULL;
1290 /* deep-copy the data */
1291 GList *cursor = priv->attachments;
1292 data->attachments = NULL;
1294 if (!(TNY_IS_MIME_PART(cursor->data))) {
1295 g_warning ("strange data in attachment list");
1296 cursor = g_list_next (cursor);
1299 data->attachments = g_list_append (data->attachments,
1300 g_object_ref (cursor->data));
1301 cursor = g_list_next (cursor);
1304 data->priority_flags = priv->priority_flags;
1311 unref_gobject (GObject *obj, gpointer data)
1313 if (!G_IS_OBJECT(obj))
1315 g_object_unref (obj);
1319 modest_msg_edit_window_free_msg_data (ModestMsgEditWindow *edit_window,
1322 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (edit_window));
1330 g_free (data->subject);
1331 g_free (data->plain_body);
1332 g_free (data->html_body);
1333 g_free (data->account_name);
1335 if (data->draft_msg != NULL) {
1336 g_object_unref (data->draft_msg);
1337 data->draft_msg = NULL;
1340 g_list_foreach (data->attachments, (GFunc)unref_gobject, NULL);
1341 g_list_free (data->attachments);
1343 g_slice_free (MsgData, data);
1347 modest_msg_edit_window_get_format (ModestMsgEditWindow *self)
1350 ModestMsgEditWindowPrivate *priv = NULL;
1351 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), MODEST_MSG_EDIT_FORMAT_HTML);
1353 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1355 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
1357 return MODEST_MSG_EDIT_FORMAT_HTML;
1359 return MODEST_MSG_EDIT_FORMAT_TEXT;
1363 modest_msg_edit_window_set_format (ModestMsgEditWindow *self,
1364 ModestMsgEditFormat format)
1366 ModestMsgEditWindowPrivate *priv;
1368 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1369 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1372 case MODEST_MSG_EDIT_FORMAT_HTML:
1373 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
1375 case MODEST_MSG_EDIT_FORMAT_TEXT:
1376 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
1379 g_return_if_reached ();
1383 ModestMsgEditFormatState *
1384 modest_msg_edit_window_get_format_state (ModestMsgEditWindow *self)
1386 ModestMsgEditFormatState *format_state = NULL;
1387 ModestMsgEditWindowPrivate *priv;
1388 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1390 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self), NULL);
1391 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1393 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, TRUE);
1395 format_state = g_new0 (ModestMsgEditFormatState, 1);
1396 format_state->bold = buffer_format->bold&0x1;
1397 format_state->italics = buffer_format->italic&0x1;
1398 format_state->bullet = buffer_format->bullet&0x1;
1399 format_state->color = buffer_format->color;
1400 format_state->font_size = buffer_format->font_size;
1401 format_state->font_family = wp_get_font_name (buffer_format->font);
1402 format_state->justification = buffer_format->justification;
1403 g_free (buffer_format);
1405 return format_state;
1410 modest_msg_edit_window_set_format_state (ModestMsgEditWindow *self,
1411 const ModestMsgEditFormatState *format_state)
1413 ModestMsgEditWindowPrivate *priv;
1414 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1415 WPTextBufferFormat *current_format = g_new0 (WPTextBufferFormat, 1);
1416 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
1417 g_return_if_fail (format_state != NULL);
1419 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (self);
1420 gtk_widget_grab_focus (priv->msg_body);
1421 buffer_format->bold = (format_state->bold != FALSE);
1422 buffer_format->italic = (format_state->italics != FALSE);
1423 buffer_format->color = format_state->color;
1424 buffer_format->font_size = format_state->font_size;
1425 buffer_format->font = wp_get_font_index (format_state->font_family, 0);
1426 buffer_format->justification = format_state->justification;
1427 buffer_format->bullet = format_state->bullet;
1429 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), current_format, TRUE);
1431 buffer_format->cs.bold = ((buffer_format->bold&0x1) != (current_format->bold&0x1));
1432 buffer_format->cs.italic = ((buffer_format->italic&0x1) != (current_format->italic&0x1));
1433 buffer_format->cs.color = !gdk_color_equal(&(buffer_format->color), &(current_format->color));
1434 buffer_format->cs.font_size = (buffer_format->font_size != current_format->font_size);
1435 buffer_format->cs.font = (buffer_format->font != current_format->font);
1436 buffer_format->cs.justification = (buffer_format->justification != current_format->justification);
1437 buffer_format->cs.bullet = (buffer_format->bullet != current_format->bullet);
1439 wp_text_buffer_freeze (WP_TEXT_BUFFER (priv->text_buffer));
1440 if (buffer_format->cs.bold) {
1441 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BOLD, (gpointer) (buffer_format->bold&0x1));
1443 if (buffer_format->cs.italic) {
1444 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_ITALIC, (gpointer) (buffer_format->italic&0x1));
1446 if (buffer_format->cs.color) {
1447 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) (&(buffer_format->color)));
1449 if (buffer_format->cs.font_size) {
1450 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE, (gpointer) (buffer_format->font_size));
1452 if (buffer_format->cs.justification) {
1453 switch (buffer_format->justification) {
1454 case GTK_JUSTIFY_LEFT:
1455 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_LEFT, (gpointer) TRUE);
1457 case GTK_JUSTIFY_CENTER:
1458 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_CENTER, (gpointer) TRUE);
1460 case GTK_JUSTIFY_RIGHT:
1461 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_RIGHT, (gpointer) TRUE);
1468 if (buffer_format->cs.font) {
1469 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT, (gpointer) (buffer_format->font));
1471 wp_text_buffer_thaw (WP_TEXT_BUFFER (priv->text_buffer));
1472 if (buffer_format->cs.bullet) {
1473 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_BULLET, (gpointer) ((buffer_format->bullet)?1:0));
1475 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), buffer_format); */
1477 g_free (current_format);
1482 text_buffer_refresh_attributes (WPTextBuffer *buffer, ModestMsgEditWindow *window)
1484 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1486 ModestWindowPrivate *parent_priv;
1487 ModestMsgEditWindowPrivate *priv;
1488 GtkWidget *new_size_menuitem;
1489 GtkWidget *new_font_menuitem;
1491 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1492 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1494 if (wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))) {
1495 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu");
1496 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1497 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1499 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatPlainTextMenu");
1500 if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
1501 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), TRUE);
1504 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1506 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
1507 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bold);
1509 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
1510 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->italic);
1512 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
1513 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), buffer_format->bullet);
1515 g_signal_handlers_block_by_func (G_OBJECT (priv->font_color_button),
1516 G_CALLBACK (modest_msg_edit_window_color_button_change),
1518 hildon_color_button_set_color (HILDON_COLOR_BUTTON (priv->font_color_button), & (buffer_format->color));
1519 g_signal_handlers_unblock_by_func (G_OBJECT (priv->font_color_button),
1520 G_CALLBACK (modest_msg_edit_window_color_button_change),
1523 new_size_menuitem = GTK_WIDGET ((g_slist_nth (priv->size_items_group,
1524 buffer_format->font_size))->data);
1525 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_size_menuitem))) {
1529 label = gtk_bin_get_child (GTK_BIN (new_size_menuitem));
1530 markup = g_strconcat ("<span font_family='Serif'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1531 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1533 g_signal_handlers_block_by_func (G_OBJECT (new_size_menuitem),
1534 G_CALLBACK (modest_msg_edit_window_size_change),
1536 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_size_menuitem), TRUE);
1537 g_signal_handlers_unblock_by_func (G_OBJECT (new_size_menuitem),
1538 G_CALLBACK (modest_msg_edit_window_size_change),
1542 new_font_menuitem = GTK_WIDGET ((g_slist_nth (priv->font_items_group,
1543 buffer_format->font))->data);
1544 if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (new_font_menuitem))) {
1548 label = gtk_bin_get_child (GTK_BIN (new_font_menuitem));
1549 markup = g_strconcat ("<span font_family='", gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
1550 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
1552 g_signal_handlers_block_by_func (G_OBJECT (new_font_menuitem),
1553 G_CALLBACK (modest_msg_edit_window_font_change),
1555 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_font_menuitem), TRUE);
1556 g_signal_handlers_unblock_by_func (G_OBJECT (new_font_menuitem),
1557 G_CALLBACK (modest_msg_edit_window_font_change),
1561 g_free (buffer_format);
1567 modest_msg_edit_window_select_color (ModestMsgEditWindow *window)
1570 WPTextBufferFormat *buffer_format = g_new0 (WPTextBufferFormat, 1);
1571 ModestMsgEditWindowPrivate *priv;
1572 GtkWidget *dialog = NULL;
1574 const GdkColor *new_color = NULL;
1576 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1577 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), buffer_format, FALSE);
1579 #ifdef MODEST_HILDON_VERSION_0
1580 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1581 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog), &(buffer_format->color));
1583 dialog = hildon_color_chooser_new ();
1584 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog), &(buffer_format->color));
1585 #endif /*MODEST_HILDON_VERSION_0*/
1586 g_free (buffer_format);
1588 response = gtk_dialog_run (GTK_DIALOG (dialog));
1590 case GTK_RESPONSE_OK: {
1591 #ifdef MODEST_HILDON_VERSION_0
1592 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1595 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1597 #endif /*MODEST_HILDON_VERSION_0*/
1604 gtk_widget_destroy (dialog);
1606 if (new_color != NULL)
1607 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1612 modest_msg_edit_window_select_background_color (ModestMsgEditWindow *window)
1615 ModestMsgEditWindowPrivate *priv;
1616 GtkWidget *dialog = NULL;
1618 GdkColor *old_color = NULL;
1619 const GdkColor *new_color = NULL;
1621 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1622 old_color = (GdkColor*)wp_text_buffer_get_background_color (WP_TEXT_BUFFER (priv->text_buffer));
1624 #ifdef MODEST_HILDON_VERSION_0
1625 dialog = hildon_color_selector_new (GTK_WINDOW (window));
1626 hildon_color_selector_set_color (HILDON_COLOR_SELECTOR (dialog),(GdkColor*)old_color);
1628 dialog = hildon_color_chooser_new ();
1629 hildon_color_chooser_set_color (HILDON_COLOR_CHOOSER (dialog),(GdkColor*)old_color);
1630 #endif /*MODEST_HILDON_VERSION_9*/
1632 response = gtk_dialog_run (GTK_DIALOG (dialog));
1634 case GTK_RESPONSE_OK: {
1635 #ifdef MODEST_HILDON_VERSION_0
1636 new_color = hildon_color_selector_get_color (HILDON_COLOR_SELECTOR (dialog));
1639 hildon_color_chooser_get_color (HILDON_COLOR_CHOOSER(dialog), &col);
1641 #endif /*MODEST_HILDON_VERSION_0*/
1647 gtk_widget_destroy (dialog);
1649 if (new_color != NULL)
1650 wp_text_buffer_set_background_color (WP_TEXT_BUFFER (priv->text_buffer), new_color);
1654 static TnyStream* create_stream_for_uri (const gchar* uri)
1659 TnyStream *result = NULL;
1661 GnomeVFSHandle *handle = NULL;
1662 GnomeVFSResult test = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1663 if (test == GNOME_VFS_OK) {
1664 /* Create the tinymail stream: */
1665 /* Presumably tinymai will call gnome_vfs_close (handle) later. */
1666 result = TNY_STREAM (tny_vfs_stream_new (handle));
1673 modest_msg_edit_window_insert_image (ModestMsgEditWindow *window)
1676 ModestMsgEditWindowPrivate *priv;
1677 GtkWidget *dialog = NULL;
1679 GSList *uris = NULL;
1680 GSList *uri_node = NULL;
1682 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1684 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1685 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ia_select_inline_image_title"));
1686 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1688 modest_maemo_utils_setup_images_filechooser (GTK_FILE_CHOOSER (dialog));
1690 response = gtk_dialog_run (GTK_DIALOG (dialog));
1692 case GTK_RESPONSE_OK:
1693 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1698 gtk_widget_destroy (dialog);
1700 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1702 GnomeVFSHandle *handle = NULL;
1703 GnomeVFSResult result;
1704 GtkTextIter position;
1705 GtkTextMark *insert_mark;
1707 uri = (const gchar *) uri_node->data;
1708 result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1709 if (result == GNOME_VFS_OK) {
1711 GnomeVFSFileInfo info;
1712 gchar *filename, *basename, *escaped_filename;
1713 TnyMimePart *mime_part;
1715 const gchar *mime_type = NULL;
1716 GnomeVFSURI *vfs_uri;
1718 vfs_uri = gnome_vfs_uri_new (uri);
1720 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1721 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1722 g_free (escaped_filename);
1723 gnome_vfs_uri_unref (vfs_uri);
1725 if (gnome_vfs_get_file_info (uri, &info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE
1726 | GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1728 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1730 mime_part = tny_platform_factory_new_mime_part
1731 (modest_runtime_get_platform_factory ());
1733 TnyStream *stream = create_stream_for_uri (uri);
1734 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1736 content_id = g_strdup_printf ("%d", priv->last_cid);
1737 tny_mime_part_set_content_id (mime_part, content_id);
1738 g_free (content_id);
1741 basename = g_path_get_basename (filename);
1742 tny_mime_part_set_filename (mime_part, basename);
1745 pixbuf = pixbuf_from_stream (stream, mime_type);
1747 if (pixbuf != NULL) {
1748 insert_mark = gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (priv->text_buffer));
1749 gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (priv->text_buffer), &position, insert_mark);
1750 wp_text_buffer_insert_image (WP_TEXT_BUFFER (priv->text_buffer), &position, g_strdup (tny_mime_part_get_content_id (mime_part)), pixbuf);
1753 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1754 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1756 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1757 gtk_widget_show_all (priv->attachments_caption);
1758 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1768 modest_msg_edit_window_offer_attach_file (ModestMsgEditWindow *window)
1771 ModestMsgEditWindowPrivate *priv;
1772 GtkWidget *dialog = NULL;
1774 GSList *uris = NULL;
1777 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1779 dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_OPEN);
1780 gtk_window_set_title (GTK_WINDOW (dialog), _("mcen_ti_select_attachment_title"));
1781 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
1783 response = gtk_dialog_run (GTK_DIALOG (dialog));
1785 case GTK_RESPONSE_OK:
1786 uris = gtk_file_chooser_get_uris (GTK_FILE_CHOOSER (dialog));
1791 gtk_widget_destroy (dialog);
1793 for (uri_node = uris; uri_node != NULL; uri_node = g_slist_next (uri_node)) {
1794 const gchar *uri = (const gchar *) uri_node->data;
1795 modest_msg_edit_window_attach_file_one (window, uri);
1797 g_slist_foreach (uris, (GFunc) g_free, NULL);
1798 g_slist_free (uris);
1802 modest_msg_edit_window_attach_file_one (
1803 ModestMsgEditWindow *window,
1806 g_return_if_fail (window);
1807 g_return_if_fail (uri);
1809 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1812 GnomeVFSHandle *handle = NULL;
1813 GnomeVFSResult result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
1814 if (result == GNOME_VFS_OK) {
1815 TnyMimePart *mime_part;
1817 const gchar *mime_type = NULL;
1819 gchar *escaped_filename;
1822 GnomeVFSFileInfo info;
1823 GnomeVFSURI *vfs_uri;
1825 vfs_uri = gnome_vfs_uri_new (uri);
1828 escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
1829 filename = gnome_vfs_unescape_string_for_display (escaped_filename);
1830 g_free (escaped_filename);
1831 gnome_vfs_uri_unref (vfs_uri);
1833 if (gnome_vfs_get_file_info (uri,
1835 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
1836 GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE)
1838 mime_type = gnome_vfs_file_info_get_mime_type (&info);
1839 mime_part = tny_platform_factory_new_mime_part
1840 (modest_runtime_get_platform_factory ());
1841 stream = TNY_STREAM (tny_vfs_stream_new (handle));
1843 tny_mime_part_construct_from_stream (mime_part, stream, mime_type);
1845 content_id = g_strdup_printf ("%d", priv->last_cid);
1846 tny_mime_part_set_content_id (mime_part, content_id);
1847 g_free (content_id);
1850 basename = g_path_get_basename (filename);
1851 tny_mime_part_set_filename (mime_part, basename);
1854 priv->attachments = g_list_prepend (priv->attachments, mime_part);
1855 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1857 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
1858 gtk_widget_show_all (priv->attachments_caption);
1859 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1865 modest_msg_edit_window_remove_attachments (ModestMsgEditWindow *window,
1868 ModestMsgEditWindowPrivate *priv;
1869 gboolean clean_list = FALSE;
1871 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1872 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1874 if (att_list == NULL) {
1875 att_list = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
1879 if (att_list == NULL) {
1880 hildon_banner_show_information (NULL, NULL, _("TODO: no attachments selected to remove"));
1882 GtkWidget *confirmation_dialog = NULL;
1883 gboolean dialog_response;
1885 gchar *message = NULL;
1886 const gchar *filename = NULL;
1888 if (att_list->next == NULL) {
1889 filename = tny_mime_part_get_filename (TNY_MIME_PART (att_list->data));
1893 message = g_strdup_printf (ngettext("emev_nc_delete_attachment", "emev_nc_delete_attachments",
1894 att_list->next == NULL), filename);
1895 confirmation_dialog = hildon_note_new_confirmation (GTK_WINDOW (window), message);
1897 dialog_response = (gtk_dialog_run (GTK_DIALOG (confirmation_dialog))==GTK_RESPONSE_OK);
1898 gtk_widget_destroy (confirmation_dialog);
1899 if (!dialog_response) {
1901 g_list_free (att_list);
1904 hildon_banner_show_information (NULL, NULL, _("mcen_ib_removing_attachment"));
1906 for (node = att_list; node != NULL; node = g_list_next (node)) {
1907 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1908 const gchar *att_id;
1909 priv->attachments = g_list_remove (priv->attachments, mime_part);
1911 modest_attachments_view_remove_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view),
1913 if (priv->attachments == NULL)
1914 gtk_widget_hide (priv->attachments_caption);
1915 att_id = tny_mime_part_get_content_id (mime_part);
1917 text_buffer_delete_images_by_id (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body)),
1919 g_object_unref (mime_part);
1920 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
1925 g_list_free (att_list);
1929 modest_msg_edit_window_color_button_change (ModestMsgEditWindow *window,
1932 ModestMsgEditWindowPrivate *priv;
1933 GdkColor *new_color;
1934 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1936 #ifdef MODEST_HAVE_HILDON0_WIDGETS
1937 new_color = hildon_color_button_get_color (HILDON_COLOR_BUTTON (priv->font_color_button));
1940 hildon_color_button_get_color (HILDON_COLOR_BUTTON(priv->font_color_button), &col);
1942 #endif /*#ifdef MODEST_HAVE_HILDON0_WIDGETS*/
1944 wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FORECOLOR, (gpointer) new_color);
1946 gtk_window_set_focus (GTK_WINDOW (window), priv->msg_body);
1951 modest_msg_edit_window_size_change (GtkCheckMenuItem *menu_item,
1954 ModestMsgEditWindowPrivate *priv;
1955 gint new_size_index;
1956 ModestMsgEditWindow *window;
1959 window = MODEST_MSG_EDIT_WINDOW (userdata);
1960 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
1961 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
1963 if (gtk_check_menu_item_get_active (menu_item)) {
1965 WPTextBufferFormat format;
1967 memset (&format, 0, sizeof (format));
1968 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &format, FALSE);
1970 label = gtk_bin_get_child (GTK_BIN (menu_item));
1972 new_size_index = atoi (gtk_label_get_text (GTK_LABEL (label)));
1973 format.cs.font_size = TRUE;
1974 format.cs.text_position = TRUE;
1975 format.cs.font = TRUE;
1976 format.font_size = wp_get_font_size_index (new_size_index, DEFAULT_FONT_SIZE);
1977 /* wp_text_buffer_set_format (WP_TEXT_BUFFER (priv->text_buffer), &format); */
1979 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT_SIZE,
1980 (gpointer) wp_get_font_size_index (new_size_index, 12)))
1981 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
1983 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
1984 markup = g_strconcat ("<span font_family='", DEFAULT_SIZE_BUTTON_FONT_FAMILY, "'>", gtk_label_get_text (GTK_LABEL (label)), "</span>", NULL);
1985 gtk_label_set_markup (GTK_LABEL (priv->size_tool_button_label), markup);
1991 modest_msg_edit_window_font_change (GtkCheckMenuItem *menu_item,
1994 ModestMsgEditWindowPrivate *priv;
1995 gint new_font_index;
1996 ModestMsgEditWindow *window;
1999 window = MODEST_MSG_EDIT_WINDOW (userdata);
2000 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2001 gtk_widget_grab_focus (GTK_WIDGET (priv->msg_body));
2003 if (gtk_check_menu_item_get_active (menu_item)) {
2006 label = gtk_bin_get_child (GTK_BIN (menu_item));
2008 new_font_index = wp_get_font_index (gtk_label_get_text (GTK_LABEL (label)), DEFAULT_FONT);
2010 if (!wp_text_buffer_set_attribute (WP_TEXT_BUFFER (priv->text_buffer), WPT_FONT,
2011 (gpointer) new_font_index))
2012 wp_text_view_reset_and_show_im (WP_TEXT_VIEW (priv->msg_body));
2014 text_buffer_refresh_attributes (WP_TEXT_BUFFER (priv->text_buffer), MODEST_MSG_EDIT_WINDOW (window));
2015 markup = g_strconcat ("<span font_family='",gtk_label_get_text (GTK_LABEL (label)),"'>Tt</span>", NULL);
2016 gtk_label_set_markup (GTK_LABEL (priv->font_tool_button_label), markup);
2022 modest_msg_edit_window_set_zoom (ModestWindow *window,
2025 ModestMsgEditWindowPrivate *priv;
2026 ModestWindowPrivate *parent_priv;
2027 GtkRadioAction *zoom_radio_action;
2029 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2031 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2032 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2033 priv->zoom_level = zoom;
2034 wp_text_buffer_set_font_scaling_factor (WP_TEXT_BUFFER (priv->text_buffer), zoom*DEFAULT_FONT_SCALE);
2036 /* Zoom level menu options should be updated with the current zoom level */
2037 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2038 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2039 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2040 #ifdef MODEST_HAVE_HILDON0_WIDGETS
2041 /* FIXME: Not availible before Gtk 2.10 */
2043 gtk_radio_action_set_current_value (zoom_radio_action, (gint) (zoom*100.0+0.1));
2048 modest_msg_edit_window_get_zoom (ModestWindow *window)
2050 ModestMsgEditWindowPrivate *priv;
2052 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), 1.0);
2054 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2055 return priv->zoom_level;
2059 zoom_allowed (ModestMsgEditWindow *window)
2063 focus = gtk_window_get_focus (GTK_WINDOW (window));
2064 return (focus != NULL && WP_IS_TEXT_VIEW (focus));
2068 modest_msg_edit_window_zoom_plus (ModestWindow *window)
2070 ModestWindowPrivate *parent_priv;
2071 GtkRadioAction *zoom_radio_action;
2072 GSList *group, *node;
2074 /* First we check if the text view is focused. If not, zooming is not allowed */
2075 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2076 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2080 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2081 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2082 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2084 group = gtk_radio_action_get_group (zoom_radio_action);
2086 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
2087 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
2091 for (node = group; node != NULL; node = g_slist_next (node)) {
2092 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
2093 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
2101 modest_msg_edit_window_zoom_minus (ModestWindow *window)
2103 ModestWindowPrivate *parent_priv;
2104 GtkRadioAction *zoom_radio_action;
2105 GSList *group, *node;
2107 /* First we check if the text view is focused. If not, zooming is not allowed */
2108 if (!zoom_allowed (MODEST_MSG_EDIT_WINDOW (window))) {
2109 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_cannot_zoom_here"));
2113 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2114 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
2115 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
2117 group = gtk_radio_action_get_group (zoom_radio_action);
2119 for (node = group; node != NULL; node = g_slist_next (node)) {
2120 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
2121 if (node->next != NULL) {
2122 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
2125 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
2133 modest_msg_edit_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
2135 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
2136 ModestWindowPrivate *parent_priv;
2137 ModestWindowMgr *mgr;
2138 gboolean is_fullscreen;
2139 GtkAction *fs_toggle_action;
2142 mgr = modest_runtime_get_window_mgr ();
2143 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
2145 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
2147 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2148 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
2149 if (is_fullscreen != active)
2150 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
2158 modest_msg_edit_window_toggle_fullscreen (ModestMsgEditWindow *window)
2160 ModestWindowPrivate *parent_priv;
2161 GtkAction *fs_toggle_action;
2164 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2166 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
2167 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action));
2168 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), !active);
2172 modest_msg_edit_window_show_cc (ModestMsgEditWindow *window,
2175 ModestMsgEditWindowPrivate *priv = NULL;
2176 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2178 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2179 if (!priv->update_caption_visibility)
2182 gtk_widget_set_no_show_all (priv->cc_caption, TRUE);
2184 gtk_widget_show (priv->cc_caption);
2186 gtk_widget_hide (priv->cc_caption);
2188 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_CC, show, NULL);
2192 modest_msg_edit_window_show_bcc (ModestMsgEditWindow *window,
2195 ModestMsgEditWindowPrivate *priv = NULL;
2196 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2198 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2199 if (!priv->update_caption_visibility)
2202 gtk_widget_set_no_show_all (priv->bcc_caption, TRUE);
2204 gtk_widget_show (priv->bcc_caption);
2206 gtk_widget_hide (priv->bcc_caption);
2208 modest_conf_set_bool(modest_runtime_get_conf(), MODEST_CONF_SHOW_BCC, show, NULL);
2212 modest_msg_edit_window_open_addressbook (ModestMsgEditWindow *window,
2213 ModestRecptEditor *editor)
2215 ModestMsgEditWindowPrivate *priv;
2217 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2218 g_return_if_fail ((editor == NULL) || (MODEST_IS_RECPT_EDITOR (editor)));
2219 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2221 if (editor == NULL) {
2222 GtkWidget *view_focus;
2223 view_focus = gtk_window_get_focus (GTK_WINDOW (window));
2225 /* This code should be kept in sync with ModestRecptEditor. The
2226 textview inside the recpt editor is the one that really gets the
2227 focus. As it's inside a scrolled window, and this one inside the
2228 hbox recpt editor inherits from, we'll need to go up in the
2229 hierarchy to know if the text view is part of the recpt editor
2230 or if it's a different text entry */
2232 if (gtk_widget_get_parent (view_focus)) {
2233 GtkWidget *first_parent;
2235 first_parent = gtk_widget_get_parent (view_focus);
2236 if (gtk_widget_get_parent (first_parent) &&
2237 MODEST_IS_RECPT_EDITOR (gtk_widget_get_parent (first_parent))) {
2238 editor = MODEST_RECPT_EDITOR (gtk_widget_get_parent (first_parent));
2243 editor = MODEST_RECPT_EDITOR (priv->to_field);
2247 modest_address_book_select_addresses (editor);
2252 modest_msg_edit_window_select_contacts (ModestMsgEditWindow *window)
2254 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2256 modest_msg_edit_window_open_addressbook (window, NULL);
2260 modest_msg_edit_window_show_toolbar (ModestWindow *self,
2261 gboolean show_toolbar)
2263 ModestWindowPrivate *parent_priv;
2265 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (self));
2266 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
2268 /* FIXME: we can not just use the code of
2269 modest_msg_edit_window_setup_toolbar because it has a
2270 mixture of both initialization and creation code. */
2273 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
2275 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
2279 modest_msg_edit_window_set_priority_flags (ModestMsgEditWindow *window,
2280 TnyHeaderFlags priority_flags)
2282 ModestMsgEditWindowPrivate *priv;
2283 ModestWindowPrivate *parent_priv;
2285 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2287 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2288 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2289 priority_flags = priority_flags & (TNY_HEADER_FLAG_PRIORITY);
2291 if (priv->priority_flags != priority_flags) {
2292 GtkAction *priority_action = NULL;
2294 priv->priority_flags = priority_flags;
2296 switch (priority_flags) {
2297 case TNY_HEADER_FLAG_HIGH_PRIORITY:
2298 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_high", GTK_ICON_SIZE_MENU);
2299 gtk_widget_show (priv->priority_icon);
2300 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2301 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityHighMenu");
2303 case TNY_HEADER_FLAG_LOW_PRIORITY:
2304 gtk_image_set_from_icon_name (GTK_IMAGE (priv->priority_icon), "qgn_list_messaging_low", GTK_ICON_SIZE_MENU);
2305 gtk_widget_show (priv->priority_icon);
2306 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2307 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityLowMenu");
2310 gtk_widget_hide (priv->priority_icon);
2311 priority_action = gtk_ui_manager_get_action (parent_priv->ui_manager,
2312 "/MenuBar/ToolsMenu/MessagePriorityMenu/MessagePriorityNormalMenu");
2315 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (priority_action), TRUE);
2316 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2321 modest_msg_edit_window_set_file_format (ModestMsgEditWindow *window,
2324 ModestMsgEditWindowPrivate *priv;
2325 ModestWindowPrivate *parent_priv;
2326 gint current_format;
2328 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2330 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2331 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2333 current_format = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer))
2334 ? MODEST_FILE_FORMAT_FORMATTED_TEXT : MODEST_FILE_FORMAT_PLAIN_TEXT;
2336 if (current_format != file_format) {
2337 switch (file_format) {
2338 case MODEST_FILE_FORMAT_FORMATTED_TEXT:
2339 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), TRUE);
2341 case MODEST_FILE_FORMAT_PLAIN_TEXT:
2345 dialog = hildon_note_new_confirmation (NULL, _("emev_nc_formatting_lost"));
2346 response = gtk_dialog_run (GTK_DIALOG (dialog));
2347 gtk_widget_destroy (dialog);
2348 if (response == GTK_RESPONSE_OK) {
2349 wp_text_buffer_enable_rich_text (WP_TEXT_BUFFER (priv->text_buffer), FALSE);
2351 GtkToggleAction *action = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/FileFormatMenu/FileFormatFormattedTextMenu"));
2352 modest_maemo_toggle_action_set_active_block_notify (action, TRUE);
2357 update_dimmed (window);
2362 modest_msg_edit_window_select_font (ModestMsgEditWindow *window)
2365 ModestMsgEditWindowPrivate *priv;
2366 WPTextBufferFormat oldfmt, fmt;
2367 gint old_position = 0;
2371 GdkColor *color = NULL;
2372 gboolean bold, bold_set, italic, italic_set;
2373 gboolean underline, underline_set;
2374 gboolean strikethrough, strikethrough_set;
2375 gboolean position_set;
2376 gboolean font_size_set, font_set, color_set;
2379 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2380 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2382 dialog = hildon_font_selection_dialog_new (GTK_WINDOW (window), NULL);
2384 /* First we get the currently selected font information */
2385 wp_text_buffer_get_attributes (WP_TEXT_BUFFER (priv->text_buffer), &oldfmt, TRUE);
2386 g_object_set (G_OBJECT (dialog), "font-scaling", priv->zoom_level, NULL);
2388 switch (oldfmt.text_position) {
2389 case TEXT_POSITION_NORMAL:
2392 case TEXT_POSITION_SUPERSCRIPT:
2400 g_object_set (G_OBJECT (dialog),
2401 "bold", oldfmt.bold != FALSE,
2402 "bold-set", !oldfmt.cs.bold,
2403 "underline", oldfmt.underline != FALSE,
2404 "underline-set", !oldfmt.cs.underline,
2405 "italic", oldfmt.italic != FALSE,
2406 "italic-set", !oldfmt.cs.italic,
2407 "strikethrough", oldfmt.strikethrough != FALSE,
2408 "strikethrough-set", !oldfmt.cs.strikethrough,
2409 "color", &oldfmt.color,
2410 "color-set", !oldfmt.cs.color,
2411 "size", wp_font_size[oldfmt.font_size],
2412 "size-set", !oldfmt.cs.font_size,
2413 "position", old_position,
2414 "position-set", !oldfmt.cs.text_position,
2415 "family", wp_get_font_name (oldfmt.font),
2416 "family-set", !oldfmt.cs.font,
2419 gtk_widget_show_all (dialog);
2420 response = gtk_dialog_run (GTK_DIALOG (dialog));
2421 if (response == GTK_RESPONSE_OK) {
2423 g_object_get( dialog,
2425 "bold-set", &bold_set,
2426 "underline", &underline,
2427 "underline-set", &underline_set,
2429 "italic-set", &italic_set,
2430 "strikethrough", &strikethrough,
2431 "strikethrough-set", &strikethrough_set,
2433 "color-set", &color_set,
2435 "size-set", &font_size_set,
2436 "family", &font_name,
2437 "family-set", &font_set,
2438 "position", &position,
2439 "position-set", &position_set,
2444 if (response == GTK_RESPONSE_OK) {
2445 memset(&fmt, 0, sizeof(fmt));
2451 fmt.italic = italic;
2452 fmt.cs.italic = TRUE;
2454 if (underline_set) {
2455 fmt.underline = underline;
2456 fmt.cs.underline = TRUE;
2458 if (strikethrough_set) {
2459 fmt.strikethrough = strikethrough;
2460 fmt.cs.strikethrough = TRUE;
2465 ? TEXT_POSITION_NORMAL
2466 : ( ( position == 1 )
2467 ? TEXT_POSITION_SUPERSCRIPT
2468 : TEXT_POSITION_SUBSCRIPT );
2469 fmt.cs.text_position = TRUE;
2473 fmt.cs.color = TRUE;
2476 fmt.font = wp_get_font_index(font_name,
2481 if (font_size_set) {
2482 fmt.font_size = wp_get_font_size_index(
2483 font_size, DEFAULT_FONT_SIZE);
2484 fmt.cs.font_size = TRUE;
2486 wp_text_buffer_set_format(WP_TEXT_BUFFER(priv->text_buffer), &fmt);
2488 gtk_widget_destroy (dialog);
2490 gtk_widget_grab_focus(GTK_WIDGET(priv->msg_body));
2494 modest_msg_edit_window_undo (ModestMsgEditWindow *window)
2496 ModestMsgEditWindowPrivate *priv;
2498 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2499 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2501 wp_text_buffer_undo (WP_TEXT_BUFFER (priv->text_buffer));
2503 update_dimmed (window);
2508 modest_msg_edit_window_redo (ModestMsgEditWindow *window)
2510 ModestMsgEditWindowPrivate *priv;
2512 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2513 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2515 wp_text_buffer_redo (WP_TEXT_BUFFER (priv->text_buffer));
2517 update_dimmed (window);
2522 update_dimmed (ModestMsgEditWindow *window)
2524 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2525 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2529 gboolean editor_focused;
2531 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2532 editor_focused = gtk_widget_is_focus (priv->msg_body);
2534 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/SelectFontMenu");
2535 gtk_action_set_sensitive (action, rich_text && editor_focused);
2536 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/BulletedListMenu");
2537 gtk_action_set_sensitive (action, rich_text && editor_focused);
2538 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu");
2539 gtk_action_set_sensitive (action, rich_text && editor_focused);
2540 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentLeftMenu");
2541 gtk_action_set_sensitive (action, rich_text && editor_focused);
2542 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentCenterMenu");
2543 gtk_action_set_sensitive (action, rich_text && editor_focused);
2544 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/FormatMenu/AlignmentMenu/AlignmentRightMenu");
2545 gtk_action_set_sensitive (action, rich_text && editor_focused);
2546 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/InsertImageMenu");
2547 gtk_action_set_sensitive (action, rich_text && editor_focused);
2548 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2549 gtk_action_set_sensitive (action, rich_text && editor_focused);
2550 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2551 gtk_action_set_sensitive (action, rich_text && editor_focused);
2552 widget = priv->font_color_button;
2553 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2554 widget = priv->font_size_toolitem;
2555 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2556 widget = priv->font_face_toolitem;
2557 gtk_widget_set_sensitive (widget, rich_text && editor_focused);
2561 setup_insensitive_handlers (ModestMsgEditWindow *window)
2563 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2564 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2567 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2568 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (send_insensitive_press), window);
2569 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsBold");
2570 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2571 widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ActionsItalics");
2572 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2573 widget = priv->font_color_button;
2574 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2575 widget = priv->font_size_toolitem;
2576 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2577 widget = priv->font_face_toolitem;
2578 g_signal_connect (G_OBJECT (widget), "insensitive-press", G_CALLBACK (style_insensitive_press), window);
2583 text_buffer_can_undo (GtkTextBuffer *buffer, gboolean can_undo, ModestMsgEditWindow *window)
2585 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2588 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/UndoMenu");
2589 gtk_action_set_sensitive (action, can_undo);
2593 text_buffer_can_redo (GtkTextBuffer *buffer, gboolean can_redo, ModestMsgEditWindow *window)
2595 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2598 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/RedoMenu");
2599 gtk_action_set_sensitive (action, can_redo);
2603 text_buffer_delete_images_by_id (GtkTextBuffer *buffer, const gchar * image_id)
2606 GtkTextIter match_start, match_end;
2608 if (image_id == NULL)
2611 gtk_text_buffer_get_start_iter (buffer, &iter);
2613 while (gtk_text_iter_forward_search (&iter, "\xef\xbf\xbc", 0, &match_start, &match_end, NULL)) {
2614 GSList *tags = gtk_text_iter_get_tags (&match_start);
2616 for (node = tags; node != NULL; node = g_slist_next (node)) {
2617 GtkTextTag *tag = (GtkTextTag *) node->data;
2618 if (g_object_get_data (G_OBJECT (tag), "image-set") != NULL) {
2619 gchar *cur_image_id = g_object_get_data (G_OBJECT (tag), "image-index");
2620 if ((cur_image_id != NULL) && (strcmp (image_id, cur_image_id)==0)) {
2622 offset = gtk_text_iter_get_offset (&match_start);
2623 gtk_text_buffer_delete (buffer, &match_start, &match_end);
2624 gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
2628 gtk_text_iter_forward_char (&iter);
2633 msg_body_focus (GtkWidget *focus,
2634 GdkEventFocus *event,
2638 update_dimmed (MODEST_MSG_EDIT_WINDOW (userdata));
2643 recpt_field_changed (GtkTextBuffer *buffer,
2644 ModestMsgEditWindow *editor)
2646 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (editor);
2647 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2648 GtkTextBuffer *to_buffer, *cc_buffer, *bcc_buffer;
2649 gboolean dim = FALSE;
2652 to_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field));
2653 cc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field));
2654 bcc_buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field));
2656 dim = ((gtk_text_buffer_get_char_count (to_buffer) +
2657 gtk_text_buffer_get_char_count (cc_buffer) +
2658 gtk_text_buffer_get_char_count (bcc_buffer)) == 0);
2660 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarSend");
2661 gtk_action_set_sensitive (action, !dim);
2662 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EmailMenu/SendMenu");
2663 gtk_action_set_sensitive (action, !dim);
2667 send_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2669 hildon_banner_show_information (NULL, NULL, _("mcen_ib_add_recipients_first"));
2673 style_insensitive_press (GtkWidget *widget, ModestMsgEditWindow *editor)
2675 gboolean rich_text, editor_focused;
2677 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2678 rich_text = wp_text_buffer_is_rich_text (WP_TEXT_BUFFER (priv->text_buffer));
2679 editor_focused = gtk_widget_is_focus (priv->msg_body);
2682 hildon_banner_show_information (NULL, NULL, _("mcen_ib_item_unavailable_plaintext"));
2683 else if (!editor_focused)
2684 hildon_banner_show_information (NULL, NULL, _("mcen_ib_move_cursor_to_message"));
2688 reset_modified (ModestMsgEditWindow *editor)
2690 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2691 GtkTextBuffer *buffer;
2693 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2694 gtk_text_buffer_set_modified (buffer, FALSE);
2695 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2696 gtk_text_buffer_set_modified (buffer, FALSE);
2697 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2698 gtk_text_buffer_set_modified (buffer, FALSE);
2699 gtk_text_buffer_set_modified (priv->text_buffer, FALSE);
2703 modest_msg_edit_window_is_modified (ModestMsgEditWindow *editor)
2705 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (editor);
2706 GtkTextBuffer *buffer;
2708 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->to_field));
2709 if (gtk_text_buffer_get_modified (buffer))
2711 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->cc_field));
2712 if (gtk_text_buffer_get_modified (buffer))
2714 buffer = modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR(priv->bcc_field));
2715 if (gtk_text_buffer_get_modified (buffer))
2717 if (gtk_text_buffer_get_modified (priv->text_buffer))
2724 modest_msg_edit_window_check_names (ModestMsgEditWindow *window, gboolean add_to_addressbook)
2726 ModestMsgEditWindowPrivate *priv = NULL;
2728 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2729 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2731 /* check if there's no recipient added */
2732 if ((gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->to_field))) == 0) &&
2733 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->cc_field))) == 0) &&
2734 (gtk_text_buffer_get_char_count (modest_recpt_editor_get_buffer (MODEST_RECPT_EDITOR (priv->bcc_field))) == 0)) {
2735 /* no recipient contents, then select contacts */
2736 modest_msg_edit_window_open_addressbook (window, NULL);
2740 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->to_field), add_to_addressbook)) {
2741 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2744 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->cc_field), add_to_addressbook)) {
2745 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->cc_field));
2748 if (!modest_address_book_check_names (MODEST_RECPT_EDITOR (priv->bcc_field), add_to_addressbook)) {
2749 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->bcc_field));
2753 if (!modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->cc_field)) &&
2754 !modest_recpt_editor_has_focus (MODEST_RECPT_EDITOR (priv->bcc_field)))
2755 modest_recpt_editor_grab_focus (MODEST_RECPT_EDITOR (priv->to_field));
2762 modest_msg_edit_window_add_attachment_clicked (GtkButton *button,
2763 ModestMsgEditWindow *window)
2765 modest_msg_edit_window_offer_attach_file (window);
2769 modest_msg_edit_window_clipboard_owner_change (GtkClipboard *clipboard,
2771 ModestMsgEditWindow *window)
2773 ModestWindowPrivate *parent_priv;
2774 ModestMsgEditWindowPrivate *priv;
2776 GList *selected_attachments = NULL;
2777 gint n_att_selected = 0;
2779 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2780 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
2782 if (!GTK_WIDGET_VISIBLE (window))
2785 selected_attachments = modest_attachments_view_get_selection (MODEST_ATTACHMENTS_VIEW (priv->attachments_view));
2786 n_att_selected = g_list_length (selected_attachments);
2787 g_list_free (selected_attachments);
2789 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/AttachmentsMenu/RemoveAttachmentsMenu");
2790 gtk_action_set_sensitive (action, n_att_selected == 1);
2792 update_copy_cut_dimming (window);
2793 update_paste_dimming (window);
2797 update_window_title (ModestMsgEditWindow *window)
2799 ModestMsgEditWindowPrivate *priv = NULL;
2800 const gchar *subject;
2802 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2803 subject = gtk_entry_get_text (GTK_ENTRY (priv->subject_field));
2804 if (subject == NULL || subject[0] == '\0')
2805 subject = _("mail_va_new_email");
2807 gtk_window_set_title (GTK_WINDOW (window), subject);
2812 subject_field_changed (GtkEditable *editable,
2813 ModestMsgEditWindow *window)
2815 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2816 update_window_title (window);
2817 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
2821 subject_field_insert_text (GtkEditable *editable,
2823 gint new_text_length,
2825 ModestMsgEditWindow *window)
2827 GString *result = g_string_new ("");
2829 gint result_len = 0;
2831 for (current = new_text; current != NULL && *current != '\0'; current = g_utf8_next_char (current)) {
2832 gunichar c = g_utf8_get_char_validated (current, 8);
2833 /* Invalid unichar, stop */
2839 result = g_string_append_unichar (result, c);
2843 if (MIN (result_len, 1000) != g_utf8_strlen (new_text, 1000)) {
2844 g_signal_stop_emission_by_name (G_OBJECT (editable), "insert-text");
2846 g_signal_emit_by_name (editable, "insert-text",
2847 (gpointer) result->str, (gpointer) strlen (result->str),
2848 (gpointer) position, (gpointer) window);
2851 g_string_free (result, TRUE);
2855 message_is_empty (ModestMsgEditWindow *window)
2857 ModestMsgEditWindowPrivate *priv = NULL;
2859 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), FALSE);
2860 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2862 /** TODO: Add wpeditor API to tell us if there is any _visible_ text,
2863 * so we can ignore markup.
2865 GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->msg_body));
2868 count = gtk_text_buffer_get_char_count (buf);
2874 modest_msg_edit_window_toggle_find_toolbar (ModestMsgEditWindow *window,
2877 ModestMsgEditWindowPrivate *priv = NULL;
2879 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2880 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2882 gtk_widget_set_no_show_all (priv->find_toolbar, FALSE);
2885 gtk_widget_show_all (priv->find_toolbar);
2886 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
2888 gtk_widget_hide_all (priv->find_toolbar);
2889 gtk_widget_grab_focus (priv->msg_body);
2895 gtk_text_iter_forward_search_insensitive (const GtkTextIter *iter,
2897 GtkTextIter *match_start,
2898 GtkTextIter *match_end)
2900 GtkTextIter end_iter;
2901 gchar *str_casefold;
2904 gchar *range_casefold;
2907 gboolean result = FALSE;
2914 gtk_text_iter_forward_to_end (&end_iter);
2916 str_casefold = g_utf8_casefold (str, -1);
2917 str_chars_n = strlen (str);
2919 range_text = gtk_text_iter_get_visible_text (iter, &end_iter);
2920 range_casefold = g_utf8_casefold (range_text, -1);
2921 range_chars_n = strlen (range_casefold);
2923 if (range_chars_n < str_chars_n) {
2924 g_free (str_casefold);
2925 g_free (range_text);
2926 g_free (range_casefold);
2930 for (offset = 0; offset <= range_chars_n - str_chars_n; offset++) {
2931 gchar *range_subtext = g_strndup (range_casefold + offset, str_chars_n);
2932 if (!g_utf8_collate (range_subtext, str_casefold)) {
2933 gchar *found_text = g_strndup (range_text + offset, str_chars_n);
2935 gtk_text_iter_forward_search (iter, found_text, GTK_TEXT_SEARCH_VISIBLE_ONLY|GTK_TEXT_SEARCH_TEXT_ONLY,
2936 match_start, match_end, NULL);
2937 g_free (found_text);
2939 g_free (range_subtext);
2943 g_free (str_casefold);
2944 g_free (range_text);
2945 g_free (range_casefold);
2952 modest_msg_edit_window_find_toolbar_search (GtkWidget *widget,
2953 ModestMsgEditWindow *window)
2955 gchar *current_search = NULL;
2956 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
2958 GtkTextIter selection_start, selection_end;
2959 GtkTextIter match_start, match_end;
2960 gboolean continue_search = FALSE;
2962 if (message_is_empty (window)) {
2963 g_free (priv->last_search);
2964 priv->last_search = NULL;
2965 hildon_banner_show_information (GTK_WIDGET (window), NULL, _("mail_ib_nothing_to_find"));
2969 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
2970 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
2971 g_free (current_search);
2972 g_free (priv->last_search);
2973 priv->last_search = NULL;
2974 /* Information banner about empty search */
2975 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
2979 if ((priv->last_search != NULL)&&(!strcmp (current_search, priv->last_search))) {
2980 continue_search = TRUE;
2982 g_free (priv->last_search);
2983 priv->last_search = g_strdup (current_search);
2986 if (continue_search) {
2987 gtk_text_buffer_get_selection_bounds (priv->text_buffer, &selection_start, &selection_end);
2988 result = gtk_text_iter_forward_search_insensitive (&selection_end, current_search,
2989 &match_start, &match_end);
2991 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_search_complete"));
2993 GtkTextIter buffer_start;
2994 gtk_text_buffer_get_start_iter (priv->text_buffer, &buffer_start);
2995 result = gtk_text_iter_forward_search_insensitive (&buffer_start, current_search,
2996 &match_start, &match_end);
2998 hildon_banner_show_information (NULL, NULL, dgettext ("hildon-libs", "ckct_ib_find_no_matches"));
3001 /* Mark as selected the string found in search */
3003 gtk_text_buffer_select_range (priv->text_buffer, &match_start, &match_end);
3004 gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->msg_body), &match_start, 0.0, TRUE, 0.0, 0.0);
3006 g_free (priv->last_search);
3007 priv->last_search = NULL;
3009 g_free (current_search);
3013 modest_msg_edit_window_find_toolbar_close (GtkWidget *widget,
3014 ModestMsgEditWindow *window)
3016 GtkToggleAction *toggle;
3017 ModestWindowPrivate *parent_priv;
3018 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3020 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/FindInMessageMenu"));
3021 gtk_toggle_action_set_active (toggle, FALSE);
3026 update_copy_cut_dimming (ModestMsgEditWindow *window)
3028 ModestWindowPrivate *parent_priv = NULL;
3029 ModestMsgEditWindowPrivate *priv = NULL;
3030 GtkClipboard *clipboard = NULL;
3031 GtkAction *action = NULL;
3032 gboolean has_selection = FALSE;
3033 GtkWidget *focused = NULL;
3034 gchar *selection = NULL;
3036 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3037 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3038 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3039 focused = gtk_window_get_focus (GTK_WINDOW (window));
3041 has_selection = gtk_clipboard_wait_for_targets (clipboard, NULL, NULL);
3043 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CutMenu");
3044 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
3045 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/CopyMenu");
3046 gtk_action_set_sensitive (action, (has_selection) && (!MODEST_IS_ATTACHMENTS_VIEW (focused)));
3048 if (selection != NULL)
3053 update_paste_dimming (ModestMsgEditWindow *window)
3055 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3056 GtkAction *action = NULL;
3057 GtkClipboard *clipboard = NULL;
3058 ModestEmailClipboard *e_clipboard;
3062 focused = gtk_window_get_focus (GTK_WINDOW (window));
3064 e_clipboard = modest_runtime_get_email_clipboard ();
3065 if (!modest_email_clipboard_cleared (e_clipboard)) {
3068 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3069 active = gtk_clipboard_wait_is_text_available (clipboard);
3073 if (MODEST_IS_ATTACHMENTS_VIEW (focused))
3077 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/PasteMenu");
3078 gtk_action_set_sensitive (action, active);
3083 update_select_all_dimming (ModestMsgEditWindow *window)
3086 gboolean dimmed = FALSE;
3088 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3090 focused = gtk_window_get_focus (GTK_WINDOW (window));
3091 if (GTK_IS_ENTRY (focused)) {
3092 const gchar *current_text;
3093 current_text = gtk_entry_get_text (GTK_ENTRY (focused));
3094 dimmed = ((current_text == NULL) || (current_text[0] == '\0'));
3095 } else if (GTK_IS_TEXT_VIEW (focused)) {
3096 GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused));
3097 dimmed = (gtk_text_buffer_get_char_count (buffer) < 1);
3098 } else if (MODEST_IS_ATTACHMENTS_VIEW (focused)) {
3101 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/SelectAllMenu");
3102 gtk_action_set_sensitive (action, !dimmed);
3106 update_zoom_dimming (ModestMsgEditWindow *window)
3109 gboolean dimmed = FALSE;
3111 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
3113 focused = gtk_window_get_focus (GTK_WINDOW (window));
3114 dimmed = ! WP_IS_TEXT_VIEW (focused);
3115 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ZoomMenu");
3116 gtk_action_set_sensitive (action, !dimmed);
3120 edit_menu_activated (GtkAction *action,
3123 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3125 update_select_all_dimming (window);
3126 update_copy_cut_dimming (window);
3127 update_paste_dimming (window);
3130 view_menu_activated (GtkAction *action,
3133 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3135 update_zoom_dimming (window);
3139 modest_msg_edit_window_get_sent (ModestMsgEditWindow *window)
3141 ModestMsgEditWindowPrivate *priv;
3143 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3148 modest_msg_edit_window_set_sent (ModestMsgEditWindow *window,
3151 ModestMsgEditWindowPrivate *priv;
3153 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE(window);
3159 modest_msg_edit_window_set_draft (ModestMsgEditWindow *window,
3162 ModestMsgEditWindowPrivate *priv;
3163 TnyHeader *header = NULL;
3165 g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3166 g_return_if_fail ((draft == NULL)||(TNY_IS_MSG (draft)));
3168 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3169 ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3171 if (priv->draft_msg != NULL) {
3172 header = tny_msg_get_header (priv->draft_msg);
3173 if (TNY_IS_HEADER (header)) {
3174 modest_window_mgr_unregister_header (mgr, header);
3176 g_object_unref (priv->draft_msg);
3179 if (draft != NULL) {
3180 g_object_ref (draft);
3181 header = tny_msg_get_header (draft);
3182 if (TNY_IS_HEADER (header))
3183 modest_window_mgr_register_header (mgr, header);
3184 if (priv->msg_uid) {
3185 g_free (priv->msg_uid);
3186 priv->msg_uid = NULL;
3188 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
3191 priv->draft_msg = draft;
3195 text_buffer_apply_tag (GtkTextBuffer *buffer, GtkTextTag *tag,
3196 GtkTextIter *start, GtkTextIter *end,
3199 ModestMsgEditWindow *window = MODEST_MSG_EDIT_WINDOW (userdata);
3200 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (userdata);
3203 if (tag == NULL+13) return;
3204 g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
3205 if ((tag_name != NULL) && (g_str_has_prefix (tag_name, "image-tag-replace-"))) {
3206 replace_with_attachments (window, priv->attachments);
3211 modest_msg_edit_window_add_part (ModestMsgEditWindow *window,
3214 ModestMsgEditWindowPrivate *priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3216 g_return_if_fail (TNY_IS_MIME_PART (part));
3217 priv->attachments = g_list_prepend (priv->attachments, part);
3218 g_object_ref (part);
3219 modest_attachments_view_add_attachment (MODEST_ATTACHMENTS_VIEW (priv->attachments_view), part);
3220 gtk_widget_set_no_show_all (priv->attachments_caption, FALSE);
3221 gtk_widget_show_all (priv->attachments_caption);
3222 gtk_text_buffer_set_modified (priv->text_buffer, TRUE);
3226 modest_msg_edit_window_get_message_uid (ModestMsgEditWindow *window)
3228 ModestMsgEditWindowPrivate *priv;
3230 g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window), NULL);
3231 priv = MODEST_MSG_EDIT_WINDOW_GET_PRIVATE (window);
3233 return priv->msg_uid;