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