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