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