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