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