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