* update the en_GB.po file with the newest translations
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved. 
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29  
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
57
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
70
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
74
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
81
82 #include <gtkhtml/gtkhtml.h>
83
84 typedef struct _GetMsgAsyncHelper {     
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;     
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         GtkWidget *parent_window;
104 } ReplyForwardHelper;
105
106 typedef struct _MoveToHelper {
107         GtkTreeRowReference *reference;
108         GtkWidget *banner;
109 } MoveToHelper;
110
111 typedef struct _PasteAsAttachmentHelper {
112         ModestMsgEditWindow *window;
113         GtkWidget *banner;
114 } PasteAsAttachmentHelper;
115
116
117 /*
118  * The do_headers_action uses this kind of functions to perform some
119  * action to each member of a list of headers
120  */
121 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
122
123 static void     do_headers_action     (ModestWindow *win, 
124                                        HeadersFunc func,
125                                        gpointer user_data);
126
127 static void     open_msg_cb            (ModestMailOperation *mail_op, 
128                                         TnyHeader *header, 
129                                         TnyMsg *msg,
130                                         gpointer user_data);
131
132 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
133                                         TnyHeader *header, 
134                                         TnyMsg *msg,
135                                         gpointer user_data);
136
137 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
138
139 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
140                                         TnyFolder *folder, 
141                                         gpointer user_data);
142
143 static void     on_send_receive_finished (ModestMailOperation  *mail_op, 
144                                           gpointer user_data);
145
146 static gint header_list_count_uncached_msgs (TnyList *header_list);
147
148 static gboolean connect_to_get_msg (ModestWindow *win,
149                                     gint num_of_uncached_msgs,
150                                     TnyAccount *account);
151
152 static gboolean remote_folder_is_pop (const TnyFolderStore *folder);
153
154 static gboolean msgs_already_deleted_from_server ( TnyList *headers,
155                                                    const TnyFolderStore *src_folder);
156
157
158 /*
159  * This function checks whether a TnyFolderStore is a pop account
160  */
161 static gboolean
162 remote_folder_is_pop (const TnyFolderStore *folder)
163 {
164         const gchar *proto = NULL;
165         TnyAccount *account = NULL;
166
167         g_return_val_if_fail (TNY_IS_FOLDER_STORE(folder), FALSE);
168
169         if (TNY_IS_ACCOUNT (folder)) {
170                 account = TNY_ACCOUNT(folder);
171                 g_object_ref(account);
172         } else if (TNY_IS_FOLDER (folder)) {
173                 account = tny_folder_get_account(TNY_FOLDER(folder));
174         }
175
176         proto = tny_account_get_proto(account);
177         g_object_unref (account);
178
179         return proto &&
180           (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
181 }
182
183 /*
184  * This functions checks whether if a list of messages are already
185  * deleted from the server: that is, if the server is a POP account
186  * and all messages are already cached.
187  */
188 static gboolean
189 msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_folder)
190 {
191         g_return_val_if_fail (TNY_IS_FOLDER_STORE(src_folder), FALSE);
192         g_return_val_if_fail (TNY_IS_LIST(headers), FALSE);
193
194         gboolean src_is_pop = remote_folder_is_pop (src_folder);
195         gint uncached_msgs = header_list_count_uncached_msgs (headers);
196
197         return (src_is_pop && !uncached_msgs);
198 }
199
200
201 /* FIXME: this should be merged with the similar code in modest-account-view-window */
202 /* Show the account creation wizard dialog.
203  * returns: TRUE if an account was created. FALSE if the user cancelled.
204  */
205 gboolean
206 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
207 {
208         gboolean result = FALSE;        
209         GtkWindow *dialog, *wizard;
210         gint dialog_response;
211
212         /* Show the easy-setup wizard: */       
213         dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
214         if (dialog && MODEST_IS_EASYSETUP_WIZARD_DIALOG(dialog)) {
215                 /* old wizard is active already; 
216                  */
217                 gtk_window_present (GTK_WINDOW(dialog));
218                 return FALSE;
219         }
220         
221
222         /* there is no such wizard yet */       
223         wizard = GTK_WINDOW (modest_easysetup_wizard_dialog_new ());
224         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard);
225
226         /* always present a main window in the background 
227          * we do it here, so we cannot end up with two wizards (as this
228          * function might be called in modest_window_mgr_get_main_window as well */
229         if (!win) 
230                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
231                                                          TRUE);  /* create if not existent */
232         
233         /* make sure the mainwindow is visible */
234         gtk_widget_show_all (GTK_WIDGET(win));
235         gtk_window_present (GTK_WINDOW(win));
236         
237         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
238         gtk_widget_destroy (GTK_WIDGET (wizard));
239         if (gtk_events_pending ())
240                 gtk_main_iteration ();
241
242         if (dialog_response == GTK_RESPONSE_CANCEL) {
243                 result = FALSE;
244         } else {
245                 /* Check whether an account was created: */
246                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
247         }
248         
249         return result;
250 }
251
252
253 void   
254 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
255 {
256         GtkWidget *about;
257         const gchar *authors[] = {
258                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
259                 NULL
260         };
261         about = gtk_about_dialog_new ();
262         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
263         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
264         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
265                                         _("Copyright (c) 2006, Nokia Corporation\n"
266                                           "All rights reserved."));
267         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
268                                        _("a modest e-mail client\n\n"
269                                          "design and implementation: Dirk-Jan C. Binnema\n"
270                                          "contributions from the fine people at KC and Ig\n"
271                                          "uses the tinymail email framework written by Philip van Hoof"));
272         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
273         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
274         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
275         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
276         
277         gtk_dialog_run (GTK_DIALOG (about));
278         gtk_widget_destroy(about);
279 }
280
281 /*
282  * Gets the list of currently selected messages. If the win is the
283  * main window, then it returns a newly allocated list of the headers
284  * selected in the header view. If win is the msg view window, then
285  * the value returned is a list with just a single header.
286  *
287  * The caller of this funcion must free the list.
288  */
289 static TnyList *
290 get_selected_headers (ModestWindow *win)
291 {
292         if (MODEST_IS_MAIN_WINDOW(win)) {
293                 GtkWidget *header_view;         
294                 
295                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
296                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
297                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
298                 
299         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
300                 /* for MsgViewWindows, we simply return a list with one element */
301                 TnyHeader *header;
302                 TnyList *list = NULL;
303                 
304                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
305                 if (header != NULL) {
306                         list = tny_simple_list_new ();
307                         tny_list_prepend (list, G_OBJECT(header));
308                         g_object_unref (G_OBJECT(header));
309                 }
310
311                 return list;
312
313         } else
314                 return NULL;
315 }
316
317 static GtkTreeRowReference *
318 get_next_after_selected_headers (ModestHeaderView *header_view)
319 {
320         GtkTreeSelection *sel;
321         GList *selected_rows, *node;
322         GtkTreePath *path;
323         GtkTreeRowReference *result;
324         GtkTreeModel *model;
325
326         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
327         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
328         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
329
330         if (selected_rows == NULL)
331                 return NULL;
332
333         node = g_list_last (selected_rows);
334         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
335         gtk_tree_path_next (path);
336
337         result = gtk_tree_row_reference_new (model, path);
338
339         gtk_tree_path_free (path);
340         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
341         g_list_free (selected_rows);
342
343         return result;
344 }
345
346 static void
347 headers_action_mark_as_read (TnyHeader *header,
348                              ModestWindow *win,
349                              gpointer user_data)
350 {
351         TnyHeaderFlags flags;
352
353         g_return_if_fail (TNY_IS_HEADER(header));
354
355         flags = tny_header_get_flags (header);
356         if (flags & TNY_HEADER_FLAG_SEEN) return;
357         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
358 }
359
360 static void
361 headers_action_mark_as_unread (TnyHeader *header,
362                                ModestWindow *win,
363                                gpointer user_data)
364 {
365         TnyHeaderFlags flags;
366
367         g_return_if_fail (TNY_IS_HEADER(header));
368
369         flags = tny_header_get_flags (header);
370         if (flags & TNY_HEADER_FLAG_SEEN)  {
371                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
372         }
373 }
374
375 /** After deleing a message that is currently visible in a window, 
376  * show the next message from the list, or close the window if there are no more messages.
377  **/
378 void 
379 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
380 {
381         /* Close msg view window or select next */
382         if (modest_msg_view_window_last_message_selected (win) &&
383                 modest_msg_view_window_first_message_selected (win)) {
384                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
385         } else if (!modest_msg_view_window_select_next_message (win)) {
386                 gboolean ret_value;
387                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
388         }
389 }
390
391
392 void
393 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
394 {
395         TnyList *header_list = NULL;
396         TnyIterator *iter = NULL;
397         TnyHeader *header = NULL;
398         gchar *message = NULL;
399         gchar *desc = NULL;
400         gint response;
401         ModestWindowMgr *mgr;
402         GtkWidget *header_view = NULL;
403
404         g_return_if_fail (MODEST_IS_WINDOW(win));
405         
406         /* Check first if the header view has the focus */
407         if (MODEST_IS_MAIN_WINDOW (win)) {
408                 header_view = 
409                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
410                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
411                 if (!gtk_widget_is_focus (header_view))
412                         return;
413         }
414         
415         /* Get the headers, either from the header view (if win is the main window),
416          * or from the message view window: */
417         header_list = get_selected_headers (win);
418         if (!header_list) return;
419                         
420         /* Check if any of the headers are already opened, or in the process of being opened */
421         if (MODEST_IS_MAIN_WINDOW (win)) {
422                 gint opened_headers = 0;
423
424                 iter = tny_list_create_iterator (header_list);
425                 mgr = modest_runtime_get_window_mgr ();
426                 while (!tny_iterator_is_done (iter)) {
427                         header = TNY_HEADER (tny_iterator_get_current (iter));
428                         if (header) {
429                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
430                                         opened_headers++;
431                                 g_object_unref (header);
432                         }
433                         tny_iterator_next (iter);
434                 }
435                 g_object_unref (iter);
436
437                 if (opened_headers > 0) {
438                         gchar *msg;
439
440                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
441                                                opened_headers);
442
443                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
444                         
445                         g_free (msg);
446                         g_object_unref (header_list);
447                         return;
448                 }
449         }
450
451         /* Select message */
452         if (tny_list_get_length(header_list) == 1) {
453                 iter = tny_list_create_iterator (header_list);
454                 header = TNY_HEADER (tny_iterator_get_current (iter));
455                 if (header) {
456                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
457                         g_object_unref (header);
458                 }
459
460                 g_object_unref (iter);
461         }
462         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
463                                            tny_list_get_length(header_list)), desc);
464
465         /* Confirmation dialog */
466         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
467                                                             message);
468         
469
470         if (response == GTK_RESPONSE_OK) {      
471                 ModestWindow *main_window = NULL;
472                 ModestWindowMgr *mgr = NULL;
473                 GtkTreeModel *model = NULL;
474                 GtkTreeSelection *sel = NULL;
475                 GList *sel_list = NULL, *tmp = NULL;
476                 GtkTreeRowReference *next_row_reference = NULL;
477                 GtkTreeRowReference *prev_row_reference = NULL;
478                 GtkTreePath *next_path = NULL;
479                 GtkTreePath *prev_path = NULL;
480                 ModestMailOperation *mail_op = NULL;
481
482                 /* Find last selected row */                    
483                 if (MODEST_IS_MAIN_WINDOW (win)) {
484                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
485                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
486                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
487                         for (tmp=sel_list; tmp; tmp=tmp->next) {
488                                 if (tmp->next == NULL) {
489                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
490                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
491
492                                         gtk_tree_path_prev (prev_path);
493                                         gtk_tree_path_next (next_path);
494
495                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
496                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
497                                 }
498                         }
499                 }
500                 
501                 /* Disable window dimming management */
502                 modest_window_disable_dimming (MODEST_WINDOW(win));
503
504                 /* Remove each header. If it's a view window header_view == NULL */
505                 mail_op = modest_mail_operation_new ((GObject *) win);
506                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
507                                                  mail_op);
508                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
509                 g_object_unref (mail_op);
510                 
511                 /* Enable window dimming management */
512                 if (sel != NULL) {
513                         gtk_tree_selection_unselect_all (sel);
514                 }
515                 modest_window_enable_dimming (MODEST_WINDOW(win));
516                 
517                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
518                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
519                         
520                         /* Get main window */
521                         mgr = modest_runtime_get_window_mgr ();
522                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
523                 } else {                        
524                         /* Move cursor to next row */
525                         main_window = win; 
526
527                         /* Select next or previous row */
528                         if (gtk_tree_row_reference_valid (next_row_reference)) {
529 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
530                                 gtk_tree_selection_select_path (sel, next_path);
531                         }
532                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
533                                 gtk_tree_selection_select_path (sel, prev_path);
534                         }
535
536                         /* Free */
537                         if (next_row_reference != NULL) 
538                                 gtk_tree_row_reference_free (next_row_reference);
539                         if (next_path != NULL) 
540                                 gtk_tree_path_free (next_path);                         
541                         if (prev_row_reference != NULL) 
542                                 gtk_tree_row_reference_free (prev_row_reference);
543                         if (prev_path != NULL) 
544                                 gtk_tree_path_free (prev_path);                         
545                 }
546                 
547                 /* Update toolbar dimming state */
548                 if (main_window)
549                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
550
551                 /* Free */
552                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
553                 g_list_free (sel_list);
554         }
555
556         /* Free*/
557         g_free(message);
558         g_free(desc);
559         g_object_unref (header_list);
560 }
561
562
563
564
565 /* delete either message or folder, based on where we are */
566 void
567 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
568 {
569         g_return_if_fail (MODEST_IS_WINDOW(win));
570         
571         /* Check first if the header view has the focus */
572         if (MODEST_IS_MAIN_WINDOW (win)) {
573                 GtkWidget *w;
574                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
575                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
576                 if (gtk_widget_is_focus (w)) {
577                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
578                         return;
579                 }
580         }
581         modest_ui_actions_on_delete_message (action, win);
582 }
583
584
585
586 void
587 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
588 {       
589         ModestWindowMgr *mgr = NULL;
590         
591 #ifdef MODEST_PLATFORM_MAEMO
592         modest_osso_save_state();
593 #endif /* MODEST_PLATFORM_MAEMO */
594
595         g_debug ("closing down, clearing %d item(s) from operation queue",
596                  modest_mail_operation_queue_num_elements
597                  (modest_runtime_get_mail_operation_queue()));
598
599         /* cancel all outstanding operations */
600         modest_mail_operation_queue_cancel_all 
601                 (modest_runtime_get_mail_operation_queue());
602         
603         g_debug ("queue has been cleared");
604
605
606         /* Check if there are opened editing windows */ 
607         mgr = modest_runtime_get_window_mgr ();
608         modest_window_mgr_close_all_windows (mgr);
609
610         /* note: when modest-tny-account-store is finalized,
611            it will automatically set all network connections
612            to offline */
613
614 /*      gtk_main_quit (); */
615 }
616
617 void
618 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
619 {
620         gboolean ret_value;
621
622         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
623
624 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
625 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
626 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
627 /*              gboolean ret_value; */
628 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
629 /*      } else if (MODEST_IS_WINDOW (win)) { */
630 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
631 /*      } else { */
632 /*              g_return_if_reached (); */
633 /*      } */
634 }
635
636 void
637 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
638 {
639         GtkClipboard *clipboard = NULL;
640         gchar *selection = NULL;
641
642         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
643         selection = gtk_clipboard_wait_for_text (clipboard);
644
645         /* Question: why is the clipboard being used here? 
646          * It doesn't really make a lot of sense. */
647
648         if (selection)
649         {
650                 modest_address_book_add_address (selection);
651                 g_free (selection);
652         }
653 }
654
655 void
656 modest_ui_actions_on_accounts (GtkAction *action, 
657                                ModestWindow *win)
658 {
659         /* This is currently only implemented for Maemo */
660 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
661         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
662                 modest_ui_actions_run_account_setup_wizard (win);
663                 return;
664         } else {
665                 /* Show the list of accounts */
666                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
667                 gtk_window_set_transient_for (account_win, GTK_WINDOW (win));
668                 
669                 /* The accounts dialog must be modal */
670                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win);
671                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win)); 
672         }
673 #else
674         GtkWidget *dialog, *label;
675         
676         /* Create the widgets */
677         
678         dialog = gtk_dialog_new_with_buttons ("Message",
679                                               GTK_WINDOW(win),
680                                               GTK_DIALOG_DESTROY_WITH_PARENT,
681                                               GTK_STOCK_OK,
682                                               GTK_RESPONSE_NONE,
683                                               NULL);
684         label = gtk_label_new ("Hello World!");
685         
686         /* Ensure that the dialog box is destroyed when the user responds. */
687         
688         g_signal_connect_swapped (dialog, "response", 
689                                   G_CALLBACK (gtk_widget_destroy),
690                                   dialog);
691         
692         /* Add the label, and show everything we've added to the dialog. */
693         
694         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
695                            label);
696         gtk_widget_show_all (dialog);
697 #endif /* MODEST_PLATFORM_MAEMO */
698 }
699
700 static void
701 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
702 {
703         /* Save any changes. */
704         modest_connection_specific_smtp_window_save_server_accounts (
705                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
706         gtk_widget_destroy (GTK_WIDGET (window));
707 }
708
709
710
711 void
712 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
713 {
714         /* This is currently only implemented for Maemo,
715          * because it requires an API (libconic) to detect different connection 
716          * possiblities.
717          */
718 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
719         
720         /* Create the window if necessary: */
721         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
722         modest_connection_specific_smtp_window_fill_with_connections (
723                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
724                 modest_runtime_get_account_mgr());
725
726         /* Show the window: */  
727         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
728         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
729         gtk_widget_show (specific_window);
730     
731         /* Save changes when the window is hidden: */
732         g_signal_connect (specific_window, "hide", 
733                 G_CALLBACK (on_smtp_servers_window_hide), win);
734 #endif /* MODEST_PLATFORM_MAEMO */
735 }
736
737 void
738 modest_ui_actions_compose_msg(ModestWindow *win,
739                               const gchar *to_str,
740                               const gchar *cc_str,
741                               const gchar *bcc_str,
742                               const gchar *subject_str,
743                               const gchar *body_str,
744                               GSList *attachments)
745 {
746         gchar *account_name = NULL;
747         TnyMsg *msg = NULL;
748         TnyAccount *account = NULL;
749         TnyFolder *folder = NULL;
750         gchar *from_str = NULL, *signature = NULL, *body = NULL;
751         gboolean use_signature = FALSE;
752         ModestWindow *msg_win = NULL;
753         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
754         ModestTnyAccountStore *store = modest_runtime_get_account_store();
755
756         if (win) account_name = g_strdup (modest_window_get_active_account (win));
757         if (!account_name) account_name = modest_account_mgr_get_default_account(mgr);
758         if (!account_name) {
759                 g_printerr ("modest: no account found\n");
760                 goto cleanup;
761         }
762         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
763         if (!account) {
764                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
765                 goto cleanup;
766         }
767         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
768         if (!folder) {
769                 g_printerr ("modest: failed to find Drafts folder\n");
770                 goto cleanup;
771         }
772         from_str = modest_account_mgr_get_from_string (mgr, account_name);
773         if (!from_str) {
774                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
775                 goto cleanup;
776         }
777
778         signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
779         if (body_str != NULL) {
780                 body = use_signature ? g_strconcat(body_str, "\n", signature, NULL) : g_strdup(body_str);
781         } else {
782                 body = use_signature ? g_strconcat("\n", signature, NULL) : g_strdup("");
783         }
784
785         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL);
786         if (!msg) {
787                 g_printerr ("modest: failed to create new msg\n");
788                 goto cleanup;
789         }
790
791         /* Create and register edit window */
792         /* This is destroyed by TODO. */
793         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
794         while (attachments) {
795                 modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
796                                                        attachments->data);
797                 attachments = g_slist_next(attachments);
798         }
799         modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win);
800
801         if (win) {
802                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
803                                               GTK_WINDOW (win));
804         }
805         gtk_widget_show_all (GTK_WIDGET (msg_win));
806
807 cleanup:
808         g_free (from_str);
809         g_free (signature);
810         g_free (body);
811         g_free (account_name);
812         if (account) g_object_unref (G_OBJECT(account));
813         if (folder) g_object_unref (G_OBJECT(folder));
814         if (msg_win) g_object_unref (G_OBJECT(msg_win));
815         if (msg) g_object_unref (G_OBJECT(msg));
816 }
817
818 void
819 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
820 {
821         /* if there are no accounts yet, just show the wizard */
822         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
823                 if (!modest_ui_actions_run_account_setup_wizard (win)) return;
824         }
825
826         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL);
827 }
828
829 gboolean 
830 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
831                                        TnyHeader *header,
832                                        TnyMsg *msg)
833 {
834         ModestMailOperationStatus status;
835
836         /* If there is no message or the operation was not successful */
837         status = modest_mail_operation_get_status (mail_op);
838         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
839
840                 /* Remove the header from the preregistered uids */
841                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
842                                                      header);
843
844                 return FALSE;
845         }
846
847         return TRUE;
848 }
849
850 static void
851 open_msg_cb (ModestMailOperation *mail_op, TnyHeader *header,  TnyMsg *msg, gpointer user_data)
852 {
853         ModestWindowMgr *mgr = NULL;
854         ModestWindow *parent_win = NULL;
855         ModestWindow *win = NULL;
856         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
857         gchar *account = NULL;
858         TnyFolder *folder;
859         gboolean open_in_editor = FALSE;
860         
861         /* Do nothing if there was any problem with the mail
862            operation. The error will be shown by the error_handler of
863            the mail operation */
864         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
865                 return;
866
867         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
868         folder = tny_header_get_folder (header);
869
870         /* Mark header as read */
871         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
872
873         /* Gets folder type (OUTBOX headers will be opened in edit window */
874         if (modest_tny_folder_is_local_folder (folder)) {
875                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
876                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
877                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
878         }
879
880                 
881         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
882                 TnyTransportAccount *traccount = NULL;
883                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
884                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
885                 if (traccount) {
886                         ModestTnySendQueue *send_queue = NULL;
887                         ModestTnySendQueueStatus status;
888                         char *msg_id;
889                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
890                                                    TNY_ACCOUNT(traccount)));
891                         send_queue = modest_runtime_get_send_queue(traccount);
892                         msg_id = modest_tny_send_queue_get_msg_id (header);
893                         status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
894                         /* Only open messages in outbox with the editor if they are in Failed state */
895                         if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
896                                 open_in_editor = TRUE;
897                         }
898                         g_free(msg_id);
899                         g_object_unref(traccount);
900                 } else {
901                         g_warning("Cannot get transport account for message in outbox!!");
902                 }
903         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
904                 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
905         }
906
907         /* Get account */
908         if (!account)
909                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
910         if (!account)
911                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
912         
913         if (open_in_editor) {
914                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
915                 const gchar *from_header = NULL;
916
917                 from_header = tny_header_get_from (header);
918
919                 /* we cannot edit without a valid account... */
920                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
921                         if (!modest_ui_actions_run_account_setup_wizard(parent_win))
922                                 goto cleanup;
923                 }
924                 
925                 if (from_header) {
926                         GSList *accounts = modest_account_mgr_account_names (mgr, TRUE);
927                         GSList *node = NULL;
928                         for (node = accounts; node != NULL; node = g_slist_next (node)) {
929                                 gchar *from = modest_account_mgr_get_from_string (mgr, node->data);
930                                 
931                                 if (from && (strcmp (from_header, from) == 0)) {
932                                         g_free (account);
933                                         account = g_strdup (node->data);
934                                         g_free (from);
935                                         break;
936                                 }
937                                 g_free (from);
938                         }
939                         g_slist_foreach (accounts, (GFunc) g_free, NULL);
940                         g_slist_free (accounts);
941                 }
942
943                 win = modest_msg_edit_window_new (msg, account, TRUE);
944
945
946                 /* Show banner */
947                 modest_platform_information_banner (NULL, NULL, _("mail_ib_opening_draft_message"));
948
949         } else {
950                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
951                 
952                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
953                         GtkWidget *header_view;
954                         GtkTreeSelection *sel;
955                         GList *sel_list = NULL;
956                         GtkTreeModel *model;
957                         
958                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
959                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
960
961                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
962                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
963
964                         if (sel_list != NULL) {
965                                 GtkTreeRowReference *row_reference;
966
967                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
968                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
969                                 g_list_free (sel_list);
970                                 
971                                 win = modest_msg_view_window_new_with_header_model (
972                                                 msg, account, (const gchar*) uid,
973                                                 model, row_reference);
974                                 gtk_tree_row_reference_free (row_reference);
975                         } else {
976                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
977                         }
978                 } else {
979                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
980                 }
981                 g_free (uid);
982         }
983         
984         /* Register and show new window */
985         if (win != NULL) {
986                 mgr = modest_runtime_get_window_mgr ();
987                 modest_window_mgr_register_window (mgr, win);
988                 g_object_unref (win);
989                 gtk_widget_show_all (GTK_WIDGET(win));
990         }
991
992         /* Update toolbar dimming state */
993         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
994                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
995         }
996
997 cleanup:
998         /* Free */
999         g_free(account);
1000         g_object_unref (parent_win);
1001         g_object_unref (folder);
1002 }
1003
1004
1005 static void
1006 open_msg_error_handler (ModestMailOperation *mail_op,
1007                         gpointer user_data)
1008 {
1009         /* Show the message error */
1010         GObject *win = modest_mail_operation_get_source (mail_op);
1011
1012         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, 
1013                                                 (gchar *) user_data);
1014         if (win)
1015                 g_object_unref (win);
1016 }
1017
1018 void
1019 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
1020                                                gpointer user_data)
1021 {
1022         const GError *error;
1023         GObject *win = modest_mail_operation_get_source (mail_op);
1024
1025         error = modest_mail_operation_get_error (mail_op);
1026  
1027         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
1028
1029                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1030                                                         error->message);
1031         } else {
1032                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1033                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
1034         }
1035
1036         if (win)
1037                 g_object_unref (win);
1038 }
1039
1040 /**
1041  * Returns the account a list of headers belongs to. It returns a
1042  * *new* reference so don't forget to unref it
1043  */
1044 static TnyAccount*
1045 get_account_from_header_list (TnyList *headers)
1046 {
1047         TnyAccount *account = NULL;
1048
1049         if (tny_list_get_length (headers) > 0) {
1050                 TnyIterator *iter = tny_list_create_iterator (headers);
1051                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1052                 TnyFolder *folder = tny_header_get_folder (header);
1053                 account = tny_folder_get_account (folder);
1054                 g_object_unref (folder);
1055                 g_object_unref (header);
1056                 g_object_unref (iter);
1057         }
1058         return account;
1059 }
1060
1061 /*
1062  * This function is used by both modest_ui_actions_on_open and
1063  * modest_ui_actions_on_header_activated. This way we always do the
1064  * same when trying to open messages.
1065  */
1066 static void
1067 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
1068 {
1069         ModestWindowMgr *mgr = NULL;
1070         TnyIterator *iter = NULL, *iter_not_opened = NULL;
1071         ModestMailOperation *mail_op = NULL;
1072         TnyList *not_opened_headers = NULL;
1073         TnyHeaderFlags flags = 0;
1074         TnyAccount *account;
1075                 
1076         g_return_if_fail (headers != NULL);
1077
1078         /* Check that only one message is selected for opening */
1079         if (tny_list_get_length (headers) != 1) {
1080                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1081                                                         _("mcen_ib_select_one_message"));
1082                 return;
1083         }
1084
1085         mgr = modest_runtime_get_window_mgr ();
1086         iter = tny_list_create_iterator (headers);
1087
1088         /* Get the account */
1089         account = get_account_from_header_list (headers);
1090         
1091         /* Look if we already have a message view for each header. If
1092            true, then remove the header from the list of headers to
1093            open */
1094         not_opened_headers = tny_simple_list_new ();
1095         while (!tny_iterator_is_done (iter)) {
1096
1097                 ModestWindow *window = NULL;
1098                 TnyHeader *header = NULL;
1099                 gboolean found = FALSE;
1100                 
1101                 header = TNY_HEADER (tny_iterator_get_current (iter));
1102                 if (header)
1103                         flags = tny_header_get_flags (header);
1104
1105                 window = NULL;
1106                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1107                 
1108                 /* Do not open again the message and present the
1109                    window to the user */
1110                 if (found) {
1111                         if (window)
1112                                 gtk_window_present (GTK_WINDOW (window));
1113                         else
1114                                 /* the header has been registered already, we don't do
1115                                  * anything but wait for the window to come up*/
1116                                 g_debug ("header %p already registered, waiting for window", header);
1117                 } else {
1118                         tny_list_append (not_opened_headers, G_OBJECT (header));
1119                 }
1120
1121                 if (header)
1122                         g_object_unref (header);
1123
1124                 tny_iterator_next (iter);
1125         }
1126         g_object_unref (iter);
1127         iter = NULL;
1128
1129         /* Open each message */
1130         if (tny_list_get_length (not_opened_headers) == 0)
1131                 goto cleanup;
1132         
1133         /* If some messages would have to be downloaded, ask the user to 
1134          * make a connection. It's generally easier to do this here (in the mainloop) 
1135          * than later in a thread:
1136          */
1137         if (tny_list_get_length (not_opened_headers) > 0) {
1138                 TnyIterator *iter;
1139                 gboolean found = FALSE;
1140
1141                 iter = tny_list_create_iterator (not_opened_headers);
1142                 while (!tny_iterator_is_done (iter) && !found) {
1143                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1144                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1145                                 found = TRUE;
1146                         else
1147                                 tny_iterator_next (iter);
1148
1149                         g_object_unref (header);
1150                 }
1151                 g_object_unref (iter);
1152
1153                 /* Ask the user if there are any uncached messages */
1154                 if (found && !connect_to_get_msg (win, 
1155                                                   header_list_count_uncached_msgs (not_opened_headers), 
1156                                                   account))
1157                         goto cleanup;
1158         }
1159         
1160         /* Register the headers before actually creating the windows: */
1161         iter_not_opened = tny_list_create_iterator (not_opened_headers);
1162         while (!tny_iterator_is_done (iter_not_opened)) {
1163                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1164                 if (header) {
1165                         modest_window_mgr_register_header (mgr, header, NULL);
1166                         g_object_unref (header);
1167                 }               
1168                 tny_iterator_next (iter_not_opened);
1169         }
1170         g_object_unref (iter_not_opened);
1171         iter_not_opened = NULL;
1172
1173         /* Create the mail operation */
1174         if (tny_list_get_length (not_opened_headers) > 1) {
1175                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win), 
1176                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1177                                                                          NULL, NULL);
1178                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1179                 
1180                 modest_mail_operation_get_msgs_full (mail_op, 
1181                                                      not_opened_headers, 
1182                                                      open_msg_cb, 
1183                                                      NULL, 
1184                                                      NULL);
1185         } else {
1186                 TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1187                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1188                 const gchar *proto_name;
1189                 gchar *error_msg;
1190                 ModestTransportStoreProtocol proto;
1191
1192                 /* Get the error message depending on the protocol */
1193                 proto_name = tny_account_get_proto (account);
1194                 if (proto_name != NULL) {
1195                         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
1196                 } else {
1197                         proto = MODEST_PROTOCOL_STORE_MAILDIR;
1198                 }
1199                 
1200                 if (proto == MODEST_PROTOCOL_STORE_POP) {
1201                         error_msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
1202                 } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
1203                         error_msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
1204                                                      tny_header_get_subject (header));
1205                 } else {
1206                         error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1207                 }
1208
1209                 /* Create and call the mail operation */
1210                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win), 
1211                                                                          open_msg_error_handler, 
1212                                                                          error_msg,
1213                                                                          g_free);
1214                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1215
1216                 modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1217
1218                 g_object_unref (header);
1219                 g_object_unref (iter);
1220         }
1221         g_object_unref (mail_op);
1222
1223 cleanup:
1224         /* Clean */
1225         if (account)
1226                 g_object_unref (account);
1227         if (not_opened_headers)
1228                 g_object_unref (not_opened_headers);
1229 }
1230
1231 void
1232 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1233 {
1234         TnyList *headers;
1235
1236         /* Get headers */
1237         headers = get_selected_headers (win);
1238         if (!headers)
1239                 return;
1240
1241         /* Open them */
1242         _modest_ui_actions_open (headers, win);
1243
1244         g_object_unref(headers);
1245 }
1246
1247
1248 static void
1249 free_reply_forward_helper (gpointer data)
1250 {
1251         ReplyForwardHelper *helper;
1252
1253         helper = (ReplyForwardHelper *) data;
1254         g_free (helper->account_name);
1255         g_slice_free (ReplyForwardHelper, helper);
1256 }
1257
1258 static void
1259 reply_forward_cb (ModestMailOperation *mail_op,  TnyHeader *header, TnyMsg *msg,
1260                   gpointer user_data)
1261 {
1262         TnyMsg *new_msg;
1263         ReplyForwardHelper *rf_helper;
1264         ModestWindow *msg_win = NULL;
1265         ModestEditType edit_type;
1266         gchar *from = NULL;
1267         TnyAccount *account = NULL;
1268         ModestWindowMgr *mgr = NULL;
1269         gchar *signature = NULL;
1270         gboolean use_signature;
1271
1272         /* If there was any error. The mail operation could be NULL,
1273            this means that we already have the message downloaded and
1274            that we didn't do a mail operation to retrieve it */
1275         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1276                 return;
1277                         
1278         g_return_if_fail (user_data != NULL);
1279         rf_helper = (ReplyForwardHelper *) user_data;
1280
1281         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1282                                                    rf_helper->account_name);
1283         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1284                                                       rf_helper->account_name, 
1285                                                       &use_signature);
1286
1287         /* Create reply mail */
1288         switch (rf_helper->action) {
1289         case ACTION_REPLY:
1290                 new_msg = 
1291                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1292                                                          rf_helper->reply_forward_type,
1293                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1294                 break;
1295         case ACTION_REPLY_TO_ALL:
1296                 new_msg = 
1297                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1298                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1299                 edit_type = MODEST_EDIT_TYPE_REPLY;
1300                 break;
1301         case ACTION_FORWARD:
1302                 new_msg = 
1303                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1304                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1305                 break;
1306         default:
1307                 g_return_if_reached ();
1308                 return;
1309         }
1310
1311         g_free (signature);
1312
1313         if (!new_msg) {
1314                 g_printerr ("modest: failed to create message\n");
1315                 goto cleanup;
1316         }
1317
1318         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1319                                                                        rf_helper->account_name,
1320                                                                        TNY_ACCOUNT_TYPE_STORE);
1321         if (!account) {
1322                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1323                 goto cleanup;
1324         }
1325
1326         /* Create and register the windows */
1327         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1328         mgr = modest_runtime_get_window_mgr ();
1329         modest_window_mgr_register_window (mgr, msg_win);
1330
1331         if (rf_helper->parent_window != NULL) {
1332                 gdouble parent_zoom;
1333
1334                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1335                 modest_window_set_zoom (msg_win, parent_zoom);
1336         }
1337
1338         /* Show edit window */
1339         gtk_widget_show_all (GTK_WIDGET (msg_win));
1340
1341 cleanup:
1342         if (msg_win)
1343                 g_object_unref (msg_win);
1344         if (new_msg)
1345                 g_object_unref (G_OBJECT (new_msg));
1346         if (account)
1347                 g_object_unref (G_OBJECT (account));
1348 /*      g_object_unref (msg); */
1349         free_reply_forward_helper (rf_helper);
1350 }
1351
1352 /* Checks a list of headers. If any of them are not currently
1353  * downloaded (CACHED) then returns TRUE else returns FALSE.
1354  */
1355 static gint
1356 header_list_count_uncached_msgs (TnyList *header_list)
1357 {
1358         TnyIterator *iter;
1359         gint uncached_messages = 0;
1360
1361         iter = tny_list_create_iterator (header_list);
1362         while (!tny_iterator_is_done (iter)) {
1363                 TnyHeader *header;
1364
1365                 header = TNY_HEADER (tny_iterator_get_current (iter));
1366                 if (header) {
1367                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1368                                 uncached_messages ++;
1369                         g_object_unref (header);
1370                 }
1371
1372                 tny_iterator_next (iter);
1373         }
1374         g_object_unref (iter);
1375
1376         return uncached_messages;
1377 }
1378
1379 /* Returns FALSE if the user does not want to download the
1380  * messages. Returns TRUE if the user allowed the download.
1381  */
1382 static gboolean
1383 connect_to_get_msg (ModestWindow *win,
1384                     gint num_of_uncached_msgs,
1385                     TnyAccount *account)
1386 {
1387         GtkResponseType response;
1388
1389         /* Allways download if we are online. */
1390         if (tny_device_is_online (modest_runtime_get_device ()))
1391                 return TRUE;
1392
1393         /* If offline, then ask for user permission to download the messages */
1394         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1395                         ngettext("mcen_nc_get_msg",
1396                         "mcen_nc_get_msgs",
1397                         num_of_uncached_msgs));
1398
1399         if (response == GTK_RESPONSE_CANCEL)
1400                 return FALSE;
1401
1402         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1403 }
1404
1405 /*
1406  * Common code for the reply and forward actions
1407  */
1408 static void
1409 reply_forward (ReplyForwardAction action, ModestWindow *win)
1410 {
1411         ModestMailOperation *mail_op = NULL;
1412         TnyList *header_list = NULL;
1413         ReplyForwardHelper *rf_helper = NULL;
1414         guint reply_forward_type;
1415         gboolean continue_download = TRUE;
1416         gboolean do_retrieve = TRUE;
1417         
1418         g_return_if_fail (MODEST_IS_WINDOW(win));
1419
1420         /* we need an account when editing */
1421         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1422                 if (!modest_ui_actions_run_account_setup_wizard (win))
1423                         return;
1424         }
1425         
1426         header_list = get_selected_headers (win);
1427         if (!header_list)
1428                 return;
1429
1430         reply_forward_type = 
1431                 modest_conf_get_int (modest_runtime_get_conf (),
1432                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1433                                      NULL);
1434
1435         /* check if we need to download msg before asking about it */
1436         do_retrieve = (action == ACTION_FORWARD) ||
1437                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1438
1439         if (do_retrieve){
1440                 gint num_of_unc_msgs;
1441
1442                 /* check that the messages have been previously downloaded */
1443                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1444                 /* If there are any uncached message ask the user
1445                  * whether he/she wants to download them. */
1446                 if (num_of_unc_msgs) {
1447                         TnyAccount *account = get_account_from_header_list (header_list);
1448                         continue_download = connect_to_get_msg (win, num_of_unc_msgs, account);
1449                         g_object_unref (account);
1450                 }
1451         }
1452
1453         if (!continue_download) {
1454                 g_object_unref (header_list);
1455                 return;
1456         }
1457         
1458         /* We assume that we can only select messages of the
1459            same folder and that we reply all of them from the
1460            same account. In fact the interface currently only
1461            allows single selection */
1462         
1463         /* Fill helpers */
1464         rf_helper = g_slice_new0 (ReplyForwardHelper);
1465         rf_helper->reply_forward_type = reply_forward_type;
1466         rf_helper->action = action;
1467         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1468         
1469         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1470                 rf_helper->parent_window = GTK_WIDGET (win);
1471         if (!rf_helper->account_name)
1472                 rf_helper->account_name =
1473                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1474
1475         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1476                 TnyMsg *msg;
1477                 TnyHeader *header;
1478                 /* Get header and message. Do not free them here, the
1479                    reply_forward_cb must do it */
1480                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1481                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1482                 if (!msg || !header) {
1483                         if (msg)
1484                                 g_object_unref (msg);
1485                         g_printerr ("modest: no message found\n");
1486                         return;
1487                 } else {
1488                         reply_forward_cb (NULL, header, msg, rf_helper);
1489                 }
1490                 if (header)
1491                         g_object_unref (header);
1492         } else {
1493                 TnyHeader *header;
1494                 TnyIterator *iter;
1495
1496                 /* Only reply/forward to one message */
1497                 iter = tny_list_create_iterator (header_list);
1498                 header = TNY_HEADER (tny_iterator_get_current (iter));
1499                 g_object_unref (iter);
1500
1501                 if (header) {
1502                         /* Retrieve messages */
1503                         if (do_retrieve) {
1504                                 mail_op = 
1505                                         modest_mail_operation_new_with_error_handling (G_OBJECT(win),
1506                                                                                        modest_ui_actions_get_msgs_full_error_handler, 
1507                                                                                        NULL, NULL);
1508                                 modest_mail_operation_queue_add (
1509                                         modest_runtime_get_mail_operation_queue (), mail_op);
1510                                 
1511                                 modest_mail_operation_get_msg (mail_op,
1512                                                                header,
1513                                                                reply_forward_cb,
1514                                                                rf_helper);
1515                                 /* Clean */
1516                                 g_object_unref(mail_op);
1517                         } else {
1518                                 /* we put a ref here to prevent double unref as the reply
1519                                  * forward callback unrefs the header at its end */
1520                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1521                         }
1522
1523
1524                         g_object_unref (header);
1525                 }
1526
1527         }
1528
1529         /* Free */
1530         g_object_unref (header_list);
1531 }
1532
1533 void
1534 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1535 {
1536         g_return_if_fail (MODEST_IS_WINDOW(win));
1537
1538         reply_forward (ACTION_REPLY, win);
1539 }
1540
1541 void
1542 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1543 {
1544         g_return_if_fail (MODEST_IS_WINDOW(win));
1545
1546         reply_forward (ACTION_FORWARD, win);
1547 }
1548
1549 void
1550 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1551 {
1552         g_return_if_fail (MODEST_IS_WINDOW(win));
1553
1554         reply_forward (ACTION_REPLY_TO_ALL, win);
1555 }
1556
1557 void 
1558 modest_ui_actions_on_next (GtkAction *action, 
1559                            ModestWindow *window)
1560 {
1561         if (MODEST_IS_MAIN_WINDOW (window)) {
1562                 GtkWidget *header_view;
1563
1564                 header_view = modest_main_window_get_child_widget (
1565                                 MODEST_MAIN_WINDOW(window),
1566                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1567                 if (!header_view)
1568                         return;
1569         
1570                 modest_header_view_select_next (
1571                                 MODEST_HEADER_VIEW(header_view)); 
1572         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1573                 modest_msg_view_window_select_next_message (
1574                                 MODEST_MSG_VIEW_WINDOW (window));
1575         } else {
1576                 g_return_if_reached ();
1577         }
1578 }
1579
1580 void 
1581 modest_ui_actions_on_prev (GtkAction *action, 
1582                            ModestWindow *window)
1583 {
1584         g_return_if_fail (MODEST_IS_WINDOW(window));
1585
1586         if (MODEST_IS_MAIN_WINDOW (window)) {
1587                 GtkWidget *header_view;
1588                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1589                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1590                 if (!header_view)
1591                         return;
1592                 
1593                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1594         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1595                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1596         } else {
1597                 g_return_if_reached ();
1598         }
1599 }
1600
1601 void 
1602 modest_ui_actions_on_sort (GtkAction *action, 
1603                            ModestWindow *window)
1604 {
1605         g_return_if_fail (MODEST_IS_WINDOW(window));
1606
1607         if (MODEST_IS_MAIN_WINDOW (window)) {
1608                 GtkWidget *header_view;
1609                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1610                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1611                 if (!header_view) {
1612                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1613
1614                         return;
1615                 }
1616
1617                 /* Show sorting dialog */
1618                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1619         }
1620 }
1621
1622 static void
1623 new_messages_arrived (ModestMailOperation *self, 
1624                       TnyList *new_headers,
1625                       gpointer user_data)
1626 {
1627         GObject *source;
1628
1629         source = modest_mail_operation_get_source (self);
1630
1631         /* Notify new messages have been downloaded. Do not notify if
1632            the send&receive was invoked by the user, i.e, if the mail
1633            operation has a source (the main window) */
1634         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0) && !source)
1635                 modest_platform_on_new_headers_received (new_headers);
1636
1637         if (source)
1638                 g_object_unref (source);
1639 }
1640
1641 typedef struct {
1642         TnyAccount *account;
1643         ModestWindow *win;
1644         gchar *account_name;
1645 } SendReceiveInfo;
1646
1647 static void
1648 do_send_receive_performer (gboolean canceled, 
1649                            GError *err,
1650                            GtkWindow *parent_window, 
1651                            TnyAccount *account, 
1652                            gpointer user_data)
1653 {
1654         ModestMailOperation *mail_op;
1655         SendReceiveInfo *info;
1656
1657         info = (SendReceiveInfo *) user_data;
1658
1659         if (err || canceled) {
1660
1661                 goto clean;
1662         }
1663
1664         /* Set send/receive operation in progress */    
1665         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1666                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
1667         
1668         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (info->win),
1669                                                                  modest_ui_actions_send_receive_error_handler,
1670                                                                  NULL, NULL);
1671
1672         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
1673                 g_signal_connect (G_OBJECT(mail_op), "operation-finished", 
1674                                   G_CALLBACK (on_send_receive_finished), 
1675                                   info->win);
1676
1677         /* Send & receive. */
1678         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1679         modest_mail_operation_update_account (mail_op, info->account_name, new_messages_arrived, info->win);
1680         g_object_unref (G_OBJECT (mail_op));
1681         
1682  clean:
1683         /* Frees */
1684         if (info->account_name)
1685                 g_free (info->account_name);
1686         if (info->win)
1687                 g_object_unref (info->win);
1688         if (info->account)
1689                 g_object_unref (info->account);
1690         g_slice_free (SendReceiveInfo, info);
1691 }
1692
1693 /*
1694  * This function performs the send & receive required actions. The
1695  * window is used to create the mail operation. Typically it should
1696  * always be the main window, but we pass it as argument in order to
1697  * be more flexible.
1698  */
1699 void
1700 modest_ui_actions_do_send_receive (const gchar *account_name, 
1701                                    ModestWindow *win)
1702 {
1703         gchar *acc_name = NULL;
1704         SendReceiveInfo *info;
1705         ModestTnyAccountStore *acc_store;
1706
1707         /* If no account name was provided then get the current account, and if
1708            there is no current account then pick the default one: */
1709         if (!account_name) {
1710                 if (win)
1711                         acc_name = g_strdup (modest_window_get_active_account (win));
1712                 if (!acc_name)
1713                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1714                 if (!acc_name) {
1715                         g_printerr ("modest: cannot get default account\n");
1716                         return;
1717                 }
1718         } else {
1719                 acc_name = g_strdup (account_name);
1720         }
1721
1722         acc_store = modest_runtime_get_account_store ();
1723
1724         /* Create the info for the connect and perform */
1725         info = g_slice_new (SendReceiveInfo);
1726         info->account_name = acc_name;
1727         info->win = (win) ? g_object_ref (win) : NULL;
1728         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
1729                                                                      TNY_ACCOUNT_TYPE_STORE);
1730
1731         /* Invoke the connect and perform */
1732         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, info->account, 
1733                                              do_send_receive_performer, info);
1734 }
1735
1736
1737 static void
1738 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1739                                   ModestWindow *win)
1740 {
1741         TnyTransportAccount *transport_account;
1742         TnySendQueue *send_queue = NULL;
1743         GError *error = NULL;
1744
1745         /* Get transport account */
1746         transport_account =
1747                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1748                                       (modest_runtime_get_account_store(),
1749                                        account_name,
1750                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1751         if (!transport_account) {
1752                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1753                 goto frees;
1754         }
1755
1756         /* Get send queue*/
1757         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1758         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1759                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1760                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1761                              "modest: could not find send queue for account\n");
1762         } else {
1763                 /* Keeep messages in outbox folder */
1764                 tny_send_queue_cancel (send_queue, FALSE, &error);
1765         }       
1766
1767  frees:
1768         if (transport_account != NULL) 
1769                 g_object_unref (G_OBJECT (transport_account));
1770 }
1771
1772 static void
1773 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1774 {
1775         GSList *account_names, *iter;
1776
1777         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1778                                                           TRUE);
1779
1780         iter = account_names;
1781         while (iter) {                  
1782                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1783                 iter = g_slist_next (iter);
1784         }
1785
1786         modest_account_mgr_free_account_names (account_names);
1787         account_names = NULL;
1788 }
1789
1790 void
1791 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1792
1793 {
1794         /* Check if accounts exist */
1795         gboolean accounts_exist = 
1796                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1797         
1798         /* If not, allow the user to create an account before trying to send/receive. */
1799         if (!accounts_exist)
1800                 modest_ui_actions_on_accounts (NULL, win);
1801         
1802         /* Cancel all sending operaitons */     
1803         modest_ui_actions_cancel_send_all (win);
1804 }
1805
1806 /*
1807  * Refreshes all accounts. This function will be used by automatic
1808  * updates
1809  */
1810 void
1811 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1812 {
1813         GSList *account_names, *iter;
1814
1815         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1816                                                           TRUE);
1817
1818         iter = account_names;
1819         while (iter) {                  
1820                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1821                 iter = g_slist_next (iter);
1822         }
1823
1824         modest_account_mgr_free_account_names (account_names);
1825         account_names = NULL;
1826 }
1827
1828 static void 
1829 refresh_current_folder(ModestWindow *win)
1830 {
1831         /* Refresh currently selected folder. Note that if we only
1832            want to retreive the headers, then the refresh only will
1833            invoke a poke_status over all folders, i.e., only the
1834            total/unread count will be updated */
1835         if (MODEST_IS_MAIN_WINDOW (win)) {
1836                 GtkWidget *header_view, *folder_view;
1837                 TnyFolderStore *folder_store;
1838
1839                 /* Get folder and header view */
1840                 folder_view = 
1841                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1842                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1843                 if (!folder_view)
1844                         return;
1845
1846                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1847
1848                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1849                         header_view = 
1850                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1851                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1852                 
1853                         /* We do not need to set the contents style
1854                            because it hasn't changed. We also do not
1855                            need to save the widget status. Just force
1856                            a refresh */
1857                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1858                                                        TNY_FOLDER (folder_store),
1859                                                        folder_refreshed_cb,
1860                                                        MODEST_MAIN_WINDOW (win));
1861                 }
1862                 
1863                 if (folder_store)
1864                         g_object_unref (folder_store);
1865         }
1866 }
1867
1868
1869 /*
1870  * Handler of the click on Send&Receive button in the main toolbar
1871  */
1872 void
1873 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1874 {
1875         /* Check if accounts exist */
1876         gboolean accounts_exist = 
1877                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1878         
1879         /* If not, allow the user to create an account before trying to send/receive. */
1880         if (!accounts_exist)
1881                 modest_ui_actions_on_accounts (NULL, win);
1882
1883         /* Refresh the current folder if we're viewing a window */
1884         if (win)
1885                 refresh_current_folder (win);
1886         
1887         /* Refresh the active account */
1888         modest_ui_actions_do_send_receive (NULL, win);
1889 }
1890
1891
1892 void
1893 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1894 {
1895         ModestConf *conf;
1896         GtkWidget *header_view;
1897         
1898         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1899
1900         header_view = modest_main_window_get_child_widget (main_window,
1901                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1902         if (!header_view)
1903                 return;
1904
1905         conf = modest_runtime_get_conf ();
1906         
1907         /* what is saved/restored is depending on the style; thus; we save with
1908          * old style, then update the style, and restore for this new style
1909          */
1910         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1911         
1912         if (modest_header_view_get_style
1913             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1914                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1915                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1916         else
1917                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1918                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1919
1920         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1921                                       MODEST_CONF_HEADER_VIEW_KEY);
1922 }
1923
1924
1925 void 
1926 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1927                                       TnyHeader *header,
1928                                       ModestMainWindow *main_window)
1929 {
1930         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1931         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1932         
1933         /* in the case the folder is empty, show the empty folder message and focus
1934          * folder view */
1935         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1936                 if (modest_header_view_is_empty (header_view)) {
1937                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1938                         GtkWidget *folder_view = 
1939                                 modest_main_window_get_child_widget (main_window,
1940                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1941                         if (folder != NULL) 
1942                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1943                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1944                         return;
1945                 }
1946         }
1947         /* If no header has been selected then exit */
1948         if (!header)
1949                 return;
1950
1951         /* Update focus */
1952         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1953             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1954
1955         /* Update toolbar dimming state */
1956         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1957 }
1958
1959 void
1960 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1961                                        TnyHeader *header,
1962                                        ModestMainWindow *main_window)
1963 {
1964         TnyList *headers;
1965
1966         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1967         
1968         if (!header)
1969                 return;
1970
1971         if (modest_header_view_count_selected_headers (header_view) > 1) {
1972                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1973                 return;
1974         }
1975
1976
1977 /*      headers = tny_simple_list_new (); */
1978 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1979         headers = modest_header_view_get_selected_headers (header_view);
1980
1981         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1982
1983         g_object_unref (headers);
1984 }
1985
1986 static void
1987 set_active_account_from_tny_account (TnyAccount *account,
1988                                      ModestWindow *window)
1989 {
1990         const gchar *server_acc_name = tny_account_get_id (account);
1991         
1992         /* We need the TnyAccount provided by the
1993            account store because that is the one that
1994            knows the name of the Modest account */
1995         TnyAccount *modest_server_account = modest_server_account = 
1996                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1997                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1998                                                              server_acc_name);
1999         if (!modest_server_account) {
2000                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2001                 return;
2002         }
2003
2004         /* Update active account, but only if it's not a pseudo-account */
2005         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2006             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2007                 const gchar *modest_acc_name = 
2008                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2009                 if (modest_acc_name)
2010                         modest_window_set_active_account (window, modest_acc_name);
2011         }
2012         
2013         g_object_unref (modest_server_account);
2014 }
2015
2016
2017 static void
2018 folder_refreshed_cb (ModestMailOperation *mail_op, 
2019                      TnyFolder *folder, 
2020                      gpointer user_data)
2021 {
2022         ModestMainWindow *win = NULL;
2023         GtkWidget *header_view;
2024         gboolean folder_empty = FALSE;
2025         gboolean all_marked_as_deleted = FALSE;
2026
2027         g_return_if_fail (TNY_IS_FOLDER (folder));
2028
2029         win = MODEST_MAIN_WINDOW (user_data);
2030         header_view = 
2031                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2032
2033         if (header_view) {
2034                 TnyFolder *current_folder;
2035
2036                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2037                 if (current_folder != NULL && folder != current_folder) {
2038                         g_object_unref (current_folder);
2039                         return;
2040                 }
2041                 g_object_unref (current_folder);
2042         }
2043
2044         /* Check if folder is empty and set headers view contents style */
2045         folder_empty = (tny_folder_get_all_count (folder) == 0);
2046         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
2047         if (folder_empty || all_marked_as_deleted)
2048                 modest_main_window_set_contents_style (win,
2049                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2050 }
2051
2052 void 
2053 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2054                                                TnyFolderStore *folder_store, 
2055                                                gboolean selected,
2056                                                ModestMainWindow *main_window)
2057 {
2058         ModestConf *conf;
2059         GtkWidget *header_view;
2060
2061         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2062
2063         header_view = modest_main_window_get_child_widget(main_window,
2064                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2065         if (!header_view)
2066                 return;
2067         
2068         conf = modest_runtime_get_conf ();
2069
2070         if (TNY_IS_ACCOUNT (folder_store)) {
2071                 if (selected) {
2072                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2073                         
2074                         /* Show account details */
2075                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2076                 }
2077         } else {
2078                 if (TNY_IS_FOLDER (folder_store) && selected) {
2079                         
2080                         /* Update the active account */
2081                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2082                         if (account) {
2083                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2084                                 g_object_unref (account);
2085                                 account = NULL;
2086                         }
2087
2088                         /* Set the header style by default, it could
2089                            be changed later by the refresh callback to
2090                            empty */
2091                         modest_main_window_set_contents_style (main_window, 
2092                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2093
2094                         /* Set folder on header view. This function
2095                            will call tny_folder_refresh_async so we
2096                            pass a callback that will be called when
2097                            finished. We use that callback to set the
2098                            empty view if there are no messages */
2099                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2100                                                        TNY_FOLDER (folder_store),
2101                                                        folder_refreshed_cb,
2102                                                        main_window);
2103                         
2104                         /* Restore configuration. We need to do this
2105                            *after* the set_folder because the widget
2106                            memory asks the header view about its
2107                            folder  */
2108                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2109                                                       G_OBJECT(header_view),
2110                                                       MODEST_CONF_HEADER_VIEW_KEY);
2111                 } else {
2112                         /* Update the active account */
2113                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2114                         /* Save only if we're seeing headers */
2115                         if (modest_main_window_get_contents_style (main_window) ==
2116                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2117                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2118                                                            MODEST_CONF_HEADER_VIEW_KEY);
2119                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2120                 }
2121         }
2122
2123         /* Update toolbar dimming state */
2124         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2125 }
2126
2127 void 
2128 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2129                                      ModestWindow *win)
2130 {
2131         GtkWidget *dialog;
2132         gchar *txt, *item;
2133         gboolean online;
2134
2135         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2136         
2137         online = tny_device_is_online (modest_runtime_get_device());
2138
2139         if (online) {
2140                 /* already online -- the item is simply not there... */
2141                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2142                                                  GTK_DIALOG_MODAL,
2143                                                  GTK_MESSAGE_WARNING,
2144                                                  GTK_BUTTONS_NONE,
2145                                                  _("The %s you selected cannot be found"),
2146                                                  item);
2147                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2148                 gtk_dialog_run (GTK_DIALOG(dialog));
2149         } else {
2150                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2151                                                       GTK_WINDOW (win),
2152                                                       GTK_DIALOG_MODAL,
2153                                                       _("mcen_bd_dialog_cancel"),
2154                                                       GTK_RESPONSE_REJECT,
2155                                                       _("mcen_bd_dialog_ok"),
2156                                                       GTK_RESPONSE_ACCEPT,
2157                                                       NULL);
2158                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2159                                          "Do you want to get online?"), item);
2160                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2161                                     gtk_label_new (txt), FALSE, FALSE, 0);
2162                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2163                 g_free (txt);
2164
2165                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2166                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2167                         /* TODO: Comment about why is this commented out: */
2168                         /* modest_platform_connect_and_wait (); */
2169                 }
2170         }
2171         gtk_widget_destroy (dialog);
2172 }
2173
2174 void
2175 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2176                                      ModestWindow *win)
2177 {
2178         /* g_message ("%s %s", __FUNCTION__, link); */
2179 }       
2180
2181
2182 void
2183 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2184                                         ModestWindow *win)
2185 {
2186         modest_platform_activate_uri (link);
2187 }
2188
2189 void
2190 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2191                                           ModestWindow *win)
2192 {
2193         modest_platform_show_uri_popup (link);
2194 }
2195
2196 void
2197 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2198                                              ModestWindow *win)
2199 {
2200         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2201 }
2202
2203 void
2204 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2205                                           const gchar *address,
2206                                           ModestWindow *win)
2207 {
2208         /* g_message ("%s %s", __FUNCTION__, address); */
2209 }
2210
2211 static void
2212 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2213                       TnyMsg *saved_draft,
2214                       gpointer user_data)
2215 {
2216         ModestMsgEditWindow *edit_window;
2217
2218         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2219
2220         /* If there was any error do nothing */
2221         if (modest_mail_operation_get_error (mail_op) != NULL)
2222                 return;
2223
2224         modest_msg_edit_window_set_draft (edit_window, saved_draft);
2225 }
2226
2227 void
2228 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2229 {
2230         TnyTransportAccount *transport_account;
2231         ModestMailOperation *mail_operation;
2232         MsgData *data;
2233         gchar *account_name, *from;
2234         ModestAccountMgr *account_mgr;
2235         gchar *info_text = NULL;
2236
2237         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2238         
2239         data = modest_msg_edit_window_get_msg_data (edit_window);
2240
2241         account_name = g_strdup (data->account_name);
2242         account_mgr = modest_runtime_get_account_mgr();
2243         if (!account_name)
2244                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2245         if (!account_name) 
2246                 account_name = modest_account_mgr_get_default_account (account_mgr);
2247         if (!account_name) {
2248                 g_printerr ("modest: no account found\n");
2249                 modest_msg_edit_window_free_msg_data (edit_window, data);
2250                 return;
2251         }
2252
2253         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2254                 account_name = g_strdup (data->account_name);
2255         }
2256
2257         transport_account =
2258                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2259                                       (modest_runtime_get_account_store(),
2260                                        account_name,
2261                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2262         if (!transport_account) {
2263                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2264                 g_free (account_name);
2265                 modest_msg_edit_window_free_msg_data (edit_window, data);
2266                 return;
2267         }
2268         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2269
2270         /* Create the mail operation */         
2271         mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2272         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2273
2274         modest_mail_operation_save_to_drafts (mail_operation,
2275                                               transport_account,
2276                                               data->draft_msg,
2277                                               from,
2278                                               data->to, 
2279                                               data->cc, 
2280                                               data->bcc,
2281                                               data->subject, 
2282                                               data->plain_body, 
2283                                               data->html_body,
2284                                               data->attachments,
2285                                               data->images,
2286                                               data->priority_flags,
2287                                               on_save_to_drafts_cb,
2288                                               edit_window);
2289         /* Frees */
2290         g_free (from);
2291         g_free (account_name);
2292         g_object_unref (G_OBJECT (transport_account));
2293         g_object_unref (G_OBJECT (mail_operation));
2294
2295         modest_msg_edit_window_free_msg_data (edit_window, data);
2296
2297         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2298         modest_platform_information_banner (NULL, NULL, info_text);
2299         modest_msg_edit_window_reset_modified (edit_window);
2300         g_free (info_text);
2301 }
2302
2303 /* For instance, when clicking the Send toolbar button when editing a message: */
2304 void
2305 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2306 {
2307         TnyTransportAccount *transport_account = NULL;
2308
2309         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2310
2311         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2312                 return;
2313         
2314         /* FIXME: Code added just for testing. The final version will
2315            use the send queue provided by tinymail and some
2316            classifier */
2317         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2318
2319         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2320         gchar *account_name = g_strdup (data->account_name);
2321         if (!account_name)
2322                 g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2323
2324         if (!account_name) 
2325                 account_name = modest_account_mgr_get_default_account (account_mgr);
2326                 
2327         if (!account_name) {
2328                 modest_msg_edit_window_free_msg_data (edit_window, data);
2329                 /* Run account setup wizard */
2330                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window)))
2331                         return;
2332         }
2333         
2334         /* Get the currently-active transport account for this modest account: */
2335 /*      TnyTransportAccount *transport_account = */
2336 /*              TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection */
2337 /*                                    (modest_runtime_get_account_store(), */
2338 /*                                     account_name)); */
2339         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2340                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2341                                                           (modest_runtime_get_account_store(),
2342                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2343         }
2344         
2345         if (!transport_account) {
2346                 /* Run account setup wizard */
2347                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2348                         return;
2349         }
2350         
2351         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2352
2353         /* Create the mail operation */
2354         ModestMailOperation *mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2355         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2356
2357         modest_mail_operation_send_new_mail (mail_operation,
2358                                              transport_account,
2359                                              data->draft_msg,
2360                                              from,
2361                                              data->to, 
2362                                              data->cc, 
2363                                              data->bcc,
2364                                              data->subject, 
2365                                              data->plain_body, 
2366                                              data->html_body,
2367                                              data->attachments,
2368                                              data->images,
2369                                              data->priority_flags);
2370                                              
2371         /* Free data: */
2372         g_free (from);
2373         g_free (account_name);
2374         g_object_unref (G_OBJECT (transport_account));
2375         g_object_unref (G_OBJECT (mail_operation));
2376
2377         modest_msg_edit_window_free_msg_data (edit_window, data);
2378         modest_msg_edit_window_set_sent (edit_window, TRUE);
2379
2380         /* Save settings and close the window: */
2381         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2382 }
2383
2384 void 
2385 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2386                                   ModestMsgEditWindow *window)
2387 {
2388         ModestMsgEditFormatState *format_state = NULL;
2389
2390         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2391         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2392
2393         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2394                 return;
2395
2396         format_state = modest_msg_edit_window_get_format_state (window);
2397         g_return_if_fail (format_state != NULL);
2398
2399         format_state->bold = gtk_toggle_action_get_active (action);
2400         modest_msg_edit_window_set_format_state (window, format_state);
2401         g_free (format_state);
2402         
2403 }
2404
2405 void 
2406 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2407                                      ModestMsgEditWindow *window)
2408 {
2409         ModestMsgEditFormatState *format_state = NULL;
2410
2411         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2412         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2413
2414         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2415                 return;
2416
2417         format_state = modest_msg_edit_window_get_format_state (window);
2418         g_return_if_fail (format_state != NULL);
2419
2420         format_state->italics = gtk_toggle_action_get_active (action);
2421         modest_msg_edit_window_set_format_state (window, format_state);
2422         g_free (format_state);
2423         
2424 }
2425
2426 void 
2427 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2428                                      ModestMsgEditWindow *window)
2429 {
2430         ModestMsgEditFormatState *format_state = NULL;
2431
2432         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2433         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2434
2435         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2436                 return;
2437
2438         format_state = modest_msg_edit_window_get_format_state (window);
2439         g_return_if_fail (format_state != NULL);
2440
2441         format_state->bullet = gtk_toggle_action_get_active (action);
2442         modest_msg_edit_window_set_format_state (window, format_state);
2443         g_free (format_state);
2444         
2445 }
2446
2447 void 
2448 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2449                                      GtkRadioAction *selected,
2450                                      ModestMsgEditWindow *window)
2451 {
2452         ModestMsgEditFormatState *format_state = NULL;
2453         GtkJustification value;
2454
2455         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2456
2457         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2458                 return;
2459
2460         value = gtk_radio_action_get_current_value (selected);
2461
2462         format_state = modest_msg_edit_window_get_format_state (window);
2463         g_return_if_fail (format_state != NULL);
2464
2465         format_state->justification = value;
2466         modest_msg_edit_window_set_format_state (window, format_state);
2467         g_free (format_state);
2468 }
2469
2470 void 
2471 modest_ui_actions_on_select_editor_color (GtkAction *action,
2472                                           ModestMsgEditWindow *window)
2473 {
2474         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2475         g_return_if_fail (GTK_IS_ACTION (action));
2476
2477         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2478                 return;
2479
2480         modest_msg_edit_window_select_color (window);
2481 }
2482
2483 void 
2484 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2485                                                      ModestMsgEditWindow *window)
2486 {
2487         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2488         g_return_if_fail (GTK_IS_ACTION (action));
2489
2490         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2491                 return;
2492
2493         modest_msg_edit_window_select_background_color (window);
2494 }
2495
2496 void 
2497 modest_ui_actions_on_insert_image (GtkAction *action,
2498                                    ModestMsgEditWindow *window)
2499 {
2500         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2501         g_return_if_fail (GTK_IS_ACTION (action));
2502
2503         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2504                 return;
2505
2506         modest_msg_edit_window_insert_image (window);
2507 }
2508
2509 void 
2510 modest_ui_actions_on_attach_file (GtkAction *action,
2511                                   ModestMsgEditWindow *window)
2512 {
2513         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2514         g_return_if_fail (GTK_IS_ACTION (action));
2515
2516         modest_msg_edit_window_offer_attach_file (window);
2517 }
2518
2519 void 
2520 modest_ui_actions_on_remove_attachments (GtkAction *action,
2521                                          ModestMsgEditWindow *window)
2522 {
2523         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2524         g_return_if_fail (GTK_IS_ACTION (action));
2525
2526         modest_msg_edit_window_remove_attachments (window, NULL);
2527 }
2528
2529 static void
2530 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2531                                             gpointer user_data)
2532 {
2533         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2534         const GError *error = modest_mail_operation_get_error (mail_op);
2535
2536         if(error) {
2537                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2538                                                     _("mail_in_ui_folder_create_error"));
2539         }
2540 }
2541
2542 static void
2543 modest_ui_actions_create_folder(GtkWidget *parent_window,
2544                                 GtkWidget *folder_view)
2545 {
2546         TnyFolderStore *parent_folder;
2547
2548         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2549         
2550         if (parent_folder) {
2551                 gboolean finished = FALSE;
2552                 gint result;
2553                 gchar *folder_name = NULL, *suggested_name = NULL;
2554                 const gchar *proto_str = NULL;
2555                 TnyAccount *account;
2556
2557                 if (TNY_IS_ACCOUNT (parent_folder))
2558                         account = g_object_ref (parent_folder);
2559                 else
2560                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2561                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2562
2563                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2564                     MODEST_PROTOCOL_STORE_POP) {
2565                         finished = TRUE;
2566                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2567                 }
2568                 g_object_unref (account);
2569
2570                 /* Run the new folder dialog */
2571                 while (!finished) {
2572                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2573                                                                         parent_folder,
2574                                                                         suggested_name,
2575                                                                         &folder_name);
2576
2577                         g_free (suggested_name);
2578                         suggested_name = NULL;
2579
2580                         if (result == GTK_RESPONSE_ACCEPT) {
2581                                 ModestMailOperation *mail_op;
2582                                 TnyFolder *new_folder = NULL;
2583
2584                                 mail_op  = modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2585                                                                                           modest_ui_actions_new_folder_error_handler,
2586                                                                                           parent_window, NULL);
2587
2588                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2589                                                                  mail_op);
2590                                 new_folder = modest_mail_operation_create_folder (mail_op,
2591                                                                                   parent_folder,
2592                                                                                   (const gchar *) folder_name);
2593                                 if (new_folder) {
2594                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2595                                                                           new_folder, TRUE);
2596
2597                                         g_object_unref (new_folder);
2598                                         finished = TRUE;
2599                                 }
2600                                 g_object_unref (mail_op);
2601                         } else {
2602                                 finished = TRUE;
2603                         }
2604
2605                         suggested_name = folder_name;
2606                         folder_name = NULL;
2607                 }
2608
2609                 g_object_unref (parent_folder);
2610         }
2611 }
2612
2613 void 
2614 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2615 {
2616         GtkWidget *folder_view;
2617         
2618         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2619
2620         folder_view = modest_main_window_get_child_widget (main_window,
2621                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2622         if (!folder_view)
2623                 return;
2624
2625         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2626 }
2627
2628 static void
2629 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2630                                                gpointer user_data)
2631 {
2632         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2633         const GError *error = NULL;
2634         const gchar *message = NULL;
2635         
2636         /* Get error message */
2637         error = modest_mail_operation_get_error (mail_op);
2638         if (!error)
2639                 g_return_if_reached ();
2640
2641         switch (error->code) {
2642         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2643                 message = _CS("ckdg_ib_folder_already_exists");
2644                 break;
2645         default:
2646                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2647                            error->code, error->message);
2648                 return;
2649         }
2650
2651         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2652 }
2653
2654 void 
2655 modest_ui_actions_on_rename_folder (GtkAction *action,
2656                                      ModestMainWindow *main_window)
2657 {
2658         TnyFolderStore *folder;
2659         GtkWidget *folder_view;
2660         GtkWidget *header_view; 
2661
2662         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2663
2664         folder_view = modest_main_window_get_child_widget (main_window,
2665                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2666         if (!folder_view)
2667                 return;
2668
2669         header_view = modest_main_window_get_child_widget (main_window,
2670                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2671         
2672         if (!header_view)
2673                 return;
2674
2675         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2676
2677         if (!folder)
2678                 return;
2679
2680         if (TNY_IS_FOLDER (folder)) {
2681                 gchar *folder_name;
2682                 gint response;
2683                 const gchar *current_name;
2684                 TnyFolderStore *parent;
2685                 gboolean do_rename = TRUE;
2686
2687                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2688                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2689                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2690                                                                      parent, current_name, 
2691                                                                      &folder_name);
2692                 g_object_unref (parent);
2693
2694                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2695                         do_rename = FALSE;
2696                 } else if (modest_platform_is_network_folderstore(folder) &&
2697                            !tny_device_is_online (modest_runtime_get_device())) {
2698                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2699                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2700                         g_object_unref(account);
2701                 }
2702
2703                 if (do_rename) {
2704                         ModestMailOperation *mail_op;
2705                         GtkTreeSelection *sel = NULL;
2706
2707                         mail_op = 
2708                                 modest_mail_operation_new_with_error_handling (G_OBJECT(main_window),
2709                                                                                modest_ui_actions_rename_folder_error_handler,
2710                                                                                main_window, NULL);
2711
2712                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2713                                                          mail_op);
2714
2715                         /* Clear the headers view */
2716                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2717                         gtk_tree_selection_unselect_all (sel);
2718
2719                         /* Select *after* the changes */
2720                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2721                                                           TNY_FOLDER(folder), TRUE);
2722
2723                         /* Actually rename the folder */
2724                         modest_mail_operation_rename_folder (mail_op,
2725                                                              TNY_FOLDER (folder),
2726                                                              (const gchar *) folder_name);
2727
2728                         g_object_unref (mail_op);
2729                         g_free (folder_name);
2730                 }
2731         }
2732         g_object_unref (folder);
2733 }
2734
2735 static void
2736 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2737                                                gpointer user_data)
2738 {
2739         GObject *win = modest_mail_operation_get_source (mail_op);
2740
2741         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2742                                                 _("mail_in_ui_folder_delete_error"));
2743         g_object_unref (win);
2744 }
2745
2746 static gboolean
2747 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2748 {
2749         TnyFolderStore *folder;
2750         GtkWidget *folder_view;
2751         gint response;
2752         gchar *message;
2753         gboolean do_delete = TRUE;
2754
2755         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (main_window), FALSE);
2756
2757         folder_view = modest_main_window_get_child_widget (main_window,
2758                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2759         if (!folder_view)
2760                 return FALSE;
2761
2762         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2763
2764         /* Show an error if it's an account */
2765         if (!TNY_IS_FOLDER (folder)) {
2766                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2767                                                         _("mail_in_ui_folder_delete_error"));
2768                 g_object_unref (G_OBJECT (folder));
2769                 return FALSE;
2770         }
2771
2772         /* Ask the user */      
2773         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2774                                     tny_folder_get_name (TNY_FOLDER (folder)));
2775         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2776                                                             (const gchar *) message);
2777         g_free (message);
2778
2779         if (response != GTK_RESPONSE_OK) {
2780                 do_delete = FALSE;
2781         } else if (modest_platform_is_network_folderstore(folder) &&
2782                    !tny_device_is_online (modest_runtime_get_device())) {
2783                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2784                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2785                 g_object_unref(account);
2786         }
2787
2788         if (do_delete) {
2789                 ModestMailOperation *mail_op;
2790                 GtkTreeSelection *sel;
2791
2792                 /* Unselect the folder before deleting it to free the headers */
2793                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2794                 gtk_tree_selection_unselect_all (sel);
2795
2796                 /* Create the mail operation */
2797                 mail_op =
2798                         modest_mail_operation_new_with_error_handling (G_OBJECT(main_window),
2799                                                                        modest_ui_actions_delete_folder_error_handler,
2800                                                                        NULL, NULL);
2801
2802                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2803                                                  mail_op);
2804                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2805                 g_object_unref (G_OBJECT (mail_op));
2806         }
2807
2808         g_object_unref (G_OBJECT (folder));
2809
2810         return do_delete;
2811 }
2812
2813 void 
2814 modest_ui_actions_on_delete_folder (GtkAction *action,
2815                                      ModestMainWindow *main_window)
2816 {
2817         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2818
2819         delete_folder (main_window, FALSE);
2820 }
2821
2822 void 
2823 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2824 {
2825         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2826         
2827         delete_folder (main_window, TRUE);
2828 }
2829
2830
2831 static void
2832 show_error (GtkWidget *parent_widget, const gchar* text)
2833 {
2834         hildon_banner_show_information(parent_widget, NULL, text);
2835         
2836 #if 0
2837         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2838         /*
2839           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2840           (GtkDialogFlags)0,
2841           GTK_MESSAGE_ERROR,
2842           GTK_BUTTONS_OK,
2843           text ));
2844         */
2845                  
2846         gtk_dialog_run (dialog);
2847         gtk_widget_destroy (GTK_WIDGET (dialog));
2848 #endif
2849 }
2850
2851 void
2852 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2853                                          const gchar* server_account_name,
2854                                          gchar **username,
2855                                          gchar **password, 
2856                                          gboolean *cancel, 
2857                                          gboolean *remember,
2858                                          ModestMainWindow *main_window)
2859 {
2860         g_return_if_fail(server_account_name);
2861         
2862         /* Initalize output parameters: */
2863         if (cancel)
2864                 *cancel = FALSE;
2865                 
2866         if (remember)
2867                 *remember = TRUE;
2868                 
2869 #ifdef MODEST_PLATFORM_MAEMO
2870         /* Maemo uses a different (awkward) button order,
2871          * It should probably just use gtk_alternative_dialog_button_order ().
2872          */
2873         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2874                                               NULL,
2875                                               GTK_DIALOG_MODAL,
2876                                               _("mcen_bd_dialog_ok"),
2877                                               GTK_RESPONSE_ACCEPT,
2878                                               _("mcen_bd_dialog_cancel"),
2879                                               GTK_RESPONSE_REJECT,
2880                                               NULL);
2881 #else
2882         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2883                                               NULL,
2884                                               GTK_DIALOG_MODAL,
2885                                               GTK_STOCK_CANCEL,
2886                                               GTK_RESPONSE_REJECT,
2887                                               GTK_STOCK_OK,
2888                                               GTK_RESPONSE_ACCEPT,
2889                                               NULL);
2890 #endif /* MODEST_PLATFORM_MAEMO */
2891
2892         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2893         
2894         gchar *server_name = modest_account_mgr_get_server_account_hostname (
2895                 modest_runtime_get_account_mgr(), server_account_name);
2896         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2897                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2898                 if (cancel)
2899                         *cancel = TRUE;
2900                 return;
2901         }
2902         
2903         /* This causes a warning because the logical ID has no %s in it, 
2904          * though the translation does, but there is not much we can do about that: */
2905         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2906         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2907                             FALSE, FALSE, 0);
2908         g_free (txt);
2909         g_free (server_name);
2910         server_name = NULL;
2911
2912         /* username: */
2913         gchar *initial_username = modest_account_mgr_get_server_account_username (
2914                 modest_runtime_get_account_mgr(), server_account_name);
2915         
2916         GtkWidget *entry_username = gtk_entry_new ();
2917         if (initial_username)
2918                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2919         /* Dim this if a connection has ever succeeded with this username,
2920          * as per the UI spec: */
2921         const gboolean username_known = 
2922                 modest_account_mgr_get_server_account_username_has_succeeded(
2923                         modest_runtime_get_account_mgr(), server_account_name);
2924         gtk_widget_set_sensitive (entry_username, !username_known);
2925         
2926 #ifdef MODEST_PLATFORM_MAEMO
2927         /* Auto-capitalization is the default, so let's turn it off: */
2928         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2929         
2930         /* Create a size group to be used by all captions.
2931          * Note that HildonCaption does not create a default size group if we do not specify one.
2932          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2933         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2934         
2935         GtkWidget *caption = hildon_caption_new (sizegroup, 
2936                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2937         gtk_widget_show (entry_username);
2938         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2939                 FALSE, FALSE, MODEST_MARGIN_HALF);
2940         gtk_widget_show (caption);
2941 #else 
2942         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2943                             TRUE, FALSE, 0);
2944 #endif /* MODEST_PLATFORM_MAEMO */      
2945                             
2946         /* password: */
2947         GtkWidget *entry_password = gtk_entry_new ();
2948         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2949         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2950         
2951 #ifdef MODEST_PLATFORM_MAEMO
2952         /* Auto-capitalization is the default, so let's turn it off: */
2953         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2954                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2955         
2956         caption = hildon_caption_new (sizegroup, 
2957                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2958         gtk_widget_show (entry_password);
2959         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2960                 FALSE, FALSE, MODEST_MARGIN_HALF);
2961         gtk_widget_show (caption);
2962         g_object_unref (sizegroup);
2963 #else 
2964         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2965                             TRUE, FALSE, 0);
2966 #endif /* MODEST_PLATFORM_MAEMO */      
2967
2968         if (initial_username != NULL)
2969                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
2970                                 
2971 /* This is not in the Maemo UI spec:
2972         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2973         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2974                             TRUE, FALSE, 0);
2975 */
2976
2977         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2978         
2979         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2980                 if (username) {
2981                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2982                         
2983                         modest_account_mgr_set_server_account_username (
2984                                  modest_runtime_get_account_mgr(), server_account_name, 
2985                                  *username);
2986                                  
2987                         const gboolean username_was_changed = 
2988                                 (strcmp (*username, initial_username) != 0);
2989                         if (username_was_changed) {
2990                                 g_warning ("%s: tinymail does not yet support changing the "
2991                                         "username in the get_password() callback.\n", __FUNCTION__);
2992                         }
2993                 }
2994                         
2995                 if (password) {
2996                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2997                         
2998                         /* We do not save the password in the configuration, 
2999                          * because this function is only called for passwords that should 
3000                          * not be remembered:
3001                         modest_server_account_set_password (
3002                                  modest_runtime_get_account_mgr(), server_account_name, 
3003                                  *password);
3004                         */
3005                 }
3006                 
3007                 if (cancel)
3008                         *cancel   = FALSE;
3009                         
3010         } else {
3011                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
3012                 
3013                 if (username)
3014                         *username = NULL;
3015                         
3016                 if (password)
3017                         *password = NULL;
3018                         
3019                 if (cancel)
3020                         *cancel   = TRUE;
3021         }
3022
3023 /* This is not in the Maemo UI spec:
3024         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3025                 *remember = TRUE;
3026         else
3027                 *remember = FALSE;
3028 */
3029
3030         gtk_widget_destroy (dialog);
3031         
3032         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3033 }
3034
3035 void
3036 modest_ui_actions_on_cut (GtkAction *action,
3037                           ModestWindow *window)
3038 {
3039         GtkWidget *focused_widget;
3040         GtkClipboard *clipboard;
3041
3042         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3043         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3044         if (GTK_IS_EDITABLE (focused_widget)) {
3045                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3046                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3047                 gtk_clipboard_store (clipboard);
3048         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3049                 GtkTextBuffer *buffer;
3050
3051                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3052                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3053                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3054                 gtk_clipboard_store (clipboard);
3055         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3056                 TnyList *header_list = modest_header_view_get_selected_headers (
3057                                 MODEST_HEADER_VIEW (focused_widget));
3058                 gboolean continue_download = FALSE;
3059                 gint num_of_unc_msgs;
3060
3061                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3062
3063                 if (num_of_unc_msgs) {
3064                         TnyAccount *account = get_account_from_header_list (header_list);
3065                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3066                         g_object_unref (account);
3067                 }
3068
3069                 if (num_of_unc_msgs == 0 || continue_download) {
3070 /*                      modest_platform_information_banner (
3071                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3072                         modest_header_view_cut_selection (
3073                                         MODEST_HEADER_VIEW (focused_widget));
3074                 }
3075
3076                 g_object_unref (header_list);
3077         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3078                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3079         }
3080 }
3081
3082 void
3083 modest_ui_actions_on_copy (GtkAction *action,
3084                            ModestWindow *window)
3085 {
3086         GtkClipboard *clipboard;
3087         GtkWidget *focused_widget;
3088         gboolean copied = TRUE;
3089
3090         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3091         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3092
3093         if (GTK_IS_LABEL (focused_widget)) {
3094                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3095                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3096                 gtk_clipboard_store (clipboard);
3097         } else if (GTK_IS_EDITABLE (focused_widget)) {
3098                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3099                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3100                 gtk_clipboard_store (clipboard);
3101         } else if (GTK_IS_HTML (focused_widget)) {
3102                 gtk_html_copy (GTK_HTML (focused_widget));
3103                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3104                 gtk_clipboard_store (clipboard);
3105         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3106                 GtkTextBuffer *buffer;
3107                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3108                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3109                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3110                 gtk_clipboard_store (clipboard);
3111         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3112                 TnyList *header_list = modest_header_view_get_selected_headers (
3113                                 MODEST_HEADER_VIEW (focused_widget));
3114                 gboolean continue_download = FALSE;
3115                 gint num_of_unc_msgs;
3116
3117                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3118
3119                 if (num_of_unc_msgs) {
3120                         TnyAccount *account = get_account_from_header_list (header_list);
3121                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3122                         g_object_unref (account);
3123                 }
3124
3125                 if (num_of_unc_msgs == 0 || continue_download) {
3126                         modest_platform_information_banner (
3127                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3128                         modest_header_view_copy_selection (
3129                                         MODEST_HEADER_VIEW (focused_widget));
3130                 } else
3131                         copied = FALSE;
3132
3133                 g_object_unref (header_list);
3134
3135         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3136                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3137         }
3138
3139         /* Show information banner if there was a copy to clipboard */
3140         if(copied)
3141                 modest_platform_information_banner (
3142                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3143 }
3144
3145 void
3146 modest_ui_actions_on_undo (GtkAction *action,
3147                            ModestWindow *window)
3148 {
3149         ModestEmailClipboard *clipboard = NULL;
3150
3151         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3152                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3153         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3154                 /* Clear clipboard source */
3155                 clipboard = modest_runtime_get_email_clipboard ();
3156                 modest_email_clipboard_clear (clipboard);               
3157         }
3158         else {
3159                 g_return_if_reached ();
3160         }
3161 }
3162
3163 void
3164 modest_ui_actions_on_redo (GtkAction *action,
3165                            ModestWindow *window)
3166 {
3167         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3168                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3169         }
3170         else {
3171                 g_return_if_reached ();
3172         }
3173 }
3174
3175
3176 static void
3177 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3178 {
3179         /* destroy information note */
3180         gtk_widget_destroy (GTK_WIDGET(user_data));
3181 }
3182
3183
3184 static void
3185 paste_as_attachment_free (gpointer data)
3186 {
3187         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3188
3189         gtk_widget_destroy (helper->banner);
3190         g_object_unref (helper->banner);
3191         g_free (helper);
3192 }
3193
3194 static void
3195 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3196                             TnyHeader *header,
3197                             TnyMsg *msg,
3198                             gpointer userdata)
3199 {
3200         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3201         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3202
3203         if (msg == NULL)
3204                 return;
3205
3206         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3207         
3208 }
3209
3210 void
3211 modest_ui_actions_on_paste (GtkAction *action,
3212                             ModestWindow *window)
3213 {
3214         GtkWidget *focused_widget = NULL;
3215         GtkWidget *inf_note = NULL;
3216         ModestMailOperation *mail_op = NULL;
3217
3218         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3219         if (GTK_IS_EDITABLE (focused_widget)) {
3220                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3221         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3222                 ModestEmailClipboard *e_clipboard = NULL;
3223                 e_clipboard = modest_runtime_get_email_clipboard ();
3224                 if (modest_email_clipboard_cleared (e_clipboard)) {
3225                         GtkTextBuffer *buffer;
3226                         GtkClipboard *clipboard;
3227
3228                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3229                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3230                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3231                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3232                         ModestMailOperation *mail_op;
3233                         TnyFolder *src_folder;
3234                         TnyList *data;
3235                         gboolean delete;
3236                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3237                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3238                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3239                                                                            _CS("ckct_nw_pasting"));
3240                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3241                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3242                         if (helper->banner != NULL) {
3243                                 g_object_ref (G_OBJECT (helper->banner));
3244                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3245                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3246                         }
3247
3248                         if (data != NULL) {
3249                                 modest_mail_operation_get_msgs_full (mail_op, 
3250                                                                      data,
3251                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3252                                                                      helper,
3253                                                                      paste_as_attachment_free);
3254                         }
3255                 }
3256         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3257                 ModestEmailClipboard *clipboard = NULL;
3258                 TnyFolder *src_folder = NULL;
3259                 TnyFolderStore *folder_store = NULL;
3260                 TnyList *data = NULL;           
3261                 gboolean delete = FALSE;
3262                 
3263                 /* Check clipboard source */
3264                 clipboard = modest_runtime_get_email_clipboard ();
3265                 if (modest_email_clipboard_cleared (clipboard)) 
3266                         return;
3267                 
3268                 /* Get elements to paste */
3269                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3270
3271                 /* Create a new mail operation */
3272                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3273                 
3274                 /* Get destination folder */
3275                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3276
3277                 /* transfer messages  */
3278                 if (data != NULL) {
3279                         gint response = 0;
3280
3281                         /* Ask for user confirmation */
3282                         response = 
3283                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3284                                                                              TNY_FOLDER (folder_store), 
3285                                                                              delete,
3286                                                                              data);
3287                         
3288                         if (response == GTK_RESPONSE_OK) {
3289                                 /* Launch notification */
3290                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3291                                                                              _CS("ckct_nw_pasting"));
3292                                 if (inf_note != NULL)  {
3293                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3294                                         gtk_widget_show (GTK_WIDGET(inf_note));
3295                                 }
3296
3297                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3298                                 modest_mail_operation_xfer_msgs (mail_op, 
3299                                                                  data,
3300                                                                  TNY_FOLDER (folder_store),
3301                                                                  delete,
3302                                                                  destroy_information_note,
3303                                                                  inf_note);                             
3304                         } else {
3305                                 g_object_unref (mail_op);
3306                         }
3307                         
3308                 } else if (src_folder != NULL) {                        
3309                         /* Launch notification */
3310                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3311                                                                      _CS("ckct_nw_pasting"));
3312                         if (inf_note != NULL)  {
3313                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3314                                 gtk_widget_show (GTK_WIDGET(inf_note));
3315                         }
3316                         
3317                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3318                         modest_mail_operation_xfer_folder (mail_op, 
3319                                                            src_folder,
3320                                                            folder_store,
3321                                                            delete,
3322                                                            destroy_information_note,
3323                                                            inf_note);
3324                 }
3325
3326                 /* Free */
3327                 if (data != NULL) 
3328                         g_object_unref (data);
3329                 if (src_folder != NULL) 
3330                         g_object_unref (src_folder);
3331                 if (folder_store != NULL) 
3332                         g_object_unref (folder_store);
3333         }
3334 }
3335
3336
3337 void
3338 modest_ui_actions_on_select_all (GtkAction *action,
3339                                  ModestWindow *window)
3340 {
3341         GtkWidget *focused_widget;
3342
3343         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3344         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3345                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3346         } else if (GTK_IS_LABEL (focused_widget)) {
3347                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3348         } else if (GTK_IS_EDITABLE (focused_widget)) {
3349                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3350         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3351                 GtkTextBuffer *buffer;
3352                 GtkTextIter start, end;
3353
3354                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3355                 gtk_text_buffer_get_start_iter (buffer, &start);
3356                 gtk_text_buffer_get_end_iter (buffer, &end);
3357                 gtk_text_buffer_select_range (buffer, &start, &end);
3358         } else if (GTK_IS_HTML (focused_widget)) {
3359                 gtk_html_select_all (GTK_HTML (focused_widget));
3360         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3361                 GtkWidget *header_view = focused_widget;
3362                 GtkTreeSelection *selection = NULL;
3363                 
3364                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3365                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3366                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3367                 }
3368                                 
3369                 /* Disable window dimming management */
3370                 modest_window_disable_dimming (MODEST_WINDOW(window));
3371                 
3372                 /* Select all messages */
3373                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3374                 gtk_tree_selection_select_all (selection);
3375
3376                 /* Set focuse on header view */
3377                 gtk_widget_grab_focus (header_view);
3378
3379
3380                 /* Enable window dimming management */
3381                 modest_window_enable_dimming (MODEST_WINDOW(window));
3382                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3383         }
3384
3385 }
3386
3387 void
3388 modest_ui_actions_on_mark_as_read (GtkAction *action,
3389                                    ModestWindow *window)
3390 {       
3391         g_return_if_fail (MODEST_IS_WINDOW(window));
3392                 
3393         /* Mark each header as read */
3394         do_headers_action (window, headers_action_mark_as_read, NULL);
3395 }
3396
3397 void
3398 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3399                                      ModestWindow *window)
3400 {       
3401         g_return_if_fail (MODEST_IS_WINDOW(window));
3402                 
3403         /* Mark each header as read */
3404         do_headers_action (window, headers_action_mark_as_unread, NULL);
3405 }
3406
3407 void
3408 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3409                                   GtkRadioAction *selected,
3410                                   ModestWindow *window)
3411 {
3412         gint value;
3413
3414         value = gtk_radio_action_get_current_value (selected);
3415         if (MODEST_IS_WINDOW (window)) {
3416                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3417         }
3418 }
3419
3420 void     
3421 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3422                                                GtkRadioAction *selected,
3423                                                ModestWindow *window)
3424 {
3425         TnyHeaderFlags flags;
3426         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3427
3428         flags = gtk_radio_action_get_current_value (selected);
3429         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3430 }
3431
3432 void     
3433 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3434                                                   GtkRadioAction *selected,
3435                                                   ModestWindow *window)
3436 {
3437         gint file_format;
3438
3439         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3440
3441         file_format = gtk_radio_action_get_current_value (selected);
3442         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3443 }
3444
3445
3446 void     
3447 modest_ui_actions_on_zoom_plus (GtkAction *action,
3448                                 ModestWindow *window)
3449 {
3450         g_return_if_fail (MODEST_IS_WINDOW (window));
3451
3452         modest_window_zoom_plus (MODEST_WINDOW (window));
3453 }
3454
3455 void     
3456 modest_ui_actions_on_zoom_minus (GtkAction *action,
3457                                  ModestWindow *window)
3458 {
3459         g_return_if_fail (MODEST_IS_WINDOW (window));
3460
3461         modest_window_zoom_minus (MODEST_WINDOW (window));
3462 }
3463
3464 void     
3465 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3466                                            ModestWindow *window)
3467 {
3468         ModestWindowMgr *mgr;
3469         gboolean fullscreen, active;
3470         g_return_if_fail (MODEST_IS_WINDOW (window));
3471
3472         mgr = modest_runtime_get_window_mgr ();
3473
3474         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3475         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3476
3477         if (active != fullscreen) {
3478                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3479                 gtk_window_present (GTK_WINDOW (window));
3480         }
3481 }
3482
3483 void
3484 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3485                                         ModestWindow *window)
3486 {
3487         ModestWindowMgr *mgr;
3488         gboolean fullscreen;
3489
3490         g_return_if_fail (MODEST_IS_WINDOW (window));
3491
3492         mgr = modest_runtime_get_window_mgr ();
3493         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3494         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3495
3496         gtk_window_present (GTK_WINDOW (window));
3497 }
3498
3499 /* 
3500  * Used by modest_ui_actions_on_details to call do_headers_action 
3501  */
3502 static void
3503 headers_action_show_details (TnyHeader *header, 
3504                              ModestWindow *window,
3505                              gpointer user_data)
3506
3507 {
3508         GtkWidget *dialog;
3509         
3510         /* Create dialog */
3511         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3512
3513         /* Run dialog */
3514         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3515         gtk_widget_show_all (dialog);
3516         gtk_dialog_run (GTK_DIALOG (dialog));
3517
3518         gtk_widget_destroy (dialog);
3519 }
3520
3521 /*
3522  * Show the folder details in a ModestDetailsDialog widget
3523  */
3524 static void
3525 show_folder_details (TnyFolder *folder, 
3526                      GtkWindow *window)
3527 {
3528         GtkWidget *dialog;
3529         
3530         /* Create dialog */
3531         dialog = modest_details_dialog_new_with_folder (window, folder);
3532
3533         /* Run dialog */
3534         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3535         gtk_widget_show_all (dialog);
3536         gtk_dialog_run (GTK_DIALOG (dialog));
3537
3538         gtk_widget_destroy (dialog);
3539 }
3540
3541 /*
3542  * Show the header details in a ModestDetailsDialog widget
3543  */
3544 void     
3545 modest_ui_actions_on_details (GtkAction *action, 
3546                               ModestWindow *win)
3547 {
3548         TnyList * headers_list;
3549         TnyIterator *iter;
3550         TnyHeader *header;              
3551
3552         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3553                 TnyMsg *msg;
3554
3555                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3556                 if (!msg)
3557                         return;
3558                 g_object_unref (msg);           
3559
3560                 headers_list = get_selected_headers (win);
3561                 if (!headers_list)
3562                         return;
3563
3564                 iter = tny_list_create_iterator (headers_list);
3565
3566                 header = TNY_HEADER (tny_iterator_get_current (iter));
3567                 if (header) {
3568                         headers_action_show_details (header, win, NULL);
3569                         g_object_unref (header);
3570                 }
3571
3572                 g_object_unref (iter);
3573                 g_object_unref (headers_list);
3574
3575         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3576                 GtkWidget *folder_view, *header_view;
3577
3578                 /* Check which widget has the focus */
3579                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3580                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3581                 if (gtk_widget_is_focus (folder_view)) {
3582                         TnyFolderStore *folder_store
3583                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3584                         if (!folder_store) {
3585                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3586                                 return; 
3587                         }
3588                         /* Show only when it's a folder */
3589                         /* This function should not be called for account items, 
3590                          * because we dim the menu item for them. */
3591                         if (TNY_IS_FOLDER (folder_store)) {
3592                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3593                         }
3594
3595                         g_object_unref (folder_store);
3596
3597                 } else {
3598                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3599                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3600                         /* Show details of each header */
3601                         do_headers_action (win, headers_action_show_details, header_view);
3602                 }
3603         }
3604 }
3605
3606 void     
3607 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3608                                      ModestMsgEditWindow *window)
3609 {
3610         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3611
3612         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3613 }
3614
3615 void     
3616 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3617                                       ModestMsgEditWindow *window)
3618 {
3619         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3620
3621         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3622 }
3623
3624 void
3625 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3626                                        ModestMainWindow *main_window)
3627 {
3628         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3629
3630         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3631                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3632         else
3633                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3634 }
3635
3636 void 
3637 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3638                                      ModestWindow *window)
3639 {
3640         gboolean active, fullscreen = FALSE;
3641         ModestWindowMgr *mgr;
3642
3643         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3644
3645         /* Check if we want to toggle the toolbar vuew in fullscreen
3646            or normal mode */
3647         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3648                      "ViewShowToolbarFullScreen")) {
3649                 fullscreen = TRUE;
3650         }
3651
3652         /* Toggle toolbar */
3653         mgr = modest_runtime_get_window_mgr ();
3654         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3655 }
3656
3657 void     
3658 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3659                                            ModestMsgEditWindow *window)
3660 {
3661         modest_msg_edit_window_select_font (window);
3662 }
3663
3664 void
3665 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3666                                                   const gchar *display_name,
3667                                                   GtkWindow *window)
3668 {
3669         /* Do not change the application name if the widget has not
3670            the focus. This callback could be called even if the folder
3671            view has not the focus, because the handled signal could be
3672            emitted when the folder view is redrawn */
3673         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3674                 if (display_name)
3675                         gtk_window_set_title (window, display_name);
3676                 else
3677                         gtk_window_set_title (window, " ");
3678         }
3679 }
3680
3681 void
3682 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3683 {
3684         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3685         modest_msg_edit_window_select_contacts (window);
3686 }
3687
3688 void
3689 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3690 {
3691         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3692         modest_msg_edit_window_check_names (window, FALSE);
3693 }
3694
3695 static void
3696 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3697 {
3698         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3699                                          GTK_WIDGET (user_data));
3700 }
3701
3702 /*
3703  * This function is used to track changes in the selection of the
3704  * folder view that is inside the "move to" dialog to enable/disable
3705  * the OK button because we do not want the user to select a disallowed
3706  * destination for a folder.
3707  * The user also not desired to be able to use NEW button on items where
3708  * folder creation is not possibel.
3709  */
3710 static void
3711 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3712                                             TnyFolderStore *folder_store,
3713                                             gboolean selected,
3714                                             gpointer user_data)
3715 {
3716         GtkWidget *dialog = NULL;
3717         GtkWidget *ok_button = NULL, *new_button = NULL;
3718         GList *children = NULL;
3719         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3720         gboolean moving_folder = FALSE;
3721         gboolean is_local_account = TRUE;
3722         GtkWidget *folder_view = NULL;
3723         ModestTnyFolderRules rules;
3724
3725         if (!selected)
3726                 return;
3727
3728         /* Get the OK button */
3729         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3730         if (!dialog)
3731                 return;
3732
3733         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3734         ok_button = GTK_WIDGET (children->next->next->data);
3735         new_button = GTK_WIDGET (children->next->data);
3736         g_list_free (children);
3737
3738         /* check if folder_store is an remote account */
3739         if (TNY_IS_ACCOUNT (folder_store)) {
3740                 TnyAccount *local_account = NULL;
3741                 TnyAccount *mmc_account = NULL;
3742                 ModestTnyAccountStore *account_store = NULL;
3743
3744                 account_store = modest_runtime_get_account_store ();
3745                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3746                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
3747
3748                 if ((gpointer) local_account != (gpointer) folder_store &&
3749                     (gpointer) mmc_account != (gpointer) folder_store) {
3750                         is_local_account = FALSE;
3751                         /* New button should be dimmed on remote
3752                            account root */
3753                         new_sensitive = FALSE;
3754                 }
3755                 g_object_unref (local_account);
3756         }
3757
3758         /* Check the target folder rules */
3759         if (TNY_IS_FOLDER (folder_store)) {
3760                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3761                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3762                         ok_sensitive = FALSE;
3763                         new_sensitive = FALSE;
3764                         goto end;
3765                 }
3766         }
3767
3768         /* Check if we're moving a folder */
3769         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3770                 /* Get the widgets */
3771                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3772                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3773                 if (gtk_widget_is_focus (folder_view))
3774                         moving_folder = TRUE;
3775         }
3776
3777         if (moving_folder) {
3778                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3779
3780                 /* Get the folder to move */
3781                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3782                 
3783                 /* Check that we're not moving to the same folder */
3784                 if (TNY_IS_FOLDER (moved_folder)) {
3785                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3786                         if (parent == folder_store)
3787                                 ok_sensitive = FALSE;
3788                         g_object_unref (parent);
3789                 } 
3790
3791                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3792                         /* Do not allow to move to an account unless it's the
3793                            local folders account */
3794                         if (!is_local_account)
3795                                 ok_sensitive = FALSE;
3796                 } 
3797
3798                 if (ok_sensitive && (moved_folder == folder_store)) {
3799                         /* Do not allow to move to itself */
3800                         ok_sensitive = FALSE;
3801                 }
3802                 g_object_unref (moved_folder);
3803         } else {
3804                 TnyHeader *header = NULL;
3805                 TnyFolder *src_folder = NULL;
3806
3807                 /* Moving a message */
3808                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3809                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3810                         src_folder = tny_header_get_folder (header);
3811                         g_object_unref (header);
3812                 } else {
3813                         src_folder = 
3814                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3815                 }
3816
3817                 /* Do not allow to move the msg to the same folder */
3818                 /* Do not allow to move the msg to an account */
3819                 if ((gpointer) src_folder == (gpointer) folder_store ||
3820                     TNY_IS_ACCOUNT (folder_store))
3821                         ok_sensitive = FALSE;
3822                 g_object_unref (src_folder);
3823         }
3824
3825  end:
3826         /* Set sensitivity of the OK button */
3827         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3828         /* Set sensitivity of the NEW button */
3829         gtk_widget_set_sensitive (new_button, new_sensitive);
3830 }
3831
3832 static GtkWidget*
3833 create_move_to_dialog (GtkWindow *win,
3834                        GtkWidget *folder_view,
3835                        GtkWidget **tree_view)
3836 {
3837         GtkWidget *dialog, *scroll;
3838         GtkWidget *new_button;
3839
3840         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3841                                               GTK_WINDOW (win),
3842                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3843                                               NULL);
3844
3845         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3846         /* We do this manually so GTK+ does not associate a response ID for
3847          * the button. */
3848         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3849         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3850         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3851
3852         /* Create scrolled window */
3853         scroll = gtk_scrolled_window_new (NULL, NULL);
3854         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3855                                          GTK_POLICY_AUTOMATIC,
3856                                          GTK_POLICY_AUTOMATIC);
3857
3858         /* Create folder view */
3859         *tree_view = modest_platform_create_folder_view (NULL);
3860
3861         /* Track changes in the selection to
3862          * disable the OK button whenever "Move to" is not possible
3863          * disbale NEW button whenever New is not possible */
3864         g_signal_connect (*tree_view,
3865                           "folder_selection_changed",
3866                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3867                           win);
3868
3869         /* Listen to clicks on New button */
3870         g_signal_connect (G_OBJECT (new_button), 
3871                           "clicked", 
3872                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3873                           *tree_view);
3874
3875         /* It could happen that we're trying to move a message from a
3876            window (msg window for example) after the main window was
3877            closed, so we can not just get the model of the folder
3878            view */
3879         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3880                 const gchar *visible_id = NULL;
3881
3882                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3883                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3884                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3885                                                MODEST_FOLDER_VIEW(*tree_view));
3886
3887                 visible_id = 
3888                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3889
3890                 /* Show the same account than the one that is shown in the main window */
3891                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3892                                                                              visible_id);
3893         } else {
3894                 const gchar *active_account_name = NULL;
3895                 ModestAccountMgr *mgr = NULL;
3896                 ModestAccountData *acc_data = NULL;
3897
3898                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3899                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3900                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3901                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3902
3903                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3904                 mgr = modest_runtime_get_account_mgr ();
3905                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3906
3907                 /* Set the new visible & active account */
3908                 if (acc_data && acc_data->store_account) { 
3909                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3910                                                                                      acc_data->store_account->account_name);
3911                         modest_account_mgr_free_account_data (mgr, acc_data);
3912                 }
3913         }
3914
3915         /* Hide special folders */
3916         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3917         
3918         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3919
3920         /* Add scroll to dialog */
3921         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3922                             scroll, TRUE, TRUE, 0);
3923
3924         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3925         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3926
3927         return dialog;
3928 }
3929
3930 /*
3931  * Returns TRUE if at least one of the headers of the list belongs to
3932  * a message that has been fully retrieved.
3933  */
3934 #if 0 /* no longer in use. delete in 2007.10 */
3935 static gboolean
3936 has_retrieved_msgs (TnyList *list)
3937 {
3938         TnyIterator *iter;
3939         gboolean found = FALSE;
3940
3941         iter = tny_list_create_iterator (list);
3942         while (!tny_iterator_is_done (iter) && !found) {
3943                 TnyHeader *header;
3944                 TnyHeaderFlags flags = 0;
3945
3946                 header = TNY_HEADER (tny_iterator_get_current (iter));
3947                 if (header) {
3948                         flags = tny_header_get_flags (header);
3949                         if (flags & TNY_HEADER_FLAG_CACHED)
3950 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3951                                 found = TRUE;
3952
3953                         g_object_unref (header);
3954                 }
3955
3956                 if (!found)
3957                         tny_iterator_next (iter);
3958         }
3959         g_object_unref (iter);
3960
3961         return found;
3962 }
3963 #endif /* 0 */
3964
3965
3966 /*
3967  * Shows a confirmation dialog to the user when we're moving messages
3968  * from a remote server to the local storage. Returns the dialog
3969  * response. If it's other kind of movement then it always returns
3970  * GTK_RESPONSE_OK
3971  *
3972  * This one is used by the next functions:
3973  *      modest_ui_actions_on_paste                      - commented out
3974  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3975  */
3976 gint
3977 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
3978                                              TnyFolder *dest_folder,
3979                                              gboolean delete,
3980                                              TnyList *headers)
3981 {
3982         gint response = GTK_RESPONSE_OK;
3983         TnyAccount *account = NULL;
3984         TnyFolder *src_folder = NULL;
3985         TnyIterator *iter = NULL;
3986         TnyHeader *header = NULL;
3987
3988         /* return with OK if the destination is a remote folder */
3989         if (modest_tny_folder_is_remote_folder (dest_folder))
3990                 return GTK_RESPONSE_OK;
3991
3992         /* Get source folder */
3993         iter = tny_list_create_iterator (headers);
3994         header = TNY_HEADER (tny_iterator_get_current (iter));
3995         if (header) {
3996                 src_folder = tny_header_get_folder (header);
3997                 g_object_unref (header);
3998         }
3999         g_object_unref (iter);
4000
4001         /* if no src_folder, message may be an attahcment */
4002         if (src_folder == NULL) 
4003                 return GTK_RESPONSE_CANCEL;
4004
4005         /* If the source is a local or MMC folder */
4006         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4007                 g_object_unref (src_folder);
4008                 return GTK_RESPONSE_OK;
4009         }
4010
4011         /* Get the account */
4012         account = tny_folder_get_account (src_folder);
4013
4014         /* now if offline we ask the user */
4015         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4016                 response = GTK_RESPONSE_OK;
4017         else
4018                 response = GTK_RESPONSE_CANCEL;
4019
4020         /* Frees */
4021         g_object_unref (src_folder);
4022         g_object_unref (account);
4023
4024         return response;
4025 }
4026
4027
4028
4029 static void
4030 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
4031 {
4032         MoveToHelper *helper = (MoveToHelper *) user_data;
4033
4034         /* Note that the operation could have failed, in that case do
4035            nothing */
4036         if (modest_mail_operation_get_status (mail_op) == 
4037             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4038
4039                 GObject *object = modest_mail_operation_get_source (mail_op);
4040                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4041                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4042
4043                         if (!modest_msg_view_window_select_next_message (self))
4044                                 if (!modest_msg_view_window_select_previous_message (self))
4045                                         /* No more messages to view, so close this window */
4046                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4047                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4048                         GtkWidget *header_view;
4049                         GtkTreePath *path;
4050                         GtkTreeSelection *sel;
4051
4052                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4053                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4054                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4055                         path = gtk_tree_row_reference_get_path (helper->reference);
4056                         gtk_tree_selection_select_path (sel, path);
4057                         gtk_tree_path_free (path);
4058                 }
4059                 g_object_unref (object);
4060         }
4061
4062         /* Close the "Pasting" information banner */
4063         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4064         if (helper->reference != NULL)
4065                 gtk_tree_row_reference_free (helper->reference);
4066         g_free (helper);
4067 }
4068
4069 void
4070 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4071                                              gpointer user_data)
4072 {
4073         ModestWindow *main_window = NULL;
4074         GObject *win = NULL;
4075         const GError *error = NULL;
4076         const gchar *message = NULL;
4077         
4078         /* Get error message */
4079         error = modest_mail_operation_get_error (mail_op);
4080         if (error != NULL && error->message != NULL) {
4081                 message = error->message;
4082         } else {
4083                 message = _("mail_in_ui_folder_move_target_error");
4084         }
4085         
4086         /* Disable next automatic folder selection */
4087         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4088                                                          FALSE); /* don't create */
4089         if (main_window) {
4090                 GtkWidget *folder_view = NULL;
4091         
4092                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4093                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4094                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4095                 
4096                 if (user_data && TNY_IS_FOLDER (user_data)) {
4097                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4098                                                           TNY_FOLDER (user_data), FALSE);
4099                 }
4100         }
4101
4102         /* Show notification dialog */
4103         win = modest_mail_operation_get_source (mail_op);
4104         if (G_IS_OBJECT (win)) {
4105                 modest_platform_run_information_dialog (GTK_WINDOW (win), message);
4106                 g_object_unref (win);
4107         }
4108 }
4109
4110 void
4111 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4112                                               gpointer user_data)
4113 {
4114         GObject *win = modest_mail_operation_get_source (mail_op);
4115         const GError *error = modest_mail_operation_get_error (mail_op);
4116
4117         g_return_if_fail (error != NULL);
4118         if (error->message != NULL)             
4119                 g_printerr ("modest: %s\n", error->message);
4120         else
4121                 g_printerr ("modest: unkonw error on send&receive operation");
4122
4123         /* Show error message */
4124 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4125 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4126 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4127 /*      else  */
4128 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4129 /*                                                      _CS("sfil_ib_unable_to_send")); */
4130         g_object_unref (win);
4131 }
4132
4133 static void
4134 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4135                        TnyHeader *header, 
4136                        TnyMsg *msg, 
4137                        gpointer user_data)
4138 {
4139         TnyList *parts;
4140         TnyIterator *iter;
4141         gint pending_purges = 0;
4142         gboolean some_purged = FALSE;
4143         ModestWindow *win = MODEST_WINDOW (user_data);
4144         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4145
4146         /* If there was any error */
4147         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4148                 modest_window_mgr_unregister_header (mgr, header);
4149                 return;
4150         }
4151
4152         /* Once the message has been retrieved for purging, we check if
4153          * it's all ok for purging */
4154
4155         parts = tny_simple_list_new ();
4156         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4157         iter = tny_list_create_iterator (parts);
4158
4159         while (!tny_iterator_is_done (iter)) {
4160                 TnyMimePart *part;
4161                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4162                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4163                         if (tny_mime_part_is_purged (part))
4164                                 some_purged = TRUE;
4165                         else
4166                                 pending_purges++;
4167                 }
4168
4169                 if (part)
4170                         g_object_unref (part);
4171
4172                 tny_iterator_next (iter);
4173         }
4174         g_object_unref (iter);
4175         
4176
4177         if (pending_purges>0) {
4178                 gint response;
4179                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4180
4181                 if (response == GTK_RESPONSE_OK) {
4182                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4183                         iter = tny_list_create_iterator (parts);
4184                         while (!tny_iterator_is_done (iter)) {
4185                                 TnyMimePart *part;
4186                                 
4187                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4188                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4189                                         tny_mime_part_set_purged (part);
4190
4191                                 if (part)
4192                                         g_object_unref (part);
4193
4194                                 tny_iterator_next (iter);
4195                         }
4196                         
4197                         tny_msg_rewrite_cache (msg);
4198                 }
4199         } else {
4200                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4201         }
4202         g_object_unref (iter);
4203
4204         modest_window_mgr_unregister_header (mgr, header);
4205
4206         g_object_unref (parts);
4207 }
4208
4209 static void
4210 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4211                                                      ModestMainWindow *win)
4212 {
4213         GtkWidget *header_view;
4214         TnyList *header_list;
4215         TnyIterator *iter;
4216         TnyHeader *header;
4217         TnyHeaderFlags flags;
4218         ModestWindow *msg_view_window =  NULL;
4219         gboolean found;
4220
4221         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4222
4223         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4224                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4225
4226         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4227         if (!header_list) {
4228                 g_warning ("%s: no header selected", __FUNCTION__);
4229                 return;
4230         }
4231         
4232         if (tny_list_get_length (header_list) == 1) {
4233                 iter = tny_list_create_iterator (header_list);
4234                 header = TNY_HEADER (tny_iterator_get_current (iter));
4235                 g_object_unref (iter);
4236         } else
4237                 return;
4238         
4239         if (!header || !TNY_IS_HEADER(header)) {
4240                 g_warning ("%s: header is not valid", __FUNCTION__);
4241                 return;
4242         }
4243         
4244         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4245                                                           header, &msg_view_window);
4246         flags = tny_header_get_flags (header);
4247         if (!(flags & TNY_HEADER_FLAG_CACHED))
4248                 return;
4249         if (found) {
4250                 if (msg_view_window != NULL) 
4251                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4252                 else {
4253                         /* do nothing; uid was registered before, so window is probably on it's way */
4254                         g_warning ("debug: header %p has already been registered", header);
4255                 }
4256         } else {
4257                 ModestMailOperation *mail_op = NULL;
4258                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4259                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4260                                                                          modest_ui_actions_get_msgs_full_error_handler,
4261                                                                          NULL, NULL);
4262                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4263                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4264                 
4265                 g_object_unref (mail_op);
4266         }
4267         if (header)
4268                 g_object_unref (header);
4269         if (header_list)
4270                 g_object_unref (header_list);
4271 }
4272
4273 /**
4274  * Utility function that transfer messages from both the main window
4275  * and the msg view window when using the "Move to" dialog
4276  */
4277 static void
4278 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4279                                               ModestWindow *win)
4280 {
4281         TnyList *headers = NULL;
4282         TnyAccount *dst_account = NULL;
4283         const gchar *proto_str = NULL;
4284         gboolean dst_is_pop = FALSE;
4285
4286         if (!TNY_IS_FOLDER (dst_folder)) {
4287                 modest_platform_information_banner (GTK_WIDGET (win),
4288                                                     NULL,
4289                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4290                 return;
4291         }
4292
4293         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4294         proto_str = tny_account_get_proto (dst_account);
4295
4296         /* tinymail will return NULL for local folders it seems */
4297         dst_is_pop = proto_str &&
4298                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4299                  MODEST_PROTOCOL_STORE_POP);
4300
4301         g_object_unref (dst_account);
4302
4303         /* Get selected headers */
4304         headers = get_selected_headers (MODEST_WINDOW (win));
4305         if (!headers) {
4306                 g_warning ("%s: no headers selected", __FUNCTION__);
4307                 return;
4308         }
4309
4310
4311         if (dst_is_pop) {
4312                 modest_platform_information_banner (GTK_WIDGET (win),
4313                                                     NULL,
4314                                                     ngettext("mail_in_ui_folder_move_target_error",
4315                                                              "mail_in_ui_folder_move_targets_error",
4316                                                              tny_list_get_length (headers)));
4317                 g_object_unref (headers);
4318                 return;
4319         }
4320
4321         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4322         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4323                                                            _CS("ckct_nw_pasting"));
4324         if (helper->banner != NULL)  {
4325                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4326                 gtk_widget_show (GTK_WIDGET(helper->banner));
4327         }
4328
4329         if (MODEST_IS_MAIN_WINDOW (win)) {
4330                 GtkWidget *header_view = 
4331                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4332                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4333                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4334         }
4335
4336         ModestMailOperation *mail_op = 
4337                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4338                                                                modest_ui_actions_move_folder_error_handler,
4339                                                                NULL, NULL);
4340         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4341                                          mail_op);
4342
4343         modest_mail_operation_xfer_msgs (mail_op, 
4344                                          headers,
4345                                          TNY_FOLDER (dst_folder),
4346                                          TRUE,
4347                                          move_to_cb,
4348                                          helper);
4349
4350         g_object_unref (G_OBJECT (mail_op));
4351         g_object_unref (headers);
4352 }
4353
4354 /*
4355  * UI handler for the "Move to" action when invoked from the
4356  * ModestMainWindow
4357  */
4358 static void 
4359 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4360                                           GtkWidget *folder_view,
4361                                           TnyFolderStore *dst_folder,
4362                                           ModestMainWindow *win)
4363 {
4364         ModestHeaderView *header_view = NULL;
4365         ModestMailOperation *mail_op = NULL;
4366         TnyFolderStore *src_folder;
4367         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4368
4369         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4370
4371         /* Get the source folder */
4372         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4373
4374         /* Get header view */
4375         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4376
4377         /* Get folder or messages to transfer */
4378         if (gtk_widget_is_focus (folder_view)) {
4379                 GtkTreeSelection *sel;
4380                 gboolean do_xfer = TRUE;
4381
4382                 /* Allow only to transfer folders to the local root folder */
4383                 if (TNY_IS_ACCOUNT (dst_folder) && 
4384                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4385                         do_xfer = FALSE;
4386                 } else if (!TNY_IS_FOLDER (src_folder)) {
4387                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4388                         do_xfer = FALSE;
4389                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4390                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER (src_folder));
4391                         TnyAccount *account = tny_folder_get_account (TNY_FOLDER (src_folder));
4392                         if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4393                                 do_xfer = FALSE;
4394                         g_object_unref (account);
4395                 }
4396
4397                 if (do_xfer) {
4398                         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4399                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4400                                                                            _CS("ckct_nw_pasting"));
4401                         if (helper->banner != NULL)  {
4402                                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4403                                 gtk_widget_show (GTK_WIDGET(helper->banner));
4404                         }
4405                         /* Clean folder on header view before moving it */
4406                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4407                         gtk_tree_selection_unselect_all (sel);
4408
4409                         /* Let gtk events run. We need that the folder
4410                            view frees its reference to the source
4411                            folder *before* issuing the mail operation
4412                            so we need the signal handler of selection
4413                            changed to happen before the mail
4414                            operation */
4415                         while (gtk_events_pending ())
4416                                 gtk_main_iteration ();
4417
4418                         mail_op =
4419                           modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4420                                                                          modest_ui_actions_move_folder_error_handler,
4421                                                                          src_folder, NULL);
4422                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4423                                                          mail_op);
4424
4425                         /* Select *after* the changes */
4426                         /* TODO: this function hangs UI after transfer */ 
4427 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4428 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4429                         
4430                         modest_mail_operation_xfer_folder (mail_op,
4431                                                            TNY_FOLDER (src_folder),
4432                                                            dst_folder,
4433                                                            TRUE, 
4434                                                            move_to_cb, 
4435                                                            helper);
4436                         /* Unref mail operation */
4437                         g_object_unref (G_OBJECT (mail_op));
4438                 }
4439         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4440                 gboolean do_xfer = TRUE;
4441                 /* Ask for confirmation if the source folder is remote and we're not connected */
4442                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4443                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4444                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4445                                 guint num_headers = tny_list_get_length(headers);
4446                                 TnyAccount *account = get_account_from_header_list (headers);
4447                                 if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4448                                         do_xfer = FALSE;
4449                                 g_object_unref (account);
4450                         }
4451                         g_object_unref(headers);
4452                 }
4453                 if (do_xfer) /* Transfer messages */
4454                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4455         }
4456
4457     if (src_folder)
4458         g_object_unref (src_folder);
4459 }
4460
4461
4462 /*
4463  * UI handler for the "Move to" action when invoked from the
4464  * ModestMsgViewWindow
4465  */
4466 static void 
4467 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4468                                               TnyFolderStore *dst_folder,
4469                                               ModestMsgViewWindow *win)
4470 {
4471         TnyHeader *header = NULL;
4472         TnyFolder *src_folder = NULL;
4473         TnyAccount *account = NULL;
4474         gboolean do_xfer = FALSE;
4475
4476         /* Create header list */
4477         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4478         src_folder = TNY_FOLDER (tny_header_get_folder(header));
4479         g_object_unref (header);
4480
4481         account = tny_folder_get_account (src_folder);
4482         if (!modest_platform_is_network_folderstore(TNY_FOLDER_STORE(src_folder))) {
4483                 /* Transfer if the source folder is local */
4484                 do_xfer = TRUE;
4485         } else if (remote_folder_is_pop(TNY_FOLDER_STORE(src_folder))) {
4486                 /* Transfer if the source folder is POP (as it means
4487                  * that the message is already downloaded) */
4488                 do_xfer = TRUE;
4489         } else if (connect_to_get_msg(MODEST_WINDOW(win), 1, account)) {
4490                 /* Transfer after asking confirmation */
4491                 do_xfer = TRUE;
4492         }
4493
4494         if (do_xfer) {
4495                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4496         }
4497         g_object_unref (account);
4498         g_object_unref (src_folder);
4499 }
4500
4501 void 
4502 modest_ui_actions_on_move_to (GtkAction *action, 
4503                               ModestWindow *win)
4504 {
4505         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4506         gint result = 0;
4507         TnyFolderStore *dst_folder = NULL;
4508         ModestMainWindow *main_window;
4509
4510         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4511                           MODEST_IS_MSG_VIEW_WINDOW (win));
4512
4513         /* Get the main window if exists */
4514         if (MODEST_IS_MAIN_WINDOW (win))
4515                 main_window = MODEST_MAIN_WINDOW (win);
4516         else
4517                 main_window = 
4518                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4519                                                                                FALSE)); /* don't create */
4520
4521         /* Get the folder view widget if exists */
4522         if (main_window)
4523                 folder_view = modest_main_window_get_child_widget (main_window,
4524                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4525         else
4526                 folder_view = NULL;
4527
4528         /* Create and run the dialog */
4529         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4530         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4531         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4532         result = gtk_dialog_run (GTK_DIALOG(dialog));
4533         g_object_ref (tree_view);
4534         gtk_widget_destroy (dialog);
4535
4536         if (result != GTK_RESPONSE_ACCEPT)
4537                 return;
4538
4539         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4540         /* Do window specific stuff */
4541         if (MODEST_IS_MAIN_WINDOW (win)) {
4542                 modest_ui_actions_on_main_window_move_to (action,
4543                                                           folder_view,
4544                                                           dst_folder,
4545                                                           MODEST_MAIN_WINDOW (win));
4546         } else {
4547                 modest_ui_actions_on_msg_view_window_move_to (action,
4548                                                               dst_folder,
4549                                                               MODEST_MSG_VIEW_WINDOW (win));
4550         }
4551
4552         if (dst_folder)
4553                 g_object_unref (dst_folder);
4554 }
4555
4556 /*
4557  * Calls #HeadersFunc for each header already selected in the main
4558  * window or the message currently being shown in the msg view window
4559  */
4560 static void
4561 do_headers_action (ModestWindow *win, 
4562                    HeadersFunc func,
4563                    gpointer user_data)
4564 {
4565         TnyList *headers_list = NULL;
4566         TnyIterator *iter = NULL;
4567         TnyHeader *header = NULL;
4568         TnyFolder *folder = NULL;
4569
4570         /* Get headers */
4571         headers_list = get_selected_headers (win);
4572         if (!headers_list)
4573                 return;
4574
4575         /* Get the folder */
4576         iter = tny_list_create_iterator (headers_list);
4577         header = TNY_HEADER (tny_iterator_get_current (iter));
4578         if (header) {
4579                 folder = tny_header_get_folder (header);
4580                 g_object_unref (header);
4581         }
4582
4583         /* Call the function for each header */
4584         while (!tny_iterator_is_done (iter)) {
4585                 header = TNY_HEADER (tny_iterator_get_current (iter));
4586                 func (header, win, user_data);
4587                 g_object_unref (header);
4588                 tny_iterator_next (iter);
4589         }
4590
4591         /* Trick: do a poke status in order to speed up the signaling
4592            of observers */
4593         tny_folder_poke_status (folder);
4594
4595         /* Frees */
4596         g_object_unref (folder);
4597         g_object_unref (iter);
4598         g_object_unref (headers_list);
4599 }
4600
4601 void 
4602 modest_ui_actions_view_attachment (GtkAction *action,
4603                                    ModestWindow *window)
4604 {
4605         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4606                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4607         } else {
4608                 /* not supported window for this action */
4609                 g_return_if_reached ();
4610         }
4611 }
4612
4613 void
4614 modest_ui_actions_save_attachments (GtkAction *action,
4615                                     ModestWindow *window)
4616 {
4617         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4618                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4619         } else {
4620                 /* not supported window for this action */
4621                 g_return_if_reached ();
4622         }
4623 }
4624
4625 void
4626 modest_ui_actions_remove_attachments (GtkAction *action,
4627                                       ModestWindow *window)
4628 {
4629         if (MODEST_IS_MAIN_WINDOW (window)) {
4630                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4631         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4632                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4633         } else {
4634                 /* not supported window for this action */
4635                 g_return_if_reached ();
4636         }
4637 }
4638
4639 void 
4640 modest_ui_actions_on_settings (GtkAction *action, 
4641                                ModestWindow *win)
4642 {
4643         GtkWidget *dialog;
4644
4645         dialog = modest_platform_get_global_settings_dialog ();
4646         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4647         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4648         gtk_widget_show_all (dialog);
4649
4650         gtk_dialog_run (GTK_DIALOG (dialog));
4651
4652         gtk_widget_destroy (dialog);
4653 }
4654
4655 void 
4656 modest_ui_actions_on_help (GtkAction *action, 
4657                            GtkWindow *win)
4658 {
4659         const gchar *help_id;
4660
4661         g_return_if_fail (action);
4662         g_return_if_fail (win && GTK_IS_WINDOW(win));
4663         
4664         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
4665         
4666         if (help_id)
4667                 modest_platform_show_help (GTK_WINDOW (win), help_id);
4668         else
4669                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
4670 }
4671
4672 void 
4673 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4674                                             ModestWindow *window)
4675 {
4676         ModestMailOperation *mail_op;
4677         TnyList *headers;
4678
4679         /* Get headers */
4680         headers = get_selected_headers (window);
4681         if (!headers)
4682                 return;
4683
4684         /* Create mail operation */
4685         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (window),
4686                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4687                                                                  NULL, NULL);
4688         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4689         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4690
4691         /* Frees */
4692         g_object_unref (headers);
4693         g_object_unref (mail_op);
4694 }
4695
4696 void
4697 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4698                                           ModestWindow *window)
4699 {
4700         g_return_if_fail (MODEST_IS_WINDOW (window));
4701         
4702         /* Update dimmed */     
4703         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4704 }
4705
4706 void
4707 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4708                                           ModestWindow *window)
4709 {
4710         g_return_if_fail (MODEST_IS_WINDOW (window));
4711
4712         /* Update dimmed */     
4713         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4714 }
4715
4716 void
4717 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4718                                           ModestWindow *window)
4719 {
4720         g_return_if_fail (MODEST_IS_WINDOW (window));
4721
4722         /* Update dimmed */     
4723         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4724 }
4725
4726 void
4727 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4728                                             ModestWindow *window)
4729 {
4730         g_return_if_fail (MODEST_IS_WINDOW (window));
4731
4732         /* Update dimmed */     
4733         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4734 }
4735
4736 void
4737 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4738                                           ModestWindow *window)
4739 {
4740         g_return_if_fail (MODEST_IS_WINDOW (window));
4741
4742         /* Update dimmed */     
4743         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4744 }
4745
4746 void
4747 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4748                                           ModestWindow *window)
4749 {
4750         g_return_if_fail (MODEST_IS_WINDOW (window));
4751
4752         /* Update dimmed */     
4753         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4754 }
4755
4756 void
4757 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4758                                                  ModestWindow *window)
4759 {
4760         g_return_if_fail (MODEST_IS_WINDOW (window));
4761
4762         /* Update dimmed */     
4763         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4764 }
4765
4766 void
4767 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4768                                                      ModestWindow *window)
4769 {
4770         g_return_if_fail (MODEST_IS_WINDOW (window));
4771
4772         /* Update dimmed */     
4773         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4774 }
4775
4776 void
4777 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4778                                                      ModestWindow *window)
4779 {
4780         g_return_if_fail (MODEST_IS_WINDOW (window));
4781
4782         /* Update dimmed */     
4783         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4784 }
4785
4786 void
4787 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4788 {
4789         g_return_if_fail (MODEST_IS_WINDOW (window));
4790
4791         /* Update dimmed */     
4792         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4793 }
4794
4795 void
4796 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4797 {
4798         g_return_if_fail (MODEST_IS_WINDOW (window));
4799
4800         modest_platform_show_search_messages (GTK_WINDOW (window));
4801 }
4802
4803 void     
4804 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4805 {
4806         g_return_if_fail (MODEST_IS_WINDOW (win));
4807         modest_platform_show_addressbook (GTK_WINDOW (win));
4808 }
4809
4810
4811 void
4812 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4813                                           ModestWindow *window)
4814 {
4815         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4816
4817         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4818 }
4819
4820 static void 
4821 on_send_receive_finished (ModestMailOperation  *mail_op, 
4822                            gpointer user_data)
4823 {
4824         /* Set send/receive operation finished */       
4825         modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW (user_data));      
4826 }
4827
4828
4829 void 
4830 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4831                                                 TnyHeader *header, 
4832                                                 TnyMsg *msg, 
4833                                                 GError *err, 
4834                                                 gpointer user_data)
4835 {
4836         const gchar* server_name = NULL;
4837         TnyTransportAccount *server_account;
4838         gchar *message = NULL;
4839
4840         /* Don't show anything if the user cancelled something */
4841         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4842                 return;
4843
4844         /* Get the server name: */
4845         server_account = 
4846                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4847         if (server_account) {
4848                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4849                         
4850                 g_object_unref (server_account);
4851                 server_account = NULL;
4852         }
4853         
4854         g_return_if_fail (server_name);
4855
4856         /* Show the appropriate message text for the GError: */
4857         switch (err->code) {
4858         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4859                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4860                 break;
4861         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4862                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4863                 break;
4864         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4865                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4866                 break;
4867         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4868                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4869                 break;
4870         default:
4871                 g_return_if_reached ();
4872         }
4873         
4874         /* TODO if the username or the password where not defined we
4875            should show the Accounts Settings dialog or the Connection
4876            specific SMTP server window */
4877
4878         modest_platform_run_information_dialog (NULL, message);
4879         g_free (message);
4880 }
4881
4882 void
4883 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
4884                                                 gchar *msg_id, 
4885                                                 guint status,
4886                                                 gpointer user_data)
4887 {
4888         ModestMainWindow *main_window = NULL;
4889         ModestWindowMgr *mgr = NULL;
4890         GtkWidget *folder_view = NULL, *header_view = NULL;
4891         TnyFolderStore *selected_folder = NULL;
4892         TnyFolderType folder_type;
4893
4894         mgr = modest_runtime_get_window_mgr ();
4895         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
4896                                                                              FALSE));/* don't create */
4897         if (!main_window)
4898                 return;
4899
4900         /* Check if selected folder is OUTBOX */
4901         folder_view = modest_main_window_get_child_widget (main_window,
4902                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4903         header_view = modest_main_window_get_child_widget (main_window,
4904                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4905
4906         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4907         if (!TNY_IS_FOLDER (selected_folder)) 
4908                 goto frees;
4909
4910         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
4911 #if GTK_CHECK_VERSION(2, 8, 0) 
4912         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
4913         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
4914                 GtkTreeViewColumn *tree_column;
4915
4916                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
4917                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
4918                 gtk_tree_view_column_queue_resize (tree_column);
4919         }
4920 #else
4921         gtk_widget_queue_draw (header_view);
4922 #endif          
4923         
4924         /* Free */
4925  frees:
4926         if (selected_folder != NULL)
4927                 g_object_unref (selected_folder);
4928 }