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