* Now the current folder is only refreshed in the s&r if the update account operatio...
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved. 
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29  
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
57
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
70
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
74
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
81
82 #include <gtkhtml/gtkhtml.h>
83
84 typedef struct _GetMsgAsyncHelper {     
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;     
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         GtkWidget *parent_window;
104 } ReplyForwardHelper;
105
106 typedef struct _MoveToHelper {
107         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         delete_folder (main_window, FALSE);
2775 }
2776
2777 void 
2778 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2779 {
2780         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2781         
2782         delete_folder (main_window, TRUE);
2783 }
2784
2785
2786 static void
2787 show_error (GtkWidget *parent_widget, const gchar* text)
2788 {
2789         hildon_banner_show_information(parent_widget, NULL, text);
2790         
2791 #if 0
2792         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2793         /*
2794           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2795           (GtkDialogFlags)0,
2796           GTK_MESSAGE_ERROR,
2797           GTK_BUTTONS_OK,
2798           text ));
2799         */
2800                  
2801         gtk_dialog_run (dialog);
2802         gtk_widget_destroy (GTK_WIDGET (dialog));
2803 #endif
2804 }
2805
2806 void
2807 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2808                                          const gchar* server_account_name,
2809                                          gchar **username,
2810                                          gchar **password, 
2811                                          gboolean *cancel, 
2812                                          gboolean *remember,
2813                                          ModestMainWindow *main_window)
2814 {
2815         g_return_if_fail(server_account_name);
2816         
2817         /* Initalize output parameters: */
2818         if (cancel)
2819                 *cancel = FALSE;
2820                 
2821         if (remember)
2822                 *remember = TRUE;
2823                 
2824 #ifdef MODEST_PLATFORM_MAEMO
2825         /* Maemo uses a different (awkward) button order,
2826          * It should probably just use gtk_alternative_dialog_button_order ().
2827          */
2828         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2829                                               NULL,
2830                                               GTK_DIALOG_MODAL,
2831                                               _("mcen_bd_dialog_ok"),
2832                                               GTK_RESPONSE_ACCEPT,
2833                                               _("mcen_bd_dialog_cancel"),
2834                                               GTK_RESPONSE_REJECT,
2835                                               NULL);
2836 #else
2837         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2838                                               NULL,
2839                                               GTK_DIALOG_MODAL,
2840                                               GTK_STOCK_CANCEL,
2841                                               GTK_RESPONSE_REJECT,
2842                                               GTK_STOCK_OK,
2843                                               GTK_RESPONSE_ACCEPT,
2844                                               NULL);
2845 #endif /* MODEST_PLATFORM_MAEMO */
2846
2847         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2848         
2849         gchar *server_name = modest_account_mgr_get_server_account_hostname (
2850                 modest_runtime_get_account_mgr(), server_account_name);
2851         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2852                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2853                 if (cancel)
2854                         *cancel = TRUE;
2855                 return;
2856         }
2857         
2858         /* This causes a warning because the logical ID has no %s in it, 
2859          * though the translation does, but there is not much we can do about that: */
2860         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2861         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2862                             FALSE, FALSE, 0);
2863         g_free (txt);
2864         g_free (server_name);
2865         server_name = NULL;
2866
2867         /* username: */
2868         gchar *initial_username = modest_account_mgr_get_server_account_username (
2869                 modest_runtime_get_account_mgr(), server_account_name);
2870         
2871         GtkWidget *entry_username = gtk_entry_new ();
2872         if (initial_username)
2873                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2874         /* Dim this if a connection has ever succeeded with this username,
2875          * as per the UI spec: */
2876         const gboolean username_known = 
2877                 modest_account_mgr_get_server_account_username_has_succeeded(
2878                         modest_runtime_get_account_mgr(), server_account_name);
2879         gtk_widget_set_sensitive (entry_username, !username_known);
2880         
2881 #ifdef MODEST_PLATFORM_MAEMO
2882         /* Auto-capitalization is the default, so let's turn it off: */
2883         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2884         
2885         /* Create a size group to be used by all captions.
2886          * Note that HildonCaption does not create a default size group if we do not specify one.
2887          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2888         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2889         
2890         GtkWidget *caption = hildon_caption_new (sizegroup, 
2891                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2892         gtk_widget_show (entry_username);
2893         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2894                 FALSE, FALSE, MODEST_MARGIN_HALF);
2895         gtk_widget_show (caption);
2896 #else 
2897         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2898                             TRUE, FALSE, 0);
2899 #endif /* MODEST_PLATFORM_MAEMO */      
2900                             
2901         /* password: */
2902         GtkWidget *entry_password = gtk_entry_new ();
2903         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2904         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2905         
2906 #ifdef MODEST_PLATFORM_MAEMO
2907         /* Auto-capitalization is the default, so let's turn it off: */
2908         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2909                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2910         
2911         caption = hildon_caption_new (sizegroup, 
2912                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2913         gtk_widget_show (entry_password);
2914         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2915                 FALSE, FALSE, MODEST_MARGIN_HALF);
2916         gtk_widget_show (caption);
2917         g_object_unref (sizegroup);
2918 #else 
2919         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2920                             TRUE, FALSE, 0);
2921 #endif /* MODEST_PLATFORM_MAEMO */      
2922
2923         if (initial_username != NULL)
2924                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
2925                                 
2926 /* This is not in the Maemo UI spec:
2927         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2928         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2929                             TRUE, FALSE, 0);
2930 */
2931
2932         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2933         
2934         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2935                 if (username) {
2936                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2937                         
2938                         modest_account_mgr_set_server_account_username (
2939                                  modest_runtime_get_account_mgr(), server_account_name, 
2940                                  *username);
2941                                  
2942                         const gboolean username_was_changed = 
2943                                 (strcmp (*username, initial_username) != 0);
2944                         if (username_was_changed) {
2945                                 g_warning ("%s: tinymail does not yet support changing the "
2946                                         "username in the get_password() callback.\n", __FUNCTION__);
2947                         }
2948                 }
2949                         
2950                 if (password) {
2951                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2952                         
2953                         /* We do not save the password in the configuration, 
2954                          * because this function is only called for passwords that should 
2955                          * not be remembered:
2956                         modest_server_account_set_password (
2957                                  modest_runtime_get_account_mgr(), server_account_name, 
2958                                  *password);
2959                         */
2960                 }
2961                 
2962                 if (cancel)
2963                         *cancel   = FALSE;
2964                         
2965         } else {
2966                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2967                 
2968                 if (username)
2969                         *username = NULL;
2970                         
2971                 if (password)
2972                         *password = NULL;
2973                         
2974                 if (cancel)
2975                         *cancel   = TRUE;
2976         }
2977
2978 /* This is not in the Maemo UI spec:
2979         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2980                 *remember = TRUE;
2981         else
2982                 *remember = FALSE;
2983 */
2984
2985         gtk_widget_destroy (dialog);
2986         
2987         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2988 }
2989
2990 void
2991 modest_ui_actions_on_cut (GtkAction *action,
2992                           ModestWindow *window)
2993 {
2994         GtkWidget *focused_widget;
2995         GtkClipboard *clipboard;
2996
2997         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2998         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2999         if (GTK_IS_EDITABLE (focused_widget)) {
3000                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3001                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3002                 gtk_clipboard_store (clipboard);
3003         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3004                 GtkTextBuffer *buffer;
3005
3006                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3007                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3008                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3009                 gtk_clipboard_store (clipboard);
3010         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3011                 TnyList *header_list = modest_header_view_get_selected_headers (
3012                                 MODEST_HEADER_VIEW (focused_widget));
3013                 gboolean continue_download = FALSE;
3014                 gint num_of_unc_msgs;
3015
3016                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3017
3018                 if (num_of_unc_msgs) {
3019                         TnyAccount *account = get_account_from_header_list (header_list);
3020                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3021                         g_object_unref (account);
3022                 }
3023
3024                 if (num_of_unc_msgs == 0 || continue_download) {
3025 /*                      modest_platform_information_banner (
3026                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3027                         modest_header_view_cut_selection (
3028                                         MODEST_HEADER_VIEW (focused_widget));
3029                 }
3030
3031                 g_object_unref (header_list);
3032         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3033                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3034         }
3035 }
3036
3037 void
3038 modest_ui_actions_on_copy (GtkAction *action,
3039                            ModestWindow *window)
3040 {
3041         GtkClipboard *clipboard;
3042         GtkWidget *focused_widget;
3043         gboolean copied = TRUE;
3044
3045         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3046         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3047
3048         if (GTK_IS_LABEL (focused_widget)) {
3049                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3050                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3051                 gtk_clipboard_store (clipboard);
3052         } else if (GTK_IS_EDITABLE (focused_widget)) {
3053                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3054                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3055                 gtk_clipboard_store (clipboard);
3056         } else if (GTK_IS_HTML (focused_widget)) {
3057                 gtk_html_copy (GTK_HTML (focused_widget));
3058                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3059                 gtk_clipboard_store (clipboard);
3060         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3061                 GtkTextBuffer *buffer;
3062                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3063                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3064                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3065                 gtk_clipboard_store (clipboard);
3066         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3067                 TnyList *header_list = modest_header_view_get_selected_headers (
3068                                 MODEST_HEADER_VIEW (focused_widget));
3069                 gboolean continue_download = FALSE;
3070                 gint num_of_unc_msgs;
3071
3072                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3073
3074                 if (num_of_unc_msgs) {
3075                         TnyAccount *account = get_account_from_header_list (header_list);
3076                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3077                         g_object_unref (account);
3078                 }
3079
3080                 if (num_of_unc_msgs == 0 || continue_download) {
3081                         modest_platform_information_banner (
3082                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3083                         modest_header_view_copy_selection (
3084                                         MODEST_HEADER_VIEW (focused_widget));
3085                 } else
3086                         copied = FALSE;
3087
3088                 g_object_unref (header_list);
3089
3090         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3091                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3092         }
3093
3094         /* Show information banner if there was a copy to clipboard */
3095         if(copied)
3096                 modest_platform_information_banner (
3097                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3098 }
3099
3100 void
3101 modest_ui_actions_on_undo (GtkAction *action,
3102                            ModestWindow *window)
3103 {
3104         ModestEmailClipboard *clipboard = NULL;
3105
3106         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3107                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3108         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3109                 /* Clear clipboard source */
3110                 clipboard = modest_runtime_get_email_clipboard ();
3111                 modest_email_clipboard_clear (clipboard);               
3112         }
3113         else {
3114                 g_return_if_reached ();
3115         }
3116 }
3117
3118 void
3119 modest_ui_actions_on_redo (GtkAction *action,
3120                            ModestWindow *window)
3121 {
3122         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3123                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3124         }
3125         else {
3126                 g_return_if_reached ();
3127         }
3128 }
3129
3130
3131 static void
3132 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3133 {
3134         /* destroy information note */
3135         gtk_widget_destroy (GTK_WIDGET(user_data));
3136 }
3137
3138
3139 static void
3140 paste_as_attachment_free (gpointer data)
3141 {
3142         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3143
3144         gtk_widget_destroy (helper->banner);
3145         g_object_unref (helper->banner);
3146         g_free (helper);
3147 }
3148
3149 static void
3150 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3151                             TnyHeader *header,
3152                             TnyMsg *msg,
3153                             gpointer userdata)
3154 {
3155         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3156         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3157
3158         if (msg == NULL)
3159                 return;
3160
3161         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3162         
3163 }
3164
3165 void
3166 modest_ui_actions_on_paste (GtkAction *action,
3167                             ModestWindow *window)
3168 {
3169         GtkWidget *focused_widget = NULL;
3170         GtkWidget *inf_note = NULL;
3171         ModestMailOperation *mail_op = NULL;
3172
3173         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3174         if (GTK_IS_EDITABLE (focused_widget)) {
3175                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3176         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3177                 ModestEmailClipboard *e_clipboard = NULL;
3178                 e_clipboard = modest_runtime_get_email_clipboard ();
3179                 if (modest_email_clipboard_cleared (e_clipboard)) {
3180                         GtkTextBuffer *buffer;
3181                         GtkClipboard *clipboard;
3182
3183                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3184                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3185                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3186                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3187                         ModestMailOperation *mail_op;
3188                         TnyFolder *src_folder;
3189                         TnyList *data;
3190                         gboolean delete;
3191                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3192                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3193                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3194                                                                            _CS("ckct_nw_pasting"));
3195                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3196                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3197                         if (helper->banner != NULL) {
3198                                 g_object_ref (G_OBJECT (helper->banner));
3199                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3200                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3201                         }
3202
3203                         if (data != NULL) {
3204                                 modest_mail_operation_get_msgs_full (mail_op, 
3205                                                                      data,
3206                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3207                                                                      helper,
3208                                                                      paste_as_attachment_free);
3209                         }
3210                 }
3211         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3212                 ModestEmailClipboard *clipboard = NULL;
3213                 TnyFolder *src_folder = NULL;
3214                 TnyFolderStore *folder_store = NULL;
3215                 TnyList *data = NULL;           
3216                 gboolean delete = FALSE;
3217                 
3218                 /* Check clipboard source */
3219                 clipboard = modest_runtime_get_email_clipboard ();
3220                 if (modest_email_clipboard_cleared (clipboard)) 
3221                         return;
3222                 
3223                 /* Get elements to paste */
3224                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3225
3226                 /* Create a new mail operation */
3227                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3228                 
3229                 /* Get destination folder */
3230                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3231
3232                 /* transfer messages  */
3233                 if (data != NULL) {
3234                         gint response = 0;
3235
3236                         /* Ask for user confirmation */
3237                         response = 
3238                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3239                                                                              TNY_FOLDER (folder_store), 
3240                                                                              delete,
3241                                                                              data);
3242                         
3243                         if (response == GTK_RESPONSE_OK) {
3244                                 /* Launch notification */
3245                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3246                                                                              _CS("ckct_nw_pasting"));
3247                                 if (inf_note != NULL)  {
3248                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3249                                         gtk_widget_show (GTK_WIDGET(inf_note));
3250                                 }
3251
3252                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3253                                 modest_mail_operation_xfer_msgs (mail_op, 
3254                                                                  data,
3255                                                                  TNY_FOLDER (folder_store),
3256                                                                  delete,
3257                                                                  destroy_information_note,
3258                                                                  inf_note);                             
3259                         } else {
3260                                 g_object_unref (mail_op);
3261                         }
3262                         
3263                 } else if (src_folder != NULL) {                        
3264                         /* Launch notification */
3265                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3266                                                                      _CS("ckct_nw_pasting"));
3267                         if (inf_note != NULL)  {
3268                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3269                                 gtk_widget_show (GTK_WIDGET(inf_note));
3270                         }
3271                         
3272                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3273                         modest_mail_operation_xfer_folder (mail_op, 
3274                                                            src_folder,
3275                                                            folder_store,
3276                                                            delete,
3277                                                            destroy_information_note,
3278                                                            inf_note);
3279                 }
3280
3281                 /* Free */
3282                 if (data != NULL) 
3283                         g_object_unref (data);
3284                 if (src_folder != NULL) 
3285                         g_object_unref (src_folder);
3286                 if (folder_store != NULL) 
3287                         g_object_unref (folder_store);
3288         }
3289 }
3290
3291
3292 void
3293 modest_ui_actions_on_select_all (GtkAction *action,
3294                                  ModestWindow *window)
3295 {
3296         GtkWidget *focused_widget;
3297
3298         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3299         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3300                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3301         } else if (GTK_IS_LABEL (focused_widget)) {
3302                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3303         } else if (GTK_IS_EDITABLE (focused_widget)) {
3304                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3305         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3306                 GtkTextBuffer *buffer;
3307                 GtkTextIter start, end;
3308
3309                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3310                 gtk_text_buffer_get_start_iter (buffer, &start);
3311                 gtk_text_buffer_get_end_iter (buffer, &end);
3312                 gtk_text_buffer_select_range (buffer, &start, &end);
3313         } else if (GTK_IS_HTML (focused_widget)) {
3314                 gtk_html_select_all (GTK_HTML (focused_widget));
3315         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3316                 GtkWidget *header_view = focused_widget;
3317                 GtkTreeSelection *selection = NULL;
3318                 
3319                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3320                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3321                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3322                 }
3323                                 
3324                 /* Disable window dimming management */
3325                 modest_window_disable_dimming (MODEST_WINDOW(window));
3326                 
3327                 /* Select all messages */
3328                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3329                 gtk_tree_selection_select_all (selection);
3330
3331                 /* Set focuse on header view */
3332                 gtk_widget_grab_focus (header_view);
3333
3334
3335                 /* Enable window dimming management */
3336                 modest_window_enable_dimming (MODEST_WINDOW(window));
3337                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3338         }
3339
3340 }
3341
3342 void
3343 modest_ui_actions_on_mark_as_read (GtkAction *action,
3344                                    ModestWindow *window)
3345 {       
3346         g_return_if_fail (MODEST_IS_WINDOW(window));
3347                 
3348         /* Mark each header as read */
3349         do_headers_action (window, headers_action_mark_as_read, NULL);
3350 }
3351
3352 void
3353 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3354                                      ModestWindow *window)
3355 {       
3356         g_return_if_fail (MODEST_IS_WINDOW(window));
3357                 
3358         /* Mark each header as read */
3359         do_headers_action (window, headers_action_mark_as_unread, NULL);
3360 }
3361
3362 void
3363 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3364                                   GtkRadioAction *selected,
3365                                   ModestWindow *window)
3366 {
3367         gint value;
3368
3369         value = gtk_radio_action_get_current_value (selected);
3370         if (MODEST_IS_WINDOW (window)) {
3371                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3372         }
3373 }
3374
3375 void     
3376 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3377                                                GtkRadioAction *selected,
3378                                                ModestWindow *window)
3379 {
3380         TnyHeaderFlags flags;
3381         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3382
3383         flags = gtk_radio_action_get_current_value (selected);
3384         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3385 }
3386
3387 void     
3388 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3389                                                   GtkRadioAction *selected,
3390                                                   ModestWindow *window)
3391 {
3392         gint file_format;
3393
3394         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3395
3396         file_format = gtk_radio_action_get_current_value (selected);
3397         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3398 }
3399
3400
3401 void     
3402 modest_ui_actions_on_zoom_plus (GtkAction *action,
3403                                 ModestWindow *window)
3404 {
3405         g_return_if_fail (MODEST_IS_WINDOW (window));
3406
3407         modest_window_zoom_plus (MODEST_WINDOW (window));
3408 }
3409
3410 void     
3411 modest_ui_actions_on_zoom_minus (GtkAction *action,
3412                                  ModestWindow *window)
3413 {
3414         g_return_if_fail (MODEST_IS_WINDOW (window));
3415
3416         modest_window_zoom_minus (MODEST_WINDOW (window));
3417 }
3418
3419 void     
3420 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3421                                            ModestWindow *window)
3422 {
3423         ModestWindowMgr *mgr;
3424         gboolean fullscreen, active;
3425         g_return_if_fail (MODEST_IS_WINDOW (window));
3426
3427         mgr = modest_runtime_get_window_mgr ();
3428
3429         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3430         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3431
3432         if (active != fullscreen) {
3433                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3434                 gtk_window_present (GTK_WINDOW (window));
3435         }
3436 }
3437
3438 void
3439 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3440                                         ModestWindow *window)
3441 {
3442         ModestWindowMgr *mgr;
3443         gboolean fullscreen;
3444
3445         g_return_if_fail (MODEST_IS_WINDOW (window));
3446
3447         mgr = modest_runtime_get_window_mgr ();
3448         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3449         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3450
3451         gtk_window_present (GTK_WINDOW (window));
3452 }
3453
3454 /* 
3455  * Used by modest_ui_actions_on_details to call do_headers_action 
3456  */
3457 static void
3458 headers_action_show_details (TnyHeader *header, 
3459                              ModestWindow *window,
3460                              gpointer user_data)
3461
3462 {
3463         GtkWidget *dialog;
3464         
3465         /* Create dialog */
3466         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3467
3468         /* Run dialog */
3469         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3470         gtk_widget_show_all (dialog);
3471         gtk_dialog_run (GTK_DIALOG (dialog));
3472
3473         gtk_widget_destroy (dialog);
3474 }
3475
3476 /*
3477  * Show the folder details in a ModestDetailsDialog widget
3478  */
3479 static void
3480 show_folder_details (TnyFolder *folder, 
3481                      GtkWindow *window)
3482 {
3483         GtkWidget *dialog;
3484         
3485         /* Create dialog */
3486         dialog = modest_details_dialog_new_with_folder (window, folder);
3487
3488         /* Run dialog */
3489         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3490         gtk_widget_show_all (dialog);
3491         gtk_dialog_run (GTK_DIALOG (dialog));
3492
3493         gtk_widget_destroy (dialog);
3494 }
3495
3496 /*
3497  * Show the header details in a ModestDetailsDialog widget
3498  */
3499 void     
3500 modest_ui_actions_on_details (GtkAction *action, 
3501                               ModestWindow *win)
3502 {
3503         TnyList * headers_list;
3504         TnyIterator *iter;
3505         TnyHeader *header;              
3506
3507         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3508                 TnyMsg *msg;
3509
3510                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3511                 if (!msg)
3512                         return;
3513                 g_object_unref (msg);           
3514
3515                 headers_list = get_selected_headers (win);
3516                 if (!headers_list)
3517                         return;
3518
3519                 iter = tny_list_create_iterator (headers_list);
3520
3521                 header = TNY_HEADER (tny_iterator_get_current (iter));
3522                 if (header) {
3523                         headers_action_show_details (header, win, NULL);
3524                         g_object_unref (header);
3525                 }
3526
3527                 g_object_unref (iter);
3528                 g_object_unref (headers_list);
3529
3530         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3531                 GtkWidget *folder_view, *header_view;
3532
3533                 /* Check which widget has the focus */
3534                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3535                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3536                 if (gtk_widget_is_focus (folder_view)) {
3537                         TnyFolderStore *folder_store
3538                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3539                         if (!folder_store) {
3540                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3541                                 return; 
3542                         }
3543                         /* Show only when it's a folder */
3544                         /* This function should not be called for account items, 
3545                          * because we dim the menu item for them. */
3546                         if (TNY_IS_FOLDER (folder_store)) {
3547                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3548                         }
3549
3550                         g_object_unref (folder_store);
3551
3552                 } else {
3553                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3554                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3555                         /* Show details of each header */
3556                         do_headers_action (win, headers_action_show_details, header_view);
3557                 }
3558         }
3559 }
3560
3561 void     
3562 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3563                                      ModestMsgEditWindow *window)
3564 {
3565         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3566
3567         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3568 }
3569
3570 void     
3571 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3572                                       ModestMsgEditWindow *window)
3573 {
3574         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3575
3576         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3577 }
3578
3579 void
3580 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3581                                        ModestMainWindow *main_window)
3582 {
3583         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3584
3585         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3586                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3587         else
3588                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3589 }
3590
3591 void 
3592 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3593                                      ModestWindow *window)
3594 {
3595         gboolean active, fullscreen = FALSE;
3596         ModestWindowMgr *mgr;
3597
3598         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3599
3600         /* Check if we want to toggle the toolbar vuew in fullscreen
3601            or normal mode */
3602         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3603                      "ViewShowToolbarFullScreen")) {
3604                 fullscreen = TRUE;
3605         }
3606
3607         /* Toggle toolbar */
3608         mgr = modest_runtime_get_window_mgr ();
3609         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3610 }
3611
3612 void     
3613 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3614                                            ModestMsgEditWindow *window)
3615 {
3616         modest_msg_edit_window_select_font (window);
3617 }
3618
3619 void
3620 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3621                                                   const gchar *display_name,
3622                                                   GtkWindow *window)
3623 {
3624         /* Do not change the application name if the widget has not
3625            the focus. This callback could be called even if the folder
3626            view has not the focus, because the handled signal could be
3627            emitted when the folder view is redrawn */
3628         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3629                 if (display_name)
3630                         gtk_window_set_title (window, display_name);
3631                 else
3632                         gtk_window_set_title (window, " ");
3633         }
3634 }
3635
3636 void
3637 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3638 {
3639         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3640         modest_msg_edit_window_select_contacts (window);
3641 }
3642
3643 void
3644 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3645 {
3646         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3647         modest_msg_edit_window_check_names (window, FALSE);
3648 }
3649
3650 static void
3651 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3652 {
3653         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3654                                          GTK_WIDGET (user_data));
3655 }
3656
3657 /*
3658  * This function is used to track changes in the selection of the
3659  * folder view that is inside the "move to" dialog to enable/disable
3660  * the OK button because we do not want the user to select a disallowed
3661  * destination for a folder.
3662  * The user also not desired to be able to use NEW button on items where
3663  * folder creation is not possibel.
3664  */
3665 static void
3666 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3667                                             TnyFolderStore *folder_store,
3668                                             gboolean selected,
3669                                             gpointer user_data)
3670 {
3671         GtkWidget *dialog = NULL;
3672         GtkWidget *ok_button = NULL, *new_button = NULL;
3673         GList *children = NULL;
3674         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3675         gboolean moving_folder = FALSE;
3676         gboolean is_local_account = TRUE;
3677         GtkWidget *folder_view = NULL;
3678         ModestTnyFolderRules rules;
3679
3680         if (!selected)
3681                 return;
3682
3683         /* Get the OK button */
3684         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3685         if (!dialog)
3686                 return;
3687
3688         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3689         ok_button = GTK_WIDGET (children->next->next->data);
3690         new_button = GTK_WIDGET (children->next->data);
3691         g_list_free (children);
3692
3693         /* check if folder_store is an remote account */
3694         if (TNY_IS_ACCOUNT (folder_store)) {
3695                 TnyAccount *local_account = NULL;
3696                 TnyAccount *mmc_account = NULL;
3697                 ModestTnyAccountStore *account_store = NULL;
3698
3699                 account_store = modest_runtime_get_account_store ();
3700                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3701                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
3702
3703                 if ((gpointer) local_account != (gpointer) folder_store &&
3704                     (gpointer) mmc_account != (gpointer) folder_store) {
3705                         is_local_account = FALSE;
3706                         /* New button should be dimmed on remote
3707                            account root */
3708                         new_sensitive = FALSE;
3709                 }
3710                 g_object_unref (local_account);
3711         }
3712
3713         /* Check the target folder rules */
3714         if (TNY_IS_FOLDER (folder_store)) {
3715                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3716                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3717                         ok_sensitive = FALSE;
3718                         new_sensitive = FALSE;
3719                         goto end;
3720                 }
3721         }
3722
3723         /* Check if we're moving a folder */
3724         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3725                 /* Get the widgets */
3726                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3727                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3728                 if (gtk_widget_is_focus (folder_view))
3729                         moving_folder = TRUE;
3730         }
3731
3732         if (moving_folder) {
3733                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3734
3735                 /* Get the folder to move */
3736                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3737                 
3738                 /* Check that we're not moving to the same folder */
3739                 if (TNY_IS_FOLDER (moved_folder)) {
3740                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3741                         if (parent == folder_store)
3742                                 ok_sensitive = FALSE;
3743                         g_object_unref (parent);
3744                 } 
3745
3746                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3747                         /* Do not allow to move to an account unless it's the
3748                            local folders account */
3749                         if (!is_local_account)
3750                                 ok_sensitive = FALSE;
3751                 } 
3752
3753                 if (ok_sensitive && (moved_folder == folder_store)) {
3754                         /* Do not allow to move to itself */
3755                         ok_sensitive = FALSE;
3756                 }
3757                 g_object_unref (moved_folder);
3758         } else {
3759                 TnyHeader *header = NULL;
3760                 TnyFolder *src_folder = NULL;
3761
3762                 /* Moving a message */
3763                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3764                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3765                         src_folder = tny_header_get_folder (header);
3766                         g_object_unref (header);
3767                 } else {
3768                         src_folder = 
3769                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3770                 }
3771
3772                 /* Do not allow to move the msg to the same folder */
3773                 /* Do not allow to move the msg to an account */
3774                 if ((gpointer) src_folder == (gpointer) folder_store ||
3775                     TNY_IS_ACCOUNT (folder_store))
3776                         ok_sensitive = FALSE;
3777                 g_object_unref (src_folder);
3778         }
3779
3780  end:
3781         /* Set sensitivity of the OK button */
3782         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3783         /* Set sensitivity of the NEW button */
3784         gtk_widget_set_sensitive (new_button, new_sensitive);
3785 }
3786
3787 static GtkWidget*
3788 create_move_to_dialog (GtkWindow *win,
3789                        GtkWidget *folder_view,
3790                        GtkWidget **tree_view)
3791 {
3792         GtkWidget *dialog, *scroll;
3793         GtkWidget *new_button;
3794
3795         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3796                                               GTK_WINDOW (win),
3797                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3798                                               NULL);
3799
3800         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3801         /* We do this manually so GTK+ does not associate a response ID for
3802          * the button. */
3803         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3804         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3805         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3806
3807         /* Create scrolled window */
3808         scroll = gtk_scrolled_window_new (NULL, NULL);
3809         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3810                                          GTK_POLICY_AUTOMATIC,
3811                                          GTK_POLICY_AUTOMATIC);
3812
3813         /* Create folder view */
3814         *tree_view = modest_platform_create_folder_view (NULL);
3815
3816         /* Track changes in the selection to
3817          * disable the OK button whenever "Move to" is not possible
3818          * disbale NEW button whenever New is not possible */
3819         g_signal_connect (*tree_view,
3820                           "folder_selection_changed",
3821                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3822                           win);
3823
3824         /* Listen to clicks on New button */
3825         g_signal_connect (G_OBJECT (new_button), 
3826                           "clicked", 
3827                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3828                           *tree_view);
3829
3830         /* It could happen that we're trying to move a message from a
3831            window (msg window for example) after the main window was
3832            closed, so we can not just get the model of the folder
3833            view */
3834         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3835                 const gchar *visible_id = NULL;
3836
3837                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3838                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3839                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3840                                                MODEST_FOLDER_VIEW(*tree_view));
3841
3842                 visible_id = 
3843                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3844
3845                 /* Show the same account than the one that is shown in the main window */
3846                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3847                                                                              visible_id);
3848         } else {
3849                 const gchar *active_account_name = NULL;
3850                 ModestAccountMgr *mgr = NULL;
3851                 ModestAccountData *acc_data = NULL;
3852
3853                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3854                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3855                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3856                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3857
3858                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3859                 mgr = modest_runtime_get_account_mgr ();
3860                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3861
3862                 /* Set the new visible & active account */
3863                 if (acc_data && acc_data->store_account) { 
3864                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3865                                                                                      acc_data->store_account->account_name);
3866                         modest_account_mgr_free_account_data (mgr, acc_data);
3867                 }
3868         }
3869
3870         /* Hide special folders */
3871         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3872         
3873         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3874
3875         /* Add scroll to dialog */
3876         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3877                             scroll, TRUE, TRUE, 0);
3878
3879         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3880         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3881
3882         return dialog;
3883 }
3884
3885 /*
3886  * Returns TRUE if at least one of the headers of the list belongs to
3887  * a message that has been fully retrieved.
3888  */
3889 #if 0 /* no longer in use. delete in 2007.10 */
3890 static gboolean
3891 has_retrieved_msgs (TnyList *list)
3892 {
3893         TnyIterator *iter;
3894         gboolean found = FALSE;
3895
3896         iter = tny_list_create_iterator (list);
3897         while (!tny_iterator_is_done (iter) && !found) {
3898                 TnyHeader *header;
3899                 TnyHeaderFlags flags = 0;
3900
3901                 header = TNY_HEADER (tny_iterator_get_current (iter));
3902                 if (header) {
3903                         flags = tny_header_get_flags (header);
3904                         if (flags & TNY_HEADER_FLAG_CACHED)
3905 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3906                                 found = TRUE;
3907
3908                         g_object_unref (header);
3909                 }
3910
3911                 if (!found)
3912                         tny_iterator_next (iter);
3913         }
3914         g_object_unref (iter);
3915
3916         return found;
3917 }
3918 #endif /* 0 */
3919
3920
3921 /*
3922  * Shows a confirmation dialog to the user when we're moving messages
3923  * from a remote server to the local storage. Returns the dialog
3924  * response. If it's other kind of movement then it always returns
3925  * GTK_RESPONSE_OK
3926  *
3927  * This one is used by the next functions:
3928  *      modest_ui_actions_on_paste                      - commented out
3929  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3930  */
3931 gint
3932 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
3933                                              TnyFolder *dest_folder,
3934                                              gboolean delete,
3935                                              TnyList *headers)
3936 {
3937         gint response = GTK_RESPONSE_OK;
3938         TnyAccount *account = NULL;
3939         TnyFolder *src_folder = NULL;
3940         TnyIterator *iter = NULL;
3941         TnyHeader *header = NULL;
3942
3943         /* return with OK if the destination is a remote folder */
3944         if (modest_tny_folder_is_remote_folder (dest_folder))
3945                 return GTK_RESPONSE_OK;
3946
3947         /* Get source folder */
3948         iter = tny_list_create_iterator (headers);
3949         header = TNY_HEADER (tny_iterator_get_current (iter));
3950         if (header) {
3951                 src_folder = tny_header_get_folder (header);
3952                 g_object_unref (header);
3953         }
3954         g_object_unref (iter);
3955
3956         /* if no src_folder, message may be an attahcment */
3957         if (src_folder == NULL) 
3958                 return GTK_RESPONSE_CANCEL;
3959
3960         /* If the source is a local or MMC folder */
3961         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3962                 g_object_unref (src_folder);
3963                 return GTK_RESPONSE_OK;
3964         }
3965
3966         /* Get the account */
3967         account = tny_folder_get_account (src_folder);
3968
3969         /* now if offline we ask the user */
3970         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
3971                 response = GTK_RESPONSE_OK;
3972         else
3973                 response = GTK_RESPONSE_CANCEL;
3974
3975         /* Frees */
3976         g_object_unref (src_folder);
3977         g_object_unref (account);
3978
3979         return response;
3980 }
3981
3982
3983
3984 static void
3985 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
3986 {
3987         MoveToHelper *helper = (MoveToHelper *) user_data;
3988
3989         /* Note that the operation could have failed, in that case do
3990            nothing */
3991         if (modest_mail_operation_get_status (mail_op) == 
3992             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
3993
3994                 GObject *object = modest_mail_operation_get_source (mail_op);
3995                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
3996                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
3997
3998                         if (!modest_msg_view_window_select_next_message (self))
3999                                 if (!modest_msg_view_window_select_previous_message (self))
4000                                         /* No more messages to view, so close this window */
4001                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4002                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4003                         GtkWidget *header_view;
4004                         GtkTreePath *path;
4005                         GtkTreeSelection *sel;
4006
4007                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4008                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4009                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4010                         path = gtk_tree_row_reference_get_path (helper->reference);
4011                         gtk_tree_selection_select_path (sel, path);
4012                         gtk_tree_path_free (path);
4013                 }
4014                 g_object_unref (object);
4015         }
4016
4017         /* Close the "Pasting" information banner */
4018         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4019         if (helper->reference != NULL)
4020                 gtk_tree_row_reference_free (helper->reference);
4021         g_free (helper);
4022 }
4023
4024 void
4025 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4026                                              gpointer user_data)
4027 {
4028         ModestWindow *main_window = NULL;
4029         GObject *win = NULL;
4030         const GError *error = NULL;
4031         const gchar *message = NULL;
4032         
4033         /* Get error message */
4034         error = modest_mail_operation_get_error (mail_op);
4035         if (error != NULL && error->message != NULL) {
4036                 message = error->message;
4037         } else {
4038                 message = _("mail_in_ui_folder_move_target_error");
4039         }
4040         
4041         /* Disable next automatic folder selection */
4042         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4043                                                          FALSE); /* don't create */
4044         if (main_window) {
4045                 GtkWidget *folder_view = NULL;
4046         
4047                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4048                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4049                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4050                 
4051                 if (user_data && TNY_IS_FOLDER (user_data)) {
4052                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4053                                                           TNY_FOLDER (user_data), FALSE);
4054                 }
4055         }
4056
4057         /* Show notification dialog */
4058         win = modest_mail_operation_get_source (mail_op);
4059         if (G_IS_OBJECT (win)) {
4060                 modest_platform_run_information_dialog (GTK_WINDOW (win), message);
4061                 g_object_unref (win);
4062         }
4063 }
4064
4065 void
4066 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4067                                               gpointer user_data)
4068 {
4069         GObject *win = modest_mail_operation_get_source (mail_op);
4070         const GError *error = modest_mail_operation_get_error (mail_op);
4071
4072         g_return_if_fail (error != NULL);
4073         if (error->message != NULL)             
4074                 g_printerr ("modest: %s\n", error->message);
4075         else
4076                 g_printerr ("modest: unkonw error on send&receive operation");
4077
4078         /* Show error message */
4079 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4080 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4081 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4082 /*      else  */
4083 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4084 /*                                                      _CS("sfil_ib_unable_to_send")); */
4085         g_object_unref (win);
4086 }
4087
4088 static void
4089 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4090                        TnyHeader *header, 
4091                        TnyMsg *msg, 
4092                        gpointer user_data)
4093 {
4094         TnyList *parts;
4095         TnyIterator *iter;
4096         gint pending_purges = 0;
4097         gboolean some_purged = FALSE;
4098         ModestWindow *win = MODEST_WINDOW (user_data);
4099         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4100
4101         /* If there was any error */
4102         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4103                 modest_window_mgr_unregister_header (mgr, header);
4104                 return;
4105         }
4106
4107         /* Once the message has been retrieved for purging, we check if
4108          * it's all ok for purging */
4109
4110         parts = tny_simple_list_new ();
4111         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4112         iter = tny_list_create_iterator (parts);
4113
4114         while (!tny_iterator_is_done (iter)) {
4115                 TnyMimePart *part;
4116                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4117                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4118                         if (tny_mime_part_is_purged (part))
4119                                 some_purged = TRUE;
4120                         else
4121                                 pending_purges++;
4122                 }
4123
4124                 if (part)
4125                         g_object_unref (part);
4126
4127                 tny_iterator_next (iter);
4128         }
4129         g_object_unref (iter);
4130         
4131
4132         if (pending_purges>0) {
4133                 gint response;
4134                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4135
4136                 if (response == GTK_RESPONSE_OK) {
4137                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4138                         iter = tny_list_create_iterator (parts);
4139                         while (!tny_iterator_is_done (iter)) {
4140                                 TnyMimePart *part;
4141                                 
4142                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4143                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4144                                         tny_mime_part_set_purged (part);
4145
4146                                 if (part)
4147                                         g_object_unref (part);
4148
4149                                 tny_iterator_next (iter);
4150                         }
4151                         
4152                         tny_msg_rewrite_cache (msg);
4153                 }
4154         } else {
4155                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4156         }
4157         g_object_unref (iter);
4158
4159         modest_window_mgr_unregister_header (mgr, header);
4160
4161         g_object_unref (parts);
4162 }
4163
4164 static void
4165 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4166                                                      ModestMainWindow *win)
4167 {
4168         GtkWidget *header_view;
4169         TnyList *header_list;
4170         TnyIterator *iter;
4171         TnyHeader *header;
4172         TnyHeaderFlags flags;
4173         ModestWindow *msg_view_window =  NULL;
4174         gboolean found;
4175
4176         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4177
4178         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4179                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4180
4181         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4182         if (!header_list) {
4183                 g_warning ("%s: no header selected", __FUNCTION__);
4184                 return;
4185         }
4186         
4187         if (tny_list_get_length (header_list) == 1) {
4188                 iter = tny_list_create_iterator (header_list);
4189                 header = TNY_HEADER (tny_iterator_get_current (iter));
4190                 g_object_unref (iter);
4191         } else
4192                 return;
4193         
4194         if (!header || !TNY_IS_HEADER(header)) {
4195                 g_warning ("%s: header is not valid", __FUNCTION__);
4196                 return;
4197         }
4198         
4199         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4200                                                           header, &msg_view_window);
4201         flags = tny_header_get_flags (header);
4202         if (!(flags & TNY_HEADER_FLAG_CACHED))
4203                 return;
4204         if (found) {
4205                 if (msg_view_window != NULL) 
4206                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4207                 else {
4208                         /* do nothing; uid was registered before, so window is probably on it's way */
4209                         g_warning ("debug: header %p has already been registered", header);
4210                 }
4211         } else {
4212                 ModestMailOperation *mail_op = NULL;
4213                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4214                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4215                                                                          modest_ui_actions_get_msgs_full_error_handler,
4216                                                                          NULL, NULL);
4217                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4218                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4219                 
4220                 g_object_unref (mail_op);
4221         }
4222         if (header)
4223                 g_object_unref (header);
4224         if (header_list)
4225                 g_object_unref (header_list);
4226 }
4227
4228 /**
4229  * Utility function that transfer messages from both the main window
4230  * and the msg view window when using the "Move to" dialog
4231  */
4232 static void
4233 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4234                                               ModestWindow *win)
4235 {
4236         TnyList *headers = NULL;
4237         TnyAccount *dst_account = NULL;
4238         const gchar *proto_str = NULL;
4239         gboolean dst_is_pop = FALSE;
4240
4241         if (!TNY_IS_FOLDER (dst_folder)) {
4242                 modest_platform_information_banner (GTK_WIDGET (win),
4243                                                     NULL,
4244                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4245                 return;
4246         }
4247
4248         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4249         proto_str = tny_account_get_proto (dst_account);
4250
4251         /* tinymail will return NULL for local folders it seems */
4252         dst_is_pop = proto_str &&
4253                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4254                  MODEST_PROTOCOL_STORE_POP);
4255
4256         g_object_unref (dst_account);
4257
4258         /* Get selected headers */
4259         headers = get_selected_headers (MODEST_WINDOW (win));
4260         if (!headers) {
4261                 g_warning ("%s: no headers selected", __FUNCTION__);
4262                 return;
4263         }
4264
4265
4266         if (dst_is_pop) {
4267                 modest_platform_information_banner (GTK_WIDGET (win),
4268                                                     NULL,
4269                                                     ngettext("mail_in_ui_folder_move_target_error",
4270                                                              "mail_in_ui_folder_move_targets_error",
4271                                                              tny_list_get_length (headers)));
4272                 g_object_unref (headers);
4273                 return;
4274         }
4275
4276         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4277         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4278                                                            _CS("ckct_nw_pasting"));
4279         if (helper->banner != NULL)  {
4280                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4281                 gtk_widget_show (GTK_WIDGET(helper->banner));
4282         }
4283
4284         if (MODEST_IS_MAIN_WINDOW (win)) {
4285                 GtkWidget *header_view = 
4286                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4287                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4288                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4289         }
4290
4291         ModestMailOperation *mail_op = 
4292                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4293                                                                modest_ui_actions_move_folder_error_handler,
4294                                                                NULL, NULL);
4295         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4296                                          mail_op);
4297
4298         modest_mail_operation_xfer_msgs (mail_op, 
4299                                          headers,
4300                                          TNY_FOLDER (dst_folder),
4301                                          TRUE,
4302                                          move_to_cb,
4303                                          helper);
4304
4305         g_object_unref (G_OBJECT (mail_op));
4306         g_object_unref (headers);
4307 }
4308
4309 /*
4310  * UI handler for the "Move to" action when invoked from the
4311  * ModestMainWindow
4312  */
4313 static void 
4314 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4315                                           GtkWidget *folder_view,
4316                                           TnyFolderStore *dst_folder,
4317                                           ModestMainWindow *win)
4318 {
4319         ModestHeaderView *header_view = NULL;
4320         ModestMailOperation *mail_op = NULL;
4321         TnyFolderStore *src_folder;
4322         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4323
4324         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4325
4326         /* Get the source folder */
4327         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4328
4329         /* Get header view */
4330         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4331
4332         /* Get folder or messages to transfer */
4333         if (gtk_widget_is_focus (folder_view)) {
4334                 GtkTreeSelection *sel;
4335                 gboolean do_xfer = TRUE;
4336
4337                 /* Allow only to transfer folders to the local root folder */
4338                 if (TNY_IS_ACCOUNT (dst_folder) && 
4339                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4340                         do_xfer = FALSE;
4341                 } else if (!TNY_IS_FOLDER (src_folder)) {
4342                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4343                         do_xfer = FALSE;
4344                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4345                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER (src_folder));
4346                         TnyAccount *account = tny_folder_get_account (TNY_FOLDER (src_folder));
4347                         if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4348                                 do_xfer = FALSE;
4349                         g_object_unref (account);
4350                 }
4351
4352                 if (do_xfer) {
4353                         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4354                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4355                                                                            _CS("ckct_nw_pasting"));
4356                         if (helper->banner != NULL)  {
4357                                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4358                                 gtk_widget_show (GTK_WIDGET(helper->banner));
4359                         }
4360                         /* Clean folder on header view before moving it */
4361                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4362                         gtk_tree_selection_unselect_all (sel);
4363
4364                         /* Let gtk events run. We need that the folder
4365                            view frees its reference to the source
4366                            folder *before* issuing the mail operation
4367                            so we need the signal handler of selection
4368                            changed to happen before the mail
4369                            operation */
4370                         while (gtk_events_pending ())
4371                                 gtk_main_iteration ();
4372
4373                         mail_op =
4374                           modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4375                                                                          modest_ui_actions_move_folder_error_handler,
4376                                                                          src_folder, NULL);
4377                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4378                                                          mail_op);
4379
4380                         /* Select *after* the changes */
4381                         /* TODO: this function hangs UI after transfer */ 
4382 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4383 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4384                         
4385                         modest_mail_operation_xfer_folder (mail_op,
4386                                                            TNY_FOLDER (src_folder),
4387                                                            dst_folder,
4388                                                            TRUE, 
4389                                                            move_to_cb, 
4390                                                            helper);
4391                         /* Unref mail operation */
4392                         g_object_unref (G_OBJECT (mail_op));
4393                 }
4394         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4395                 gboolean do_xfer = TRUE;
4396                 /* Ask for confirmation if the source folder is remote and we're not connected */
4397                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4398                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4399                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4400                                 guint num_headers = tny_list_get_length(headers);
4401                                 TnyAccount *account = get_account_from_header_list (headers);
4402                                 if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4403                                         do_xfer = FALSE;
4404                                 g_object_unref (account);
4405                         }
4406                         g_object_unref(headers);
4407                 }
4408                 if (do_xfer) /* Transfer messages */
4409                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4410         }
4411
4412     if (src_folder)
4413         g_object_unref (src_folder);
4414 }
4415
4416
4417 /*
4418  * UI handler for the "Move to" action when invoked from the
4419  * ModestMsgViewWindow
4420  */
4421 static void 
4422 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4423                                               TnyFolderStore *dst_folder,
4424                                               ModestMsgViewWindow *win)
4425 {
4426         TnyHeader *header = NULL;
4427         TnyFolder *src_folder = NULL;
4428         TnyAccount *account = NULL;
4429         gboolean do_xfer = FALSE;
4430
4431         /* Create header list */
4432         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4433         src_folder = TNY_FOLDER (tny_header_get_folder(header));
4434         g_object_unref (header);
4435
4436         account = tny_folder_get_account (src_folder);
4437         if (!modest_platform_is_network_folderstore(TNY_FOLDER_STORE(src_folder))) {
4438                 /* Transfer if the source folder is local */
4439                 do_xfer = TRUE;
4440         } else if (remote_folder_is_pop(TNY_FOLDER_STORE(src_folder))) {
4441                 /* Transfer if the source folder is POP (as it means
4442                  * that the message is already downloaded) */
4443                 do_xfer = TRUE;
4444         } else if (connect_to_get_msg(MODEST_WINDOW(win), 1, account)) {
4445                 /* Transfer after asking confirmation */
4446                 do_xfer = TRUE;
4447         }
4448
4449         if (do_xfer) {
4450                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4451         }
4452         g_object_unref (account);
4453         g_object_unref (src_folder);
4454 }
4455
4456 void 
4457 modest_ui_actions_on_move_to (GtkAction *action, 
4458                               ModestWindow *win)
4459 {
4460         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4461         gint result = 0;
4462         TnyFolderStore *dst_folder = NULL;
4463         ModestMainWindow *main_window;
4464
4465         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4466                           MODEST_IS_MSG_VIEW_WINDOW (win));
4467
4468         /* Get the main window if exists */
4469         if (MODEST_IS_MAIN_WINDOW (win))
4470                 main_window = MODEST_MAIN_WINDOW (win);
4471         else
4472                 main_window = 
4473                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4474                                                                                FALSE)); /* don't create */
4475
4476         /* Get the folder view widget if exists */
4477         if (main_window)
4478                 folder_view = modest_main_window_get_child_widget (main_window,
4479                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4480         else
4481                 folder_view = NULL;
4482
4483         /* Create and run the dialog */
4484         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4485         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4486         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4487         result = gtk_dialog_run (GTK_DIALOG(dialog));
4488         g_object_ref (tree_view);
4489         gtk_widget_destroy (dialog);
4490
4491         if (result != GTK_RESPONSE_ACCEPT)
4492                 return;
4493
4494         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4495         /* Do window specific stuff */
4496         if (MODEST_IS_MAIN_WINDOW (win)) {
4497                 modest_ui_actions_on_main_window_move_to (action,
4498                                                           folder_view,
4499                                                           dst_folder,
4500                                                           MODEST_MAIN_WINDOW (win));
4501         } else {
4502                 modest_ui_actions_on_msg_view_window_move_to (action,
4503                                                               dst_folder,
4504                                                               MODEST_MSG_VIEW_WINDOW (win));
4505         }
4506
4507         if (dst_folder)
4508                 g_object_unref (dst_folder);
4509 }
4510
4511 /*
4512  * Calls #HeadersFunc for each header already selected in the main
4513  * window or the message currently being shown in the msg view window
4514  */
4515 static void
4516 do_headers_action (ModestWindow *win, 
4517                    HeadersFunc func,
4518                    gpointer user_data)
4519 {
4520         TnyList *headers_list = NULL;
4521         TnyIterator *iter = NULL;
4522         TnyHeader *header = NULL;
4523         TnyFolder *folder = NULL;
4524
4525         /* Get headers */
4526         headers_list = get_selected_headers (win);
4527         if (!headers_list)
4528                 return;
4529
4530         /* Get the folder */
4531         iter = tny_list_create_iterator (headers_list);
4532         header = TNY_HEADER (tny_iterator_get_current (iter));
4533         if (header) {
4534                 folder = tny_header_get_folder (header);
4535                 g_object_unref (header);
4536         }
4537
4538         /* Call the function for each header */
4539         while (!tny_iterator_is_done (iter)) {
4540                 header = TNY_HEADER (tny_iterator_get_current (iter));
4541                 func (header, win, user_data);
4542                 g_object_unref (header);
4543                 tny_iterator_next (iter);
4544         }
4545
4546         /* Trick: do a poke status in order to speed up the signaling
4547            of observers */
4548         tny_folder_poke_status (folder);
4549
4550         /* Frees */
4551         g_object_unref (folder);
4552         g_object_unref (iter);
4553         g_object_unref (headers_list);
4554 }
4555
4556 void 
4557 modest_ui_actions_view_attachment (GtkAction *action,
4558                                    ModestWindow *window)
4559 {
4560         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4561                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4562         } else {
4563                 /* not supported window for this action */
4564                 g_return_if_reached ();
4565         }
4566 }
4567
4568 void
4569 modest_ui_actions_save_attachments (GtkAction *action,
4570                                     ModestWindow *window)
4571 {
4572         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4573                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4574         } else {
4575                 /* not supported window for this action */
4576                 g_return_if_reached ();
4577         }
4578 }
4579
4580 void
4581 modest_ui_actions_remove_attachments (GtkAction *action,
4582                                       ModestWindow *window)
4583 {
4584         if (MODEST_IS_MAIN_WINDOW (window)) {
4585                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4586         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4587                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4588         } else {
4589                 /* not supported window for this action */
4590                 g_return_if_reached ();
4591         }
4592 }
4593
4594 void 
4595 modest_ui_actions_on_settings (GtkAction *action, 
4596                                ModestWindow *win)
4597 {
4598         GtkWidget *dialog;
4599
4600         dialog = modest_platform_get_global_settings_dialog ();
4601         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4602         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4603         gtk_widget_show_all (dialog);
4604
4605         gtk_dialog_run (GTK_DIALOG (dialog));
4606
4607         gtk_widget_destroy (dialog);
4608 }
4609
4610 void 
4611 modest_ui_actions_on_help (GtkAction *action, 
4612                            GtkWindow *win)
4613 {
4614         const gchar *help_id;
4615
4616         g_return_if_fail (action);
4617         g_return_if_fail (win && GTK_IS_WINDOW(win));
4618         
4619         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
4620         
4621         if (help_id)
4622                 modest_platform_show_help (GTK_WINDOW (win), help_id);
4623         else
4624                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
4625 }
4626
4627 void 
4628 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4629                                             ModestWindow *window)
4630 {
4631         ModestMailOperation *mail_op;
4632         TnyList *headers;
4633
4634         /* Get headers */
4635         headers = get_selected_headers (window);
4636         if (!headers)
4637                 return;
4638
4639         /* Create mail operation */
4640         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (window),
4641                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4642                                                                  NULL, NULL);
4643         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4644         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4645
4646         /* Frees */
4647         g_object_unref (headers);
4648         g_object_unref (mail_op);
4649 }
4650
4651 void
4652 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4653                                           ModestWindow *window)
4654 {
4655         g_return_if_fail (MODEST_IS_WINDOW (window));
4656         
4657         /* Update dimmed */     
4658         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4659 }
4660
4661 void
4662 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4663                                           ModestWindow *window)
4664 {
4665         g_return_if_fail (MODEST_IS_WINDOW (window));
4666
4667         /* Update dimmed */     
4668         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4669 }
4670
4671 void
4672 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4673                                           ModestWindow *window)
4674 {
4675         g_return_if_fail (MODEST_IS_WINDOW (window));
4676
4677         /* Update dimmed */     
4678         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4679 }
4680
4681 void
4682 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4683                                             ModestWindow *window)
4684 {
4685         g_return_if_fail (MODEST_IS_WINDOW (window));
4686
4687         /* Update dimmed */     
4688         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4689 }
4690
4691 void
4692 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4693                                           ModestWindow *window)
4694 {
4695         g_return_if_fail (MODEST_IS_WINDOW (window));
4696
4697         /* Update dimmed */     
4698         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4699 }
4700
4701 void
4702 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4703                                           ModestWindow *window)
4704 {
4705         g_return_if_fail (MODEST_IS_WINDOW (window));
4706
4707         /* Update dimmed */     
4708         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4709 }
4710
4711 void
4712 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4713                                                  ModestWindow *window)
4714 {
4715         g_return_if_fail (MODEST_IS_WINDOW (window));
4716
4717         /* Update dimmed */     
4718         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4719 }
4720
4721 void
4722 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4723                                                      ModestWindow *window)
4724 {
4725         g_return_if_fail (MODEST_IS_WINDOW (window));
4726
4727         /* Update dimmed */     
4728         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4729 }
4730
4731 void
4732 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4733                                                      ModestWindow *window)
4734 {
4735         g_return_if_fail (MODEST_IS_WINDOW (window));
4736
4737         /* Update dimmed */     
4738         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4739 }
4740
4741 void
4742 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4743 {
4744         g_return_if_fail (MODEST_IS_WINDOW (window));
4745
4746         /* Update dimmed */     
4747         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4748 }
4749
4750 void
4751 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4752 {
4753         g_return_if_fail (MODEST_IS_WINDOW (window));
4754
4755         modest_platform_show_search_messages (GTK_WINDOW (window));
4756 }
4757
4758 void     
4759 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4760 {
4761         g_return_if_fail (MODEST_IS_WINDOW (win));
4762         modest_platform_show_addressbook (GTK_WINDOW (win));
4763 }
4764
4765
4766 void
4767 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4768                                           ModestWindow *window)
4769 {
4770         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4771
4772         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4773 }
4774
4775 static void 
4776 on_send_receive_finished (ModestMailOperation  *mail_op, 
4777                            gpointer user_data)
4778 {
4779         GtkWidget *header_view, *folder_view;
4780         TnyFolderStore *folder_store;
4781         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
4782
4783         /* Set send/receive operation finished */       
4784         modest_main_window_notify_send_receive_completed (main_win);
4785
4786         /* Don't refresh the current folder if there were any errors */
4787         if (modest_mail_operation_get_status (mail_op) !=
4788             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
4789                 return;
4790         
4791         /* Refresh the current folder if we're viewing a window. We do
4792            this because the user won't be able to see the new mails in
4793            the selected folder after a Send&Receive because it only
4794            performs a poke_status, i.e, only the number of read/unread
4795            messages is updated, but the new headers are not
4796            downloaded */
4797         folder_view = modest_main_window_get_child_widget (main_win, 
4798                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4799         if (!folder_view)
4800                 return;
4801
4802         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4803         
4804         if (folder_store && TNY_IS_FOLDER (folder_store)) {
4805                 header_view = modest_main_window_get_child_widget (main_win,
4806                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4807                 
4808                 /* We do not need to set the contents style
4809                    because it hasn't changed. We also do not
4810                    need to save the widget status. Just force
4811                    a refresh */
4812                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
4813                                                TNY_FOLDER (folder_store),
4814                                                folder_refreshed_cb,
4815                                                main_win);
4816         }
4817         
4818         if (folder_store)
4819                 g_object_unref (folder_store);
4820 }
4821
4822
4823 void 
4824 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4825                                                 TnyHeader *header, 
4826                                                 TnyMsg *msg, 
4827                                                 GError *err, 
4828                                                 gpointer user_data)
4829 {
4830         const gchar* server_name = NULL;
4831         TnyTransportAccount *server_account;
4832         gchar *message = NULL;
4833
4834         /* Don't show anything if the user cancelled something */
4835         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4836                 return;
4837
4838         /* Get the server name: */
4839         server_account = 
4840                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4841         if (server_account) {
4842                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4843                         
4844                 g_object_unref (server_account);
4845                 server_account = NULL;
4846         }
4847         
4848         g_return_if_fail (server_name);
4849
4850         /* Show the appropriate message text for the GError: */
4851         switch (err->code) {
4852         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4853                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4854                 break;
4855         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4856                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4857                 break;
4858         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4859                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4860                 break;
4861         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4862                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4863                 break;
4864         default:
4865                 g_return_if_reached ();
4866         }
4867         
4868         /* TODO if the username or the password where not defined we
4869            should show the Accounts Settings dialog or the Connection
4870            specific SMTP server window */
4871
4872         modest_platform_run_information_dialog (NULL, message);
4873         g_free (message);
4874 }
4875
4876 void
4877 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
4878                                                 gchar *msg_id, 
4879                                                 guint status,
4880                                                 gpointer user_data)
4881 {
4882         ModestMainWindow *main_window = NULL;
4883         ModestWindowMgr *mgr = NULL;
4884         GtkWidget *folder_view = NULL, *header_view = NULL;
4885         TnyFolderStore *selected_folder = NULL;
4886         TnyFolderType folder_type;
4887
4888         mgr = modest_runtime_get_window_mgr ();
4889         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
4890                                                                              FALSE));/* don't create */
4891         if (!main_window)
4892                 return;
4893
4894         /* Check if selected folder is OUTBOX */
4895         folder_view = modest_main_window_get_child_widget (main_window,
4896                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4897         header_view = modest_main_window_get_child_widget (main_window,
4898                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4899
4900         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4901         if (!TNY_IS_FOLDER (selected_folder)) 
4902                 goto frees;
4903
4904         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
4905 #if GTK_CHECK_VERSION(2, 8, 0) 
4906         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
4907         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
4908                 GtkTreeViewColumn *tree_column;
4909
4910                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
4911                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
4912                 gtk_tree_view_column_queue_resize (tree_column);
4913         }
4914 #else
4915         gtk_widget_queue_draw (header_view);
4916 #endif          
4917         
4918         /* Free */
4919  frees:
4920         if (selected_folder != NULL)
4921                 g_object_unref (selected_folder);
4922 }