* Select the folder that has been moved
[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                         /* Actually rename the folder */
2512                         modest_mail_operation_rename_folder (mail_op,
2513                                                              TNY_FOLDER (folder),
2514                                                              (const gchar *) folder_name);
2515
2516                         g_object_unref (mail_op);
2517                         g_free (folder_name);
2518                 }
2519         }
2520         g_object_unref (folder);
2521 }
2522
2523 static void
2524 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2525                                                gpointer user_data)
2526 {
2527         GObject *win = modest_mail_operation_get_source (mail_op);
2528
2529         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2530                                                 _("mail_in_ui_folder_delete_error"));
2531         g_object_unref (win);
2532 }
2533
2534 static void
2535 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2536 {
2537         TnyFolderStore *folder;
2538         GtkWidget *folder_view;
2539         gint response;
2540         gchar *message;
2541         gboolean do_delete = TRUE;
2542
2543         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2544
2545         folder_view = modest_main_window_get_child_widget (main_window,
2546                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2547         if (!folder_view)
2548                 return;
2549
2550         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2551
2552         /* Show an error if it's an account */
2553         if (!TNY_IS_FOLDER (folder)) {
2554                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2555                                                         _("mail_in_ui_folder_delete_error"));
2556                 g_object_unref (G_OBJECT (folder));
2557                 return ;
2558         }
2559
2560         /* Ask the user */      
2561         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2562                                     tny_folder_get_name (TNY_FOLDER (folder)));
2563         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2564                                                             (const gchar *) message);
2565         g_free (message);
2566
2567         if (response != GTK_RESPONSE_OK) {
2568                 do_delete = FALSE;
2569         } else if (modest_platform_is_network_folderstore(folder) &&
2570                    !tny_device_is_online (modest_runtime_get_device())) {
2571                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2572                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2573                 g_object_unref(account);
2574         }
2575
2576         if (do_delete) {
2577                 ModestMailOperation *mail_op;
2578                 GtkTreeSelection *sel;
2579
2580                 /* Unselect the folder before deleting it to free the headers */
2581                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2582                 gtk_tree_selection_unselect_all (sel);
2583
2584                 /* Create the mail operation */
2585                 mail_op =
2586                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2587                                                                        G_OBJECT(main_window),
2588                                                                        modest_ui_actions_delete_folder_error_handler,
2589                                                                        NULL);
2590
2591                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2592                                                  mail_op);
2593                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2594                 g_object_unref (G_OBJECT (mail_op));
2595         }
2596
2597         g_object_unref (G_OBJECT (folder));
2598 }
2599
2600 void 
2601 modest_ui_actions_on_delete_folder (GtkAction *action,
2602                                      ModestMainWindow *main_window)
2603 {
2604         GtkWidget *folder_view;
2605         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2606
2607         delete_folder (main_window, FALSE);
2608         folder_view = modest_main_window_get_child_widget (main_window,
2609                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2610         if (!folder_view)
2611                 return;
2612         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2613 }
2614
2615 void 
2616 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2617 {
2618         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2619         
2620         delete_folder (main_window, TRUE);
2621 }
2622
2623
2624 static void
2625 show_error (GtkWidget *parent_widget, const gchar* text)
2626 {
2627         hildon_banner_show_information(parent_widget, NULL, text);
2628         
2629 #if 0
2630         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2631         /*
2632           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2633           (GtkDialogFlags)0,
2634           GTK_MESSAGE_ERROR,
2635           GTK_BUTTONS_OK,
2636           text ));
2637         */
2638                  
2639         gtk_dialog_run (dialog);
2640         gtk_widget_destroy (GTK_WIDGET (dialog));
2641 #endif
2642 }
2643
2644 void
2645 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2646                                          const gchar* server_account_name,
2647                                          gchar **username,
2648                                          gchar **password, 
2649                                          gboolean *cancel, 
2650                                          gboolean *remember,
2651                                          ModestMainWindow *main_window)
2652 {
2653         g_return_if_fail(server_account_name);
2654         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2655         
2656         /* Initalize output parameters: */
2657         if (cancel)
2658                 *cancel = FALSE;
2659                 
2660         if (remember)
2661                 *remember = TRUE;
2662                 
2663 #ifdef MODEST_PLATFORM_MAEMO
2664         /* Maemo uses a different (awkward) button order,
2665          * It should probably just use gtk_alternative_dialog_button_order ().
2666          */
2667         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2668                                               NULL,
2669                                               GTK_DIALOG_MODAL,
2670                                               _("mcen_bd_dialog_ok"),
2671                                               GTK_RESPONSE_ACCEPT,
2672                                               _("mcen_bd_dialog_cancel"),
2673                                               GTK_RESPONSE_REJECT,
2674                                               NULL);
2675 #else
2676         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2677                                               NULL,
2678                                               GTK_DIALOG_MODAL,
2679                                               GTK_STOCK_CANCEL,
2680                                               GTK_RESPONSE_REJECT,
2681                                               GTK_STOCK_OK,
2682                                               GTK_RESPONSE_ACCEPT,
2683                                               NULL);
2684 #endif /* MODEST_PLATFORM_MAEMO */
2685
2686         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2687         
2688         gchar *server_name = modest_server_account_get_hostname (
2689                 modest_runtime_get_account_mgr(), server_account_name);
2690         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2691                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2692                 *cancel = TRUE;
2693                 return;
2694         }
2695         
2696         /* This causes a warning because the logical ID has no %s in it, 
2697          * though the translation does, but there is not much we can do about that: */
2698         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2699         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2700                             FALSE, FALSE, 0);
2701         g_free (txt);
2702         g_free (server_name);
2703         server_name = NULL;
2704
2705         /* username: */
2706         gchar *initial_username = modest_server_account_get_username (
2707                 modest_runtime_get_account_mgr(), server_account_name);
2708         
2709         GtkWidget *entry_username = gtk_entry_new ();
2710         if (initial_username)
2711                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2712         /* Dim this if a connection has ever succeeded with this username,
2713          * as per the UI spec: */
2714         const gboolean username_known = 
2715                 modest_server_account_get_username_has_succeeded(
2716                         modest_runtime_get_account_mgr(), server_account_name);
2717         gtk_widget_set_sensitive (entry_username, !username_known);
2718         
2719 #ifdef MODEST_PLATFORM_MAEMO
2720         /* Auto-capitalization is the default, so let's turn it off: */
2721         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2722         
2723         /* Create a size group to be used by all captions.
2724          * Note that HildonCaption does not create a default size group if we do not specify one.
2725          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2726         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2727         
2728         GtkWidget *caption = hildon_caption_new (sizegroup, 
2729                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2730         gtk_widget_show (entry_username);
2731         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2732                 FALSE, FALSE, MODEST_MARGIN_HALF);
2733         gtk_widget_show (caption);
2734 #else 
2735         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2736                             TRUE, FALSE, 0);
2737 #endif /* MODEST_PLATFORM_MAEMO */      
2738                             
2739         /* password: */
2740         GtkWidget *entry_password = gtk_entry_new ();
2741         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2742         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2743         
2744 #ifdef MODEST_PLATFORM_MAEMO
2745         /* Auto-capitalization is the default, so let's turn it off: */
2746         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2747                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2748         
2749         caption = hildon_caption_new (sizegroup, 
2750                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2751         gtk_widget_show (entry_password);
2752         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2753                 FALSE, FALSE, MODEST_MARGIN_HALF);
2754         gtk_widget_show (caption);
2755         g_object_unref (sizegroup);
2756 #else 
2757         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2758                             TRUE, FALSE, 0);
2759 #endif /* MODEST_PLATFORM_MAEMO */      
2760                                 
2761 /* This is not in the Maemo UI spec:
2762         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2763         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2764                             TRUE, FALSE, 0);
2765 */
2766
2767         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2768         
2769         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2770                 if (username) {
2771                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2772                         
2773                         modest_server_account_set_username (
2774                                  modest_runtime_get_account_mgr(), server_account_name, 
2775                                  *username);
2776                                  
2777                         const gboolean username_was_changed = 
2778                                 (strcmp (*username, initial_username) != 0);
2779                         if (username_was_changed) {
2780                                 g_warning ("%s: tinymail does not yet support changing the "
2781                                         "username in the get_password() callback.\n", __FUNCTION__);
2782                         }
2783                 }
2784                         
2785                 if (password) {
2786                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2787                         
2788                         /* We do not save the password in the configuration, 
2789                          * because this function is only called for passwords that should 
2790                          * not be remembered:
2791                         modest_server_account_set_password (
2792                                  modest_runtime_get_account_mgr(), server_account_name, 
2793                                  *password);
2794                         */
2795                 }
2796                 
2797                 if (cancel)
2798                         *cancel   = FALSE;
2799                         
2800         } else {
2801                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2802                 
2803                 if (username)
2804                         *username = NULL;
2805                         
2806                 if (password)
2807                         *password = NULL;
2808                         
2809                 if (cancel)
2810                         *cancel   = TRUE;
2811         }
2812
2813 /* This is not in the Maemo UI spec:
2814         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2815                 *remember = TRUE;
2816         else
2817                 *remember = FALSE;
2818 */
2819
2820         gtk_widget_destroy (dialog);
2821         
2822         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2823 }
2824
2825 void
2826 modest_ui_actions_on_cut (GtkAction *action,
2827                           ModestWindow *window)
2828 {
2829         GtkWidget *focused_widget;
2830         GtkClipboard *clipboard;
2831
2832         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2833         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2834         if (GTK_IS_EDITABLE (focused_widget)) {
2835                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2836                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2837                 gtk_clipboard_store (clipboard);
2838         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2839                 GtkTextBuffer *buffer;
2840
2841                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2842                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2843                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2844                 gtk_clipboard_store (clipboard);
2845         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2846                 TnyList *header_list = modest_header_view_get_selected_headers (
2847                                 MODEST_HEADER_VIEW (focused_widget));
2848                 gboolean continue_download = FALSE;
2849                 gint num_of_unc_msgs;
2850
2851                 num_of_unc_msgs = header_list_count_uncached_msgs(
2852                                 header_list, GTK_WINDOW (window));
2853
2854                 if (num_of_unc_msgs)
2855                         continue_download = connect_to_get_msg(
2856                                                                 GTK_WINDOW (window),
2857                                                                 num_of_unc_msgs);
2858
2859                 if (num_of_unc_msgs == 0 || continue_download) {
2860 /*                      modest_platform_information_banner (
2861                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
2862                         modest_header_view_cut_selection (
2863                                         MODEST_HEADER_VIEW (focused_widget));
2864                 }
2865
2866                 g_object_unref (header_list);
2867         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2868                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2869         }
2870 }
2871
2872 void
2873 modest_ui_actions_on_copy (GtkAction *action,
2874                            ModestWindow *window)
2875 {
2876         GtkClipboard *clipboard;
2877         GtkWidget *focused_widget;
2878         gboolean copied = TRUE;
2879
2880         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2881         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2882
2883         if (GTK_IS_LABEL (focused_widget)) {
2884                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2885                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2886                 gtk_clipboard_store (clipboard);
2887         } else if (GTK_IS_EDITABLE (focused_widget)) {
2888                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2889                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2890                 gtk_clipboard_store (clipboard);
2891         } else if (GTK_IS_HTML (focused_widget)) {
2892                 gtk_html_copy (GTK_HTML (focused_widget));
2893                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2894                 gtk_clipboard_store (clipboard);
2895         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2896                 GtkTextBuffer *buffer;
2897                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2898                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2899                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2900                 gtk_clipboard_store (clipboard);
2901         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2902                 TnyList *header_list = modest_header_view_get_selected_headers (
2903                                 MODEST_HEADER_VIEW (focused_widget));
2904                 gboolean continue_download = FALSE;
2905                 gint num_of_unc_msgs;
2906
2907                 num_of_unc_msgs = header_list_count_uncached_msgs(
2908                                                                 header_list,
2909                                                                 GTK_WINDOW (window));
2910
2911                 if (num_of_unc_msgs)
2912                         continue_download = connect_to_get_msg(
2913                                                                 GTK_WINDOW (window),
2914                                                                 num_of_unc_msgs);
2915
2916                 if (num_of_unc_msgs == 0 || continue_download) {
2917                         modest_platform_information_banner (
2918                                         NULL, NULL, _CS("mcen_ib_getting_items"));
2919                         modest_header_view_copy_selection (
2920                                         MODEST_HEADER_VIEW (focused_widget));
2921                 } else
2922                         copied = FALSE;
2923
2924                 g_object_unref (header_list);
2925
2926         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2927                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2928         }
2929
2930         /* Show information banner if there was a copy to clipboard */
2931         if(copied)
2932                 modest_platform_information_banner (
2933                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2934 }
2935
2936 void
2937 modest_ui_actions_on_undo (GtkAction *action,
2938                            ModestWindow *window)
2939 {
2940         ModestEmailClipboard *clipboard = NULL;
2941
2942         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2943                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2944         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2945                 /* Clear clipboard source */
2946                 clipboard = modest_runtime_get_email_clipboard ();
2947                 modest_email_clipboard_clear (clipboard);               
2948         }
2949         else {
2950                 g_return_if_reached ();
2951         }
2952 }
2953
2954 void
2955 modest_ui_actions_on_redo (GtkAction *action,
2956                            ModestWindow *window)
2957 {
2958         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2959                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2960         }
2961         else {
2962                 g_return_if_reached ();
2963         }
2964 }
2965
2966
2967 static void
2968 paste_msgs_cb (const GObject *object, gpointer user_data)
2969 {
2970         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2971         g_return_if_fail (GTK_IS_WIDGET (user_data));
2972         
2973         /* destroy information note */
2974         gtk_widget_destroy (GTK_WIDGET(user_data));
2975 }
2976
2977 static void
2978 paste_as_attachment_free (gpointer data)
2979 {
2980         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2981
2982         gtk_widget_destroy (helper->banner);
2983         g_object_unref (helper->banner);
2984         g_free (helper);
2985 }
2986
2987 static void
2988 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2989                             TnyHeader *header,
2990                             TnyMsg *msg,
2991                             gpointer userdata)
2992 {
2993         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2994         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2995
2996         if (msg == NULL)
2997                 return;
2998
2999         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3000         
3001 }
3002
3003 void
3004 modest_ui_actions_on_paste (GtkAction *action,
3005                             ModestWindow *window)
3006 {
3007         GtkWidget *focused_widget = NULL;
3008         GtkWidget *inf_note = NULL;
3009         ModestMailOperation *mail_op = NULL;
3010
3011         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3012         if (GTK_IS_EDITABLE (focused_widget)) {
3013                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3014         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3015                 ModestEmailClipboard *e_clipboard = NULL;
3016                 e_clipboard = modest_runtime_get_email_clipboard ();
3017                 if (modest_email_clipboard_cleared (e_clipboard)) {
3018                         GtkTextBuffer *buffer;
3019                         GtkClipboard *clipboard;
3020
3021                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3022                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3023                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3024                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3025                         ModestMailOperation *mail_op;
3026                         TnyFolder *src_folder;
3027                         TnyList *data;
3028                         gboolean delete;
3029                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3030                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3031                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3032                                                                            _CS("ckct_nw_pasting"));
3033                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3034                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3035                                                              G_OBJECT (window));
3036                         if (helper->banner != NULL) {
3037                                 g_object_ref (G_OBJECT (helper->banner));
3038                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3039                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3040                         }
3041
3042                         if (data != NULL) {
3043                                 modest_mail_operation_get_msgs_full (mail_op, 
3044                                                                      data,
3045                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3046                                                                      helper,
3047                                                                      paste_as_attachment_free);
3048                         }
3049                 }
3050         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3051                 ModestEmailClipboard *clipboard = NULL;
3052                 TnyFolder *src_folder = NULL;
3053                 TnyFolderStore *folder_store = NULL;
3054                 TnyList *data = NULL;           
3055                 gboolean delete = FALSE;
3056                 
3057                 /* Check clipboard source */
3058                 clipboard = modest_runtime_get_email_clipboard ();
3059                 if (modest_email_clipboard_cleared (clipboard)) 
3060                         return;
3061                 
3062                 /* Get elements to paste */
3063                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3064
3065                 /* Create a new mail operation */
3066                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3067                 
3068                 /* Get destination folder */
3069                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3070
3071                 /* transfer messages  */
3072                 if (data != NULL) {
3073                         gint response = 0;
3074
3075                         /* Ask for user confirmation */
3076                         response = msgs_move_to_confirmation (GTK_WINDOW (window), 
3077                                                               TNY_FOLDER (folder_store), 
3078                                                               delete,
3079                                                               data);
3080                         
3081                         if (response == GTK_RESPONSE_OK) {
3082                                 /* Launch notification */
3083                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3084                                                                              _CS("ckct_nw_pasting"));
3085                                 if (inf_note != NULL)  {
3086                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3087                                         gtk_widget_show (GTK_WIDGET(inf_note));
3088                                 }
3089
3090                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3091                                 modest_mail_operation_xfer_msgs (mail_op, 
3092                                                                  data,
3093                                                                  TNY_FOLDER (folder_store),
3094                                                                  delete,
3095                                                                  paste_msgs_cb,
3096                                                                  inf_note);                             
3097                         } else {
3098                                 g_object_unref (mail_op);
3099                         }
3100                         
3101                 } else if (src_folder != NULL) {                        
3102                         /* Launch notification */
3103                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3104                                                                      _CS("ckct_nw_pasting"));
3105                         if (inf_note != NULL)  {
3106                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3107                                 gtk_widget_show (GTK_WIDGET(inf_note));
3108                         }
3109                         
3110                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3111                         modest_mail_operation_xfer_folder (mail_op, 
3112                                                            src_folder,
3113                                                            folder_store,
3114                                                            delete,
3115                                                            paste_msgs_cb,
3116                                                            inf_note);
3117                 }
3118
3119                 /* Free */
3120                 if (data != NULL) 
3121                         g_object_unref (data);
3122                 if (src_folder != NULL) 
3123                         g_object_unref (src_folder);
3124                 if (folder_store != NULL) 
3125                         g_object_unref (folder_store);
3126         }
3127 }
3128
3129
3130 void
3131 modest_ui_actions_on_select_all (GtkAction *action,
3132                                  ModestWindow *window)
3133 {
3134         GtkWidget *focused_widget;
3135
3136         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3137         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3138                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3139         } else if (GTK_IS_LABEL (focused_widget)) {
3140                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3141         } else if (GTK_IS_EDITABLE (focused_widget)) {
3142                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3143         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3144                 GtkTextBuffer *buffer;
3145                 GtkTextIter start, end;
3146
3147                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3148                 gtk_text_buffer_get_start_iter (buffer, &start);
3149                 gtk_text_buffer_get_end_iter (buffer, &end);
3150                 gtk_text_buffer_select_range (buffer, &start, &end);
3151         } else if (GTK_IS_HTML (focused_widget)) {
3152                 gtk_html_select_all (GTK_HTML (focused_widget));
3153         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3154                 GtkWidget *header_view = focused_widget;
3155                 GtkTreeSelection *selection = NULL;
3156                 
3157                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3158                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3159                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3160                 }
3161                                 
3162                 /* Disable window dimming management */
3163                 modest_window_disable_dimming (MODEST_WINDOW(window));
3164                 
3165                 /* Select all messages */
3166                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3167                 gtk_tree_selection_select_all (selection);
3168
3169                 /* Set focuse on header view */
3170                 gtk_widget_grab_focus (header_view);
3171
3172
3173                 /* Enable window dimming management */
3174                 modest_window_enable_dimming (MODEST_WINDOW(window));
3175                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3176         }
3177
3178 }
3179
3180 void
3181 modest_ui_actions_on_mark_as_read (GtkAction *action,
3182                                    ModestWindow *window)
3183 {       
3184         g_return_if_fail (MODEST_IS_WINDOW(window));
3185                 
3186         /* Mark each header as read */
3187         do_headers_action (window, headers_action_mark_as_read, NULL);
3188 }
3189
3190 void
3191 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3192                                      ModestWindow *window)
3193 {       
3194         g_return_if_fail (MODEST_IS_WINDOW(window));
3195                 
3196         /* Mark each header as read */
3197         do_headers_action (window, headers_action_mark_as_unread, NULL);
3198 }
3199
3200 void
3201 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3202                                   GtkRadioAction *selected,
3203                                   ModestWindow *window)
3204 {
3205         gint value;
3206
3207         value = gtk_radio_action_get_current_value (selected);
3208         if (MODEST_IS_WINDOW (window)) {
3209                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3210         }
3211 }
3212
3213 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3214                                                         GtkRadioAction *selected,
3215                                                         ModestWindow *window)
3216 {
3217         TnyHeaderFlags flags;
3218         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3219
3220         flags = gtk_radio_action_get_current_value (selected);
3221         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3222 }
3223
3224 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3225                                                            GtkRadioAction *selected,
3226                                                            ModestWindow *window)
3227 {
3228         gint file_format;
3229
3230         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3231
3232         file_format = gtk_radio_action_get_current_value (selected);
3233         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3234 }
3235
3236
3237 void     
3238 modest_ui_actions_on_zoom_plus (GtkAction *action,
3239                                 ModestWindow *window)
3240 {
3241         g_return_if_fail (MODEST_IS_WINDOW (window));
3242
3243         modest_window_zoom_plus (MODEST_WINDOW (window));
3244 }
3245
3246 void     
3247 modest_ui_actions_on_zoom_minus (GtkAction *action,
3248                                  ModestWindow *window)
3249 {
3250         g_return_if_fail (MODEST_IS_WINDOW (window));
3251
3252         modest_window_zoom_minus (MODEST_WINDOW (window));
3253 }
3254
3255 void     
3256 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3257                                            ModestWindow *window)
3258 {
3259         ModestWindowMgr *mgr;
3260         gboolean fullscreen, active;
3261         g_return_if_fail (MODEST_IS_WINDOW (window));
3262
3263         mgr = modest_runtime_get_window_mgr ();
3264
3265         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3266         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3267
3268         if (active != fullscreen) {
3269                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3270                 gtk_window_present (GTK_WINDOW (window));
3271         }
3272 }
3273
3274 void
3275 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3276                                         ModestWindow *window)
3277 {
3278         ModestWindowMgr *mgr;
3279         gboolean fullscreen;
3280
3281         g_return_if_fail (MODEST_IS_WINDOW (window));
3282
3283         mgr = modest_runtime_get_window_mgr ();
3284         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3285         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3286
3287         gtk_window_present (GTK_WINDOW (window));
3288 }
3289
3290 /* 
3291  * Used by modest_ui_actions_on_details to call do_headers_action 
3292  */
3293 static void
3294 headers_action_show_details (TnyHeader *header, 
3295                              ModestWindow *window,
3296                              gpointer user_data)
3297
3298 {
3299         GtkWidget *dialog;
3300         
3301         /* Create dialog */
3302         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3303
3304         /* Run dialog */
3305         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3306         gtk_widget_show_all (dialog);
3307         gtk_dialog_run (GTK_DIALOG (dialog));
3308
3309         gtk_widget_destroy (dialog);
3310 }
3311
3312 /*
3313  * Show the folder details in a ModestDetailsDialog widget
3314  */
3315 static void
3316 show_folder_details (TnyFolder *folder, 
3317                      GtkWindow *window)
3318 {
3319         GtkWidget *dialog;
3320         
3321         /* Create dialog */
3322         dialog = modest_details_dialog_new_with_folder (window, folder);
3323
3324         /* Run dialog */
3325         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3326         gtk_widget_show_all (dialog);
3327         gtk_dialog_run (GTK_DIALOG (dialog));
3328
3329         gtk_widget_destroy (dialog);
3330 }
3331
3332 /*
3333  * Show the header details in a ModestDetailsDialog widget
3334  */
3335 void     
3336 modest_ui_actions_on_details (GtkAction *action, 
3337                               ModestWindow *win)
3338 {
3339         TnyList * headers_list;
3340         TnyIterator *iter;
3341         TnyHeader *header;              
3342
3343         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3344                 TnyMsg *msg;
3345
3346                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3347                 if (!msg)
3348                         return;
3349                 g_object_unref (msg);           
3350
3351                 headers_list = get_selected_headers (win);
3352                 if (!headers_list)
3353                         return;
3354
3355                 iter = tny_list_create_iterator (headers_list);
3356
3357                 header = TNY_HEADER (tny_iterator_get_current (iter));
3358                 if (header) {
3359                         headers_action_show_details (header, win, NULL);
3360                         g_object_unref (header);
3361                 }
3362
3363                 g_object_unref (iter);
3364                 g_object_unref (headers_list);
3365
3366         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3367                 GtkWidget *folder_view, *header_view;
3368
3369                 /* Check which widget has the focus */
3370                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3371                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3372                 if (gtk_widget_is_focus (folder_view)) {
3373                         TnyFolderStore *folder_store
3374                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3375                         if (!folder_store) {
3376                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3377                                 return; 
3378                         }
3379                         /* Show only when it's a folder */
3380                         /* This function should not be called for account items, 
3381                          * because we dim the menu item for them. */
3382                         if (TNY_IS_FOLDER (folder_store)) {
3383                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3384                         }
3385
3386                         g_object_unref (folder_store);
3387
3388                 } else {
3389                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3390                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3391                         /* Show details of each header */
3392                         do_headers_action (win, headers_action_show_details, header_view);
3393                 }
3394         }
3395 }
3396
3397 void     
3398 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3399                                      ModestMsgEditWindow *window)
3400 {
3401         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3402
3403         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3404 }
3405
3406 void     
3407 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3408                                       ModestMsgEditWindow *window)
3409 {
3410         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3411
3412         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3413 }
3414
3415 void
3416 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3417                                        ModestMainWindow *main_window)
3418 {
3419         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3420
3421         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3422                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3423         else
3424                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3425 }
3426
3427 void 
3428 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3429                                      ModestWindow *window)
3430 {
3431         gboolean active, fullscreen = FALSE;
3432         ModestWindowMgr *mgr;
3433
3434         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3435
3436         /* Check if we want to toggle the toolbar vuew in fullscreen
3437            or normal mode */
3438         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3439                      "ViewShowToolbarFullScreen")) {
3440                 fullscreen = TRUE;
3441         }
3442
3443         /* Toggle toolbar */
3444         mgr = modest_runtime_get_window_mgr ();
3445         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3446 }
3447
3448 void     
3449 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3450                                            ModestMsgEditWindow *window)
3451 {
3452         modest_msg_edit_window_select_font (window);
3453 }
3454
3455 void
3456 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3457                                                   const gchar *display_name,
3458                                                   GtkWindow *window)
3459 {
3460         /* Do not change the application name if the widget has not
3461            the focus. This callback could be called even if the folder
3462            view has not the focus, because the handled signal could be
3463            emitted when the folder view is redrawn */
3464         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3465                 if (display_name)
3466                         gtk_window_set_title (window, display_name);
3467                 else
3468                         gtk_window_set_title (window, " ");
3469         }
3470 }
3471
3472 void
3473 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3474 {
3475         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3476         modest_msg_edit_window_select_contacts (window);
3477 }
3478
3479 void
3480 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3481 {
3482         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3483         modest_msg_edit_window_check_names (window, FALSE);
3484 }
3485
3486 static void
3487 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3488 {
3489         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3490                                          GTK_WIDGET (user_data));
3491 }
3492
3493 /*
3494  * This function is used to track changes in the selection of the
3495  * folder view that is inside the "move to" dialog to enable/disable
3496  * the OK button because we do not want the user to select a disallowed
3497  * destination for a folder.
3498  * The user also not desired to be able to use NEW button on items where
3499  * folder creation is not possibel.
3500  */
3501 static void
3502 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3503                                             TnyFolderStore *folder_store,
3504                                             gboolean selected,
3505                                             gpointer user_data)
3506 {
3507         GtkWidget *dialog = NULL;
3508         GtkWidget *ok_button = NULL, *new_button = NULL;
3509         GList *children = NULL;
3510         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3511         gboolean moving_folder = FALSE;
3512         gboolean is_local_account = TRUE;
3513         GtkWidget *folder_view = NULL;
3514         ModestTnyFolderRules rules;
3515
3516         if (!selected)
3517                 return;
3518
3519         /* Get the OK button */
3520         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3521         if (!dialog)
3522                 return;
3523
3524         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3525         ok_button = GTK_WIDGET (children->next->next->data);
3526         new_button = GTK_WIDGET (children->next->data);
3527         g_list_free (children);
3528
3529         /* check if folder_store is an remote account */
3530         if (TNY_IS_ACCOUNT (folder_store)) {
3531                 TnyAccount *local_account = NULL;
3532                 ModestTnyAccountStore *account_store = NULL;
3533
3534                 account_store = modest_runtime_get_account_store ();
3535                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3536
3537                 if ((gpointer) local_account != (gpointer) folder_store) {
3538                         is_local_account = FALSE;
3539                         /* New button should be dimmed on remote
3540                            account root */
3541                         new_sensitive = FALSE;
3542                 }
3543                 g_object_unref (local_account);
3544         }
3545
3546         /* Check the target folder rules */
3547         if (TNY_IS_FOLDER (folder_store)) {
3548                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3549                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3550                         ok_sensitive = FALSE;
3551                         new_sensitive = FALSE;
3552                         goto end;
3553                 }
3554         }
3555
3556         /* Check if we're moving a folder */
3557         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3558                 /* Get the widgets */
3559                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3560                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3561                 if (gtk_widget_is_focus (folder_view))
3562                         moving_folder = TRUE;
3563         }
3564
3565         if (moving_folder) {
3566                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3567
3568                 /* Get the folder to move */
3569                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3570                 
3571                 /* Check that we're not moving to the same folder */
3572                 if (TNY_IS_FOLDER (moved_folder)) {
3573                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3574                         if (parent == folder_store)
3575                                 ok_sensitive = FALSE;
3576                         g_object_unref (parent);
3577                 } 
3578
3579                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3580                         /* Do not allow to move to an account unless it's the
3581                            local folders account */
3582                         if (!is_local_account)
3583                                 ok_sensitive = FALSE;
3584                 } 
3585
3586                 if (ok_sensitive && (moved_folder == folder_store)) {
3587                         /* Do not allow to move to itself */
3588                         ok_sensitive = FALSE;
3589                 }
3590                 g_object_unref (moved_folder);
3591         } else {
3592                 TnyHeader *header = NULL;
3593                 TnyFolder *src_folder = NULL;
3594
3595                 /* Moving a message */
3596                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3597                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3598                         src_folder = tny_header_get_folder (header);
3599                         g_object_unref (header);
3600                 } else {
3601                         src_folder = 
3602                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3603                 }
3604
3605                 /* Do not allow to move the msg to the same folder */
3606                 /* Do not allow to move the msg to an account */
3607                 if ((gpointer) src_folder == (gpointer) folder_store ||
3608                     TNY_IS_ACCOUNT (folder_store))
3609                         ok_sensitive = FALSE;
3610                 g_object_unref (src_folder);
3611         }
3612
3613  end:
3614         /* Set sensitivity of the OK button */
3615         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3616         /* Set sensitivity of the NEW button */
3617         gtk_widget_set_sensitive (new_button, new_sensitive);
3618 }
3619
3620 static GtkWidget*
3621 create_move_to_dialog (GtkWindow *win,
3622                        GtkWidget *folder_view,
3623                        GtkWidget **tree_view)
3624 {
3625         GtkWidget *dialog, *scroll;
3626         GtkWidget *new_button;
3627
3628         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3629                                               GTK_WINDOW (win),
3630                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3631                                               NULL);
3632
3633         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3634         /* We do this manually so GTK+ does not associate a response ID for
3635          * the button. */
3636         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3637         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3638         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3639
3640         /* Create scrolled window */
3641         scroll = gtk_scrolled_window_new (NULL, NULL);
3642         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3643                                          GTK_POLICY_AUTOMATIC,
3644                                          GTK_POLICY_AUTOMATIC);
3645
3646         /* Create folder view */
3647         *tree_view = modest_platform_create_folder_view (NULL);
3648
3649         /* Track changes in the selection to
3650          * disable the OK button whenever "Move to" is not possible
3651          * disbale NEW button whenever New is not possible */
3652         g_signal_connect (*tree_view,
3653                           "folder_selection_changed",
3654                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3655                           win);
3656
3657         /* Listen to clicks on New button */
3658         g_signal_connect (G_OBJECT (new_button), 
3659                           "clicked", 
3660                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3661                           *tree_view);
3662
3663         /* It could happen that we're trying to move a message from a
3664            window (msg window for example) after the main window was
3665            closed, so we can not just get the model of the folder
3666            view */
3667         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3668                 const gchar *visible_id = NULL;
3669
3670                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3671                                                MODEST_FOLDER_VIEW(*tree_view));
3672
3673                 visible_id = 
3674                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3675
3676                 /* Show the same account than the one that is shown in the main window */
3677                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3678                                                                              visible_id);
3679         } else {
3680                 const gchar *active_account_name = NULL;
3681                 ModestAccountMgr *mgr = NULL;
3682                 ModestAccountData *acc_data = NULL;
3683
3684                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3685                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3686
3687                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3688                 mgr = modest_runtime_get_account_mgr ();
3689                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3690
3691                 /* Set the new visible & active account */
3692                 if (acc_data && acc_data->store_account) { 
3693                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3694                                                                                      acc_data->store_account->account_name);
3695                         modest_account_mgr_free_account_data (mgr, acc_data);
3696                 }
3697         }
3698
3699         /* Hide special folders */
3700         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3701         
3702         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3703
3704         /* Add scroll to dialog */
3705         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3706                             scroll, TRUE, TRUE, 0);
3707
3708         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3709         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3710
3711         return dialog;
3712 }
3713
3714 /*
3715  * Returns TRUE if at least one of the headers of the list belongs to
3716  * a message that has been fully retrieved.
3717  */
3718 #if 0 /* no longer in use. delete in 2007.10 */
3719 static gboolean
3720 has_retrieved_msgs (TnyList *list)
3721 {
3722         TnyIterator *iter;
3723         gboolean found = FALSE;
3724
3725         iter = tny_list_create_iterator (list);
3726         while (!tny_iterator_is_done (iter) && !found) {
3727                 TnyHeader *header;
3728                 TnyHeaderFlags flags = 0;
3729
3730                 header = TNY_HEADER (tny_iterator_get_current (iter));
3731                 if (header) {
3732                         flags = tny_header_get_flags (header);
3733                         if (flags & TNY_HEADER_FLAG_CACHED)
3734 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3735                                 found = TRUE;
3736
3737                         g_object_unref (header);
3738                 }
3739
3740                 if (!found)
3741                         tny_iterator_next (iter);
3742         }
3743         g_object_unref (iter);
3744
3745         return found;
3746 }
3747 #endif /* 0 */
3748
3749
3750 /*
3751  * Shows a confirmation dialog to the user when we're moving messages
3752  * from a remote server to the local storage. Returns the dialog
3753  * response. If it's other kind of movement then it always returns
3754  * GTK_RESPONSE_OK
3755  *
3756  * This one is used by the next functions:
3757  *      modest_ui_actions_xfer_messages_from_move_to
3758  *      modest_ui_actions_on_paste                      - commented out
3759  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3760  */
3761 gint
3762 msgs_move_to_confirmation (GtkWindow *win,
3763                            TnyFolder *dest_folder,
3764                            gboolean delete,
3765                            TnyList *headers)
3766 {
3767         gint response = GTK_RESPONSE_OK;
3768
3769         /* return with OK if the destination is a remote folder */
3770         if (modest_tny_folder_is_remote_folder (dest_folder))
3771                 return GTK_RESPONSE_OK;
3772
3773         TnyFolder *src_folder = NULL;
3774         TnyIterator *iter = NULL;
3775         TnyHeader *header = NULL;
3776
3777         /* Get source folder */
3778         iter = tny_list_create_iterator (headers);
3779         header = TNY_HEADER (tny_iterator_get_current (iter));
3780         if (header) {
3781                 src_folder = tny_header_get_folder (header);
3782                 g_object_unref (header);
3783         }
3784         g_object_unref (iter);
3785
3786         /* if no src_folder, message may be an attahcment */
3787         if (src_folder == NULL) 
3788                 return GTK_RESPONSE_CANCEL;
3789
3790         /* If the source is a local or MMC folder */
3791         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3792                 g_object_unref (src_folder);
3793                 return GTK_RESPONSE_OK;
3794         }
3795         g_object_unref (src_folder);
3796
3797         /* now if offline we ask the user */
3798         if(connect_to_get_msg(  GTK_WINDOW (win),
3799                                         tny_list_get_length (headers)))
3800                 response = GTK_RESPONSE_OK;
3801         else
3802                 response = GTK_RESPONSE_CANCEL;
3803
3804         return response;
3805 }
3806
3807
3808
3809 static void
3810 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3811 {
3812         ModestMsgViewWindow *self = NULL;
3813
3814         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3815         self = MODEST_MSG_VIEW_WINDOW (object);
3816         
3817         if (!modest_msg_view_window_select_next_message (self))
3818                 if (!modest_msg_view_window_select_previous_message (self))
3819                         /* No more messages to view, so close this window */
3820                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3821 }
3822
3823 void
3824 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3825                                              gpointer user_data)
3826 {
3827         GObject *win = modest_mail_operation_get_source (mail_op);
3828         const GError *error = NULL;
3829         const gchar *message = NULL;
3830         
3831         /* Get error message */
3832         error = modest_mail_operation_get_error (mail_op);
3833         if (error != NULL && error->message != NULL) {
3834                 message = error->message;
3835         } else {
3836                 message = _("mail_in_ui_folder_move_target_error");
3837         }
3838         
3839         /* Show notification dialog */
3840         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3841         g_object_unref (win);
3842 }
3843
3844 void
3845 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3846                                               gpointer user_data)
3847 {
3848         GObject *win = modest_mail_operation_get_source (mail_op);
3849         const GError *error = modest_mail_operation_get_error (mail_op);
3850
3851         g_return_if_fail (error != NULL);
3852         if (error->message != NULL)             
3853                 g_printerr ("modest: %s\n", error->message);
3854         else
3855                 g_printerr ("modest: unkonw error on send&receive operation");
3856
3857         /* Show error message */
3858 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3859 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3860 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3861 /*      else  */
3862 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3863 /*                                                      _CS("sfil_ib_unable_to_send")); */
3864         g_object_unref (win);
3865 }
3866
3867 static void
3868 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3869                        TnyHeader *header, 
3870                        TnyMsg *msg, 
3871                        gpointer user_data)
3872 {
3873         TnyList *parts;
3874         TnyIterator *iter;
3875         gint pending_purges = 0;
3876         gboolean some_purged = FALSE;
3877         ModestWindow *win = MODEST_WINDOW (user_data);
3878         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3879
3880         /* If there was any error */
3881         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3882                 modest_window_mgr_unregister_header (mgr, header);
3883                 return;
3884         }
3885
3886         /* Once the message has been retrieved for purging, we check if
3887          * it's all ok for purging */
3888
3889         parts = tny_simple_list_new ();
3890         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3891         iter = tny_list_create_iterator (parts);
3892
3893         while (!tny_iterator_is_done (iter)) {
3894                 TnyMimePart *part;
3895                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3896                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3897                         if (tny_mime_part_is_purged (part))
3898                                 some_purged = TRUE;
3899                         else
3900                                 pending_purges++;
3901                 }
3902
3903                 if (part)
3904                         g_object_unref (part);
3905
3906                 tny_iterator_next (iter);
3907         }
3908
3909         if (pending_purges>0) {
3910                 gint response;
3911                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3912
3913                 if (response == GTK_RESPONSE_OK) {
3914                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3915                         tny_iterator_first (iter);
3916                         while (!tny_iterator_is_done (iter)) {
3917                                 TnyMimePart *part;
3918                                 
3919                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3920                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
3921                                         tny_mime_part_set_purged (part);
3922
3923                                 if (part)
3924                                         g_object_unref (part);
3925
3926                                 tny_iterator_next (iter);
3927                         }
3928                         
3929                         tny_msg_rewrite_cache (msg);
3930                 }
3931         } else {
3932                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3933         }
3934
3935         /* remove attachments */
3936         tny_iterator_first (iter);
3937         while (!tny_iterator_is_done (iter)) {
3938                 TnyMimePart *part;
3939                         
3940                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3941                 if (part) {
3942                         /* One for the reference given by tny_iterator_get_current(): */
3943                         g_object_unref (part);
3944
3945                         /* TODO: Is this meant to remove the attachment by doing another unref()? 
3946                          * Otherwise, this seems useless. */
3947                 }
3948
3949                 tny_iterator_next (iter);
3950         }
3951         modest_window_mgr_unregister_header (mgr, header);
3952
3953         g_object_unref (iter);
3954         g_object_unref (parts);
3955 }
3956
3957 static void
3958 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3959                                                      ModestMainWindow *win)
3960 {
3961         GtkWidget *header_view;
3962         TnyList *header_list;
3963         TnyIterator *iter;
3964         TnyHeader *header;
3965         TnyHeaderFlags flags;
3966         ModestWindow *msg_view_window =  NULL;
3967         gboolean found;
3968
3969         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3970
3971         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3972                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3973
3974         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3975
3976         if (tny_list_get_length (header_list) == 1) {
3977                 iter = tny_list_create_iterator (header_list);
3978                 header = TNY_HEADER (tny_iterator_get_current (iter));
3979                 g_object_unref (iter);
3980         } else {
3981                 return;
3982         }
3983
3984         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3985                                                           header, &msg_view_window);
3986         flags = tny_header_get_flags (header);
3987         if (!(flags & TNY_HEADER_FLAG_CACHED))
3988                 return;
3989         if (found) {
3990                 if (msg_view_window != NULL) 
3991                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3992                 else {
3993                         /* do nothing; uid was registered before, so window is probably on it's way */
3994                         g_warning ("debug: header %p has already been registered", header);
3995                 }
3996         } else {
3997                 ModestMailOperation *mail_op = NULL;
3998                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3999                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4000                                                                          G_OBJECT (win),
4001                                                                          modest_ui_actions_get_msgs_full_error_handler,
4002                                                                          NULL);
4003                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4004                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4005                 
4006                 g_object_unref (mail_op);
4007         }
4008         if (header)
4009                 g_object_unref (header);
4010         if (header_list)
4011                 g_object_unref (header_list);
4012 }
4013
4014 /**
4015  * Utility function that transfer messages from both the main window
4016  * and the msg view window when using the "Move to" dialog
4017  */
4018 static void
4019 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4020                                               ModestWindow *win)
4021 {
4022         TnyList *headers = NULL;
4023         gint response = 0;
4024         TnyAccount *dst_account = NULL;
4025         const gchar *proto_str = NULL;
4026         gboolean dst_is_pop = FALSE;
4027
4028         if (!TNY_IS_FOLDER (dst_folder)) {
4029                 modest_platform_information_banner (GTK_WIDGET (win),
4030                                                     NULL,
4031                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4032                 return;
4033         }
4034
4035         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4036         proto_str = tny_account_get_proto (dst_account);
4037
4038         /* tinymail will return NULL for local folders it seems */
4039         dst_is_pop = proto_str &&
4040                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4041                  MODEST_PROTOCOL_STORE_POP);
4042
4043         g_object_unref (dst_account);
4044
4045         /* Get selected headers */
4046         headers = get_selected_headers (MODEST_WINDOW (win));
4047
4048         if (dst_is_pop) {
4049                 modest_platform_information_banner (GTK_WIDGET (win),
4050                                                     NULL,
4051                                                     ngettext("mail_in_ui_folder_move_target_error",
4052                                                              "mail_in_ui_folder_move_targets_error",
4053                                                              tny_list_get_length (headers)));
4054                 g_object_unref (headers);
4055                 return;
4056         }
4057
4058         /* Ask for user confirmation */
4059         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
4060                                               TNY_FOLDER (dst_folder), 
4061                                               TRUE,
4062                                               headers);
4063
4064         /* Transfer messages */
4065         if (response == GTK_RESPONSE_OK) {
4066                 ModestMailOperation *mail_op = 
4067                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4068                                                                        G_OBJECT(win),
4069                                                                        modest_ui_actions_move_folder_error_handler,
4070                                                                        NULL);
4071                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4072                                                  mail_op);
4073
4074                 modest_mail_operation_xfer_msgs (mail_op, 
4075                                                  headers,
4076                                                  TNY_FOLDER (dst_folder),
4077                                                  TRUE,
4078                                                  (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
4079                                                  NULL);
4080
4081                 g_object_unref (G_OBJECT (mail_op));
4082         }
4083         g_object_unref (headers);
4084 }
4085
4086 /*
4087  * UI handler for the "Move to" action when invoked from the
4088  * ModestMainWindow
4089  */
4090 static void 
4091 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4092                                           GtkWidget *folder_view,
4093                                           TnyFolderStore *dst_folder,
4094                                           ModestMainWindow *win)
4095 {
4096         ModestHeaderView *header_view = NULL;
4097         ModestMailOperation *mail_op = NULL;
4098         TnyFolderStore *src_folder;
4099         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4100
4101         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4102
4103         /* Get the source folder */
4104         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4105
4106         /* Get header view */
4107         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW));
4108
4109         /* Get folder or messages to transfer */
4110         if (gtk_widget_is_focus (folder_view)) {
4111                 GtkTreeSelection *sel;
4112                 gboolean do_xfer = TRUE;
4113
4114                 /* Allow only to transfer folders to the local root folder */
4115                 if (TNY_IS_ACCOUNT (dst_folder) && 
4116                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4117                         do_xfer = FALSE;
4118                 } else if (!TNY_IS_FOLDER (src_folder)) {
4119                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4120                         do_xfer = FALSE;
4121                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4122                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER(src_folder));
4123                         if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4124                                 do_xfer = FALSE;
4125                         }
4126                 }
4127
4128                 if (do_xfer) {
4129                         /* Clean folder on header view before moving it */
4130                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4131                         gtk_tree_selection_unselect_all (sel);
4132
4133                         mail_op =
4134                           modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4135                                                                          G_OBJECT(win),
4136                                                                          modest_ui_actions_move_folder_error_handler,
4137                                                                          NULL);
4138                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4139                                                          mail_op);
4140
4141                         /* Select *after* the changes */
4142                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
4143                                                           TNY_FOLDER (src_folder), TRUE);
4144
4145                         modest_mail_operation_xfer_folder (mail_op,
4146                                                            TNY_FOLDER (src_folder),
4147                                                            dst_folder,
4148                                                            TRUE, NULL, NULL);
4149                         /* Unref mail operation */
4150                         g_object_unref (G_OBJECT (mail_op));
4151                 }
4152         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4153                 gboolean do_xfer = TRUE;
4154                 /* Ask for confirmation if the source folder is remote and we're not connected */
4155                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4156                         guint num_headers = modest_header_view_count_selected_headers(header_view);
4157                         if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4158                                 do_xfer = FALSE;
4159                         }
4160                 }
4161                 if (do_xfer) /* Transfer messages */
4162                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4163         }
4164
4165     if (src_folder)
4166         g_object_unref (src_folder);
4167 }
4168
4169
4170 /*
4171  * UI handler for the "Move to" action when invoked from the
4172  * ModestMsgViewWindow
4173  */
4174 static void 
4175 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4176                                               TnyFolderStore *dst_folder,
4177                                               ModestMsgViewWindow *win)
4178 {
4179         TnyHeader *header = NULL;
4180         TnyFolderStore *src_folder;
4181
4182         /* Create header list */
4183         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4184         src_folder = TNY_FOLDER_STORE(tny_header_get_folder(header));
4185         g_object_unref (header);
4186
4187         /* Transfer the message if online or confirmed by the user */
4188         if (tny_device_is_online (modest_runtime_get_device()) ||
4189             (modest_platform_is_network_folderstore(src_folder) && connect_to_get_msg(GTK_WINDOW(win), 1))) {
4190                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4191         }
4192
4193         g_object_unref (src_folder);
4194 }
4195
4196 void 
4197 modest_ui_actions_on_move_to (GtkAction *action, 
4198                               ModestWindow *win)
4199 {
4200         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4201         gint result = 0;
4202         TnyFolderStore *dst_folder = NULL;
4203         ModestMainWindow *main_window;
4204
4205         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4206                           MODEST_IS_MSG_VIEW_WINDOW (win));
4207
4208         /* Get the main window if exists */
4209         if (MODEST_IS_MAIN_WINDOW (win))
4210                 main_window = MODEST_MAIN_WINDOW (win);
4211         else
4212                 main_window = 
4213                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4214
4215         /* Get the folder view widget if exists */
4216         if (main_window)
4217                 folder_view = modest_main_window_get_child_widget (main_window,
4218                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
4219         else
4220                 folder_view = NULL;
4221
4222         /* Create and run the dialog */
4223         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4224         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4225         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4226         result = gtk_dialog_run (GTK_DIALOG(dialog));
4227         g_object_ref (tree_view);
4228         gtk_widget_destroy (dialog);
4229
4230         if (result != GTK_RESPONSE_ACCEPT)
4231                 return;
4232
4233         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4234         /* Do window specific stuff */
4235         if (MODEST_IS_MAIN_WINDOW (win)) {
4236                 modest_ui_actions_on_main_window_move_to (action,
4237                                                           folder_view,
4238                                                           dst_folder,
4239                                                           MODEST_MAIN_WINDOW (win));
4240         } else {
4241                 modest_ui_actions_on_msg_view_window_move_to (action,
4242                                                               dst_folder,
4243                                                               MODEST_MSG_VIEW_WINDOW (win));
4244         }
4245
4246         if (dst_folder)
4247                 g_object_unref (dst_folder);
4248 }
4249
4250 /*
4251  * Calls #HeadersFunc for each header already selected in the main
4252  * window or the message currently being shown in the msg view window
4253  */
4254 static void
4255 do_headers_action (ModestWindow *win, 
4256                    HeadersFunc func,
4257                    gpointer user_data)
4258 {
4259         TnyList *headers_list = NULL;
4260         TnyIterator *iter = NULL;
4261         TnyHeader *header = NULL;
4262         TnyFolder *folder = NULL;
4263
4264         /* Get headers */
4265         headers_list = get_selected_headers (win);
4266         if (!headers_list)
4267                 return;
4268
4269         /* Get the folder */
4270         iter = tny_list_create_iterator (headers_list);
4271         header = TNY_HEADER (tny_iterator_get_current (iter));
4272         if (header) {
4273                 folder = tny_header_get_folder (header);
4274                 g_object_unref (header);
4275         }
4276
4277         /* Call the function for each header */
4278         while (!tny_iterator_is_done (iter)) {
4279                 header = TNY_HEADER (tny_iterator_get_current (iter));
4280                 func (header, win, user_data);
4281                 g_object_unref (header);
4282                 tny_iterator_next (iter);
4283         }
4284
4285         /* Trick: do a poke status in order to speed up the signaling
4286            of observers */
4287         tny_folder_poke_status (folder);
4288
4289         /* Frees */
4290         g_object_unref (folder);
4291         g_object_unref (iter);
4292         g_object_unref (headers_list);
4293 }
4294
4295 void 
4296 modest_ui_actions_view_attachment (GtkAction *action,
4297                                    ModestWindow *window)
4298 {
4299         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4300                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4301         } else {
4302                 /* not supported window for this action */
4303                 g_return_if_reached ();
4304         }
4305 }
4306
4307 void
4308 modest_ui_actions_save_attachments (GtkAction *action,
4309                                     ModestWindow *window)
4310 {
4311         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4312                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4313         } else {
4314                 /* not supported window for this action */
4315                 g_return_if_reached ();
4316         }
4317 }
4318
4319 void
4320 modest_ui_actions_remove_attachments (GtkAction *action,
4321                                       ModestWindow *window)
4322 {
4323         if (MODEST_IS_MAIN_WINDOW (window)) {
4324                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4325         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4326                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4327         } else {
4328                 /* not supported window for this action */
4329                 g_return_if_reached ();
4330         }
4331 }
4332
4333 void 
4334 modest_ui_actions_on_settings (GtkAction *action, 
4335                                ModestWindow *win)
4336 {
4337         GtkWidget *dialog;
4338
4339         dialog = modest_platform_get_global_settings_dialog ();
4340         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4341         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4342         gtk_widget_show_all (dialog);
4343
4344         gtk_dialog_run (GTK_DIALOG (dialog));
4345
4346         gtk_widget_destroy (dialog);
4347 }
4348
4349 void 
4350 modest_ui_actions_on_help (GtkAction *action, 
4351                            ModestWindow *win)
4352 {
4353         const gchar *help_id = NULL;
4354
4355         if (MODEST_IS_MAIN_WINDOW (win)) {
4356                 const gchar *action_name;
4357                 action_name = gtk_action_get_name (action);
4358
4359                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
4360                     !strcmp (action_name, "HeaderViewCSMHelp")) {
4361                         GtkWidget *folder_view;
4362                         TnyFolderStore *folder_store;
4363                         /* Get selected folder */
4364                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4365                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
4366                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4367
4368                         /* Switch help_id */
4369                         if (TNY_IS_FOLDER (folder_store)) {
4370                                 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4371                                 case TNY_FOLDER_TYPE_NORMAL:
4372                                         help_id = "applications_email_managefolders";
4373                                         break;
4374                                 case TNY_FOLDER_TYPE_INBOX:
4375                                         help_id = "applications_email_inbox";
4376                                         break;
4377                                 case TNY_FOLDER_TYPE_OUTBOX:
4378                                         help_id = "applications_email_outbox";
4379                                         break;
4380                                 case TNY_FOLDER_TYPE_SENT:
4381                                         help_id = "applications_email_sent";
4382                                         break;
4383                                 case TNY_FOLDER_TYPE_DRAFTS:
4384                                         help_id = "applications_email_drafts";
4385                                         break;
4386                                 case TNY_FOLDER_TYPE_ARCHIVE:
4387                                         help_id = "applications_email_managefolders";
4388                                         break;
4389                                 default:
4390                                         help_id = "applications_email_managefolders";
4391                                 }
4392                         } else {
4393                                 help_id = "applications_email_mainview";        
4394                         }
4395                         g_object_unref (folder_store);
4396                 } else {
4397                         help_id = "applications_email_mainview";        
4398                 }
4399         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4400                 help_id = "applications_email_viewer";
4401         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4402                 help_id = "applications_email_editor";
4403
4404         modest_platform_show_help (GTK_WINDOW (win), help_id);
4405 }
4406
4407 void 
4408 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4409                                             ModestWindow *window)
4410 {
4411         ModestMailOperation *mail_op;
4412         TnyList *headers;
4413
4414         /* Get headers */
4415         headers = get_selected_headers (window);
4416         if (!headers)
4417                 return;
4418
4419         /* Create mail operation */
4420         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4421                                                                  G_OBJECT (window),
4422                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4423                                                                  NULL);
4424         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4425         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4426
4427         /* Frees */
4428         g_object_unref (headers);
4429         g_object_unref (mail_op);
4430 }
4431
4432 void
4433 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4434                                           ModestWindow *window)
4435 {
4436         g_return_if_fail (MODEST_IS_WINDOW (window));
4437         
4438         /* Update dimmed */     
4439         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4440 }
4441
4442 void
4443 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4444                                           ModestWindow *window)
4445 {
4446         g_return_if_fail (MODEST_IS_WINDOW (window));
4447
4448         /* Update dimmed */     
4449         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4450 }
4451
4452 void
4453 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4454                                           ModestWindow *window)
4455 {
4456         g_return_if_fail (MODEST_IS_WINDOW (window));
4457
4458         /* Update dimmed */     
4459         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4460 }
4461
4462 void
4463 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4464                                           ModestWindow *window)
4465 {
4466         g_return_if_fail (MODEST_IS_WINDOW (window));
4467
4468         /* Update dimmed */     
4469         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4470 }
4471
4472 void
4473 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4474                                           ModestWindow *window)
4475 {
4476         g_return_if_fail (MODEST_IS_WINDOW (window));
4477
4478         /* Update dimmed */     
4479         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4480 }
4481
4482 void
4483 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4484                                                  ModestWindow *window)
4485 {
4486         g_return_if_fail (MODEST_IS_WINDOW (window));
4487
4488         /* Update dimmed */     
4489         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4490 }
4491
4492 void
4493 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4494                                                      ModestWindow *window)
4495 {
4496         g_return_if_fail (MODEST_IS_WINDOW (window));
4497
4498         /* Update dimmed */     
4499         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4500 }
4501
4502 void
4503 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4504                                                      ModestWindow *window)
4505 {
4506         g_return_if_fail (MODEST_IS_WINDOW (window));
4507
4508         /* Update dimmed */     
4509         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4510 }
4511
4512 void
4513 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4514 {
4515         g_return_if_fail (MODEST_IS_WINDOW (window));
4516
4517         /* Update dimmed */     
4518         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4519 }
4520
4521 void
4522 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4523 {
4524         g_return_if_fail (MODEST_IS_WINDOW (window));
4525
4526         modest_platform_show_search_messages (GTK_WINDOW (window));
4527 }
4528
4529 void     
4530 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4531 {
4532         g_return_if_fail (MODEST_IS_WINDOW (win));
4533         modest_platform_show_addressbook (GTK_WINDOW (win));
4534 }
4535
4536
4537 void
4538 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4539                                           ModestWindow *window)
4540 {
4541         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4542
4543         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4544 }
4545
4546 static void 
4547 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4548                                    ModestMailOperationState *state,
4549                                    gpointer user_data)
4550 {
4551         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4552
4553         /* Set send/receive operation finished */       
4554         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4555                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4556         
4557 }
4558
4559