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