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