9368b17d9b1cf0a994df09714fc734103ab5373f
[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 /*
1642  * This function performs the send & receive required actions. The
1643  * window is used to create the mail operation. Typically it should
1644  * always be the main window, but we pass it as argument in order to
1645  * be more flexible.
1646  */
1647 void
1648 modest_ui_actions_do_send_receive (const gchar *account_name, 
1649                                    ModestWindow *win)
1650 {
1651         gchar *acc_name = NULL;
1652         ModestMailOperation *mail_op;
1653         TnyAccount *store_account = NULL;
1654
1655         /* If no account name was provided then get the current account, and if
1656            there is no current account then pick the default one: */
1657         if (!account_name) {
1658                 if (win)
1659                         acc_name = g_strdup (modest_window_get_active_account (win));
1660                 if (!acc_name)
1661                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1662                 if (!acc_name) {
1663                         g_printerr ("modest: cannot get default account\n");
1664                         return;
1665                 }
1666         } else {
1667                 acc_name = g_strdup (account_name);
1668         }
1669
1670         /* Ensure that we have a connection available */
1671         store_account =
1672                 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1673                                                              acc_name,
1674                                                              TNY_ACCOUNT_TYPE_STORE);
1675
1676         if (!modest_platform_connect_and_wait (NULL, TNY_ACCOUNT (store_account))) {
1677                 g_object_unref (store_account);
1678                 return;
1679         }
1680         g_object_unref (store_account);
1681
1682         /* Set send/receive operation in progress */    
1683         if (win && MODEST_IS_MAIN_WINDOW (win))
1684                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1685         
1686         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
1687                                                                  modest_ui_actions_send_receive_error_handler,
1688                                                                  NULL, NULL);
1689
1690         if (win && MODEST_IS_MAIN_WINDOW (win))
1691                 g_signal_connect (G_OBJECT(mail_op), "operation-finished", 
1692                                   G_CALLBACK (on_send_receive_finished), 
1693                                   win);
1694
1695         /* Send & receive. */
1696         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1697         /* Receive and then send. The operation is tagged initially as
1698            a receive operation because the account update performs a
1699            receive and then a send. The operation changes its type
1700            internally, so the progress objects will receive the proper
1701            progress information */
1702         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1703         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1704         g_object_unref (G_OBJECT (mail_op));
1705         
1706         /* Free */
1707         g_free (acc_name);
1708 }
1709
1710
1711 static void
1712 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1713                                   ModestWindow *win)
1714 {
1715         TnyTransportAccount *transport_account;
1716         TnySendQueue *send_queue = NULL;
1717         GError *error = NULL;
1718
1719         /* Get transport account */
1720         transport_account =
1721                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1722                                       (modest_runtime_get_account_store(),
1723                                        account_name,
1724                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1725         if (!transport_account) {
1726                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1727                 goto frees;
1728         }
1729
1730         /* Get send queue*/
1731         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1732         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1733                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1734                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1735                              "modest: could not find send queue for account\n");
1736         } else {
1737                 /* Keeep messages in outbox folder */
1738                 tny_send_queue_cancel (send_queue, FALSE, &error);
1739         }       
1740
1741  frees:
1742         if (transport_account != NULL) 
1743                 g_object_unref (G_OBJECT (transport_account));
1744 }
1745
1746 static void
1747 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1748 {
1749         GSList *account_names, *iter;
1750
1751         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1752                                                           TRUE);
1753
1754         iter = account_names;
1755         while (iter) {                  
1756                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1757                 iter = g_slist_next (iter);
1758         }
1759
1760         modest_account_mgr_free_account_names (account_names);
1761         account_names = NULL;
1762 }
1763
1764 void
1765 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1766
1767 {
1768         /* Check if accounts exist */
1769         gboolean accounts_exist = 
1770                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1771         
1772         /* If not, allow the user to create an account before trying to send/receive. */
1773         if (!accounts_exist)
1774                 modest_ui_actions_on_accounts (NULL, win);
1775         
1776         /* Cancel all sending operaitons */     
1777         modest_ui_actions_cancel_send_all (win);
1778 }
1779
1780 /*
1781  * Refreshes all accounts. This function will be used by automatic
1782  * updates
1783  */
1784 void
1785 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1786 {
1787         GSList *account_names, *iter;
1788
1789         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1790                                                           TRUE);
1791
1792         iter = account_names;
1793         while (iter) {                  
1794                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1795                 iter = g_slist_next (iter);
1796         }
1797
1798         modest_account_mgr_free_account_names (account_names);
1799         account_names = NULL;
1800 }
1801
1802 static void 
1803 refresh_current_folder(ModestWindow *win)
1804 {
1805         /* Refresh currently selected folder. Note that if we only
1806            want to retreive the headers, then the refresh only will
1807            invoke a poke_status over all folders, i.e., only the
1808            total/unread count will be updated */
1809         if (MODEST_IS_MAIN_WINDOW (win)) {
1810                 GtkWidget *header_view, *folder_view;
1811                 TnyFolderStore *folder_store;
1812
1813                 /* Get folder and header view */
1814                 folder_view = 
1815                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1816                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1817                 if (!folder_view)
1818                         return;
1819
1820                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1821
1822                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1823                         header_view = 
1824                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1825                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1826                 
1827                         /* We do not need to set the contents style
1828                            because it hasn't changed. We also do not
1829                            need to save the widget status. Just force
1830                            a refresh */
1831                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1832                                                        TNY_FOLDER (folder_store),
1833                                                        folder_refreshed_cb,
1834                                                        MODEST_MAIN_WINDOW (win));
1835                 }
1836                 
1837                 if (folder_store)
1838                         g_object_unref (folder_store);
1839         }
1840 }
1841
1842
1843 /*
1844  * Handler of the click on Send&Receive button in the main toolbar
1845  */
1846 void
1847 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1848 {
1849         /* Check if accounts exist */
1850         gboolean accounts_exist = 
1851                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1852         
1853         /* If not, allow the user to create an account before trying to send/receive. */
1854         if (!accounts_exist)
1855                 modest_ui_actions_on_accounts (NULL, win);
1856
1857         /* Refresh the current folder if we're viewing a window */
1858         if (win)
1859                 refresh_current_folder (win);
1860         
1861         /* Refresh the active account */
1862         modest_ui_actions_do_send_receive (NULL, win);
1863 }
1864
1865
1866 void
1867 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1868 {
1869         ModestConf *conf;
1870         GtkWidget *header_view;
1871         
1872         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1873
1874         header_view = modest_main_window_get_child_widget (main_window,
1875                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1876         if (!header_view)
1877                 return;
1878
1879         conf = modest_runtime_get_conf ();
1880         
1881         /* what is saved/restored is depending on the style; thus; we save with
1882          * old style, then update the style, and restore for this new style
1883          */
1884         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1885         
1886         if (modest_header_view_get_style
1887             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1888                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1889                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1890         else
1891                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1892                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1893
1894         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1895                                       MODEST_CONF_HEADER_VIEW_KEY);
1896 }
1897
1898
1899 void 
1900 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1901                                       TnyHeader *header,
1902                                       ModestMainWindow *main_window)
1903 {
1904         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1905         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1906         
1907         /* in the case the folder is empty, show the empty folder message and focus
1908          * folder view */
1909         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1910                 if (modest_header_view_is_empty (header_view)) {
1911                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1912                         GtkWidget *folder_view = 
1913                                 modest_main_window_get_child_widget (main_window,
1914                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1915                         if (folder != NULL) 
1916                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1917                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1918                         return;
1919                 }
1920         }
1921         /* If no header has been selected then exit */
1922         if (!header)
1923                 return;
1924
1925         /* Update focus */
1926         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1927             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1928
1929         /* Update toolbar dimming state */
1930         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1931 }
1932
1933 void
1934 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1935                                        TnyHeader *header,
1936                                        ModestMainWindow *main_window)
1937 {
1938         TnyList *headers;
1939
1940         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1941         
1942         if (!header)
1943                 return;
1944
1945         if (modest_header_view_count_selected_headers (header_view) > 1) {
1946                 hildon_banner_show_information (NULL, NULL, _("mcen_ib_select_one_message"));
1947                 return;
1948         }
1949
1950
1951 /*      headers = tny_simple_list_new (); */
1952 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1953         headers = modest_header_view_get_selected_headers (header_view);
1954
1955         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1956
1957         g_object_unref (headers);
1958 }
1959
1960 static void
1961 set_active_account_from_tny_account (TnyAccount *account,
1962                                      ModestWindow *window)
1963 {
1964         const gchar *server_acc_name = tny_account_get_id (account);
1965         
1966         /* We need the TnyAccount provided by the
1967            account store because that is the one that
1968            knows the name of the Modest account */
1969         TnyAccount *modest_server_account = modest_server_account = 
1970                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1971                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1972                                                              server_acc_name);
1973         if (!modest_server_account) {
1974                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
1975                 return;
1976         }
1977
1978         /* Update active account, but only if it's not a pseudo-account */
1979         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
1980             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
1981                 const gchar *modest_acc_name = 
1982                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1983                 if (modest_acc_name)
1984                         modest_window_set_active_account (window, modest_acc_name);
1985         }
1986         
1987         g_object_unref (modest_server_account);
1988 }
1989
1990
1991 static void
1992 folder_refreshed_cb (ModestMailOperation *mail_op, 
1993                      TnyFolder *folder, 
1994                      gpointer user_data)
1995 {
1996         ModestMainWindow *win = NULL;
1997         GtkWidget *header_view;
1998         gboolean folder_empty = FALSE;
1999         gboolean all_marked_as_deleted = FALSE;
2000
2001         g_return_if_fail (TNY_IS_FOLDER (folder));
2002
2003         win = MODEST_MAIN_WINDOW (user_data);
2004         header_view = 
2005                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2006
2007         if (header_view) {
2008                 TnyFolder *current_folder;
2009
2010                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
2011                 if (current_folder != NULL && folder != current_folder) {
2012                         g_object_unref (current_folder);
2013                         return;
2014                 }
2015                 g_object_unref (current_folder);
2016         }
2017
2018         /* Check if folder is empty and set headers view contents style */
2019         folder_empty = (tny_folder_get_all_count (folder) == 0);
2020         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
2021         if (folder_empty || all_marked_as_deleted)
2022                 modest_main_window_set_contents_style (win,
2023                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2024 }
2025
2026 void 
2027 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2028                                                TnyFolderStore *folder_store, 
2029                                                gboolean selected,
2030                                                ModestMainWindow *main_window)
2031 {
2032         ModestConf *conf;
2033         GtkWidget *header_view;
2034
2035         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2036
2037         header_view = modest_main_window_get_child_widget(main_window,
2038                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2039         if (!header_view)
2040                 return;
2041         
2042         conf = modest_runtime_get_conf ();
2043
2044         if (TNY_IS_ACCOUNT (folder_store)) {
2045                 if (selected) {
2046                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2047                         
2048                         /* Show account details */
2049                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2050                 }
2051         } else {
2052                 if (TNY_IS_FOLDER (folder_store) && selected) {
2053                         
2054                         /* Update the active account */
2055                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2056                         if (account) {
2057                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2058                                 g_object_unref (account);
2059                                 account = NULL;
2060                         }
2061
2062                         /* Set the header style by default, it could
2063                            be changed later by the refresh callback to
2064                            empty */
2065                         modest_main_window_set_contents_style (main_window, 
2066                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2067
2068                         /* Set folder on header view. This function
2069                            will call tny_folder_refresh_async so we
2070                            pass a callback that will be called when
2071                            finished. We use that callback to set the
2072                            empty view if there are no messages */
2073                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2074                                                        TNY_FOLDER (folder_store),
2075                                                        folder_refreshed_cb,
2076                                                        main_window);
2077                         
2078                         /* Restore configuration. We need to do this
2079                            *after* the set_folder because the widget
2080                            memory asks the header view about its
2081                            folder  */
2082                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2083                                                       G_OBJECT(header_view),
2084                                                       MODEST_CONF_HEADER_VIEW_KEY);
2085                 } else {
2086                         /* Update the active account */
2087                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2088                         /* Save only if we're seeing headers */
2089                         if (modest_main_window_get_contents_style (main_window) ==
2090                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2091                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2092                                                            MODEST_CONF_HEADER_VIEW_KEY);
2093                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2094                 }
2095         }
2096
2097         /* Update toolbar dimming state */
2098         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2099 }
2100
2101 void 
2102 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2103                                      ModestWindow *win)
2104 {
2105         GtkWidget *dialog;
2106         gchar *txt, *item;
2107         gboolean online;
2108
2109         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2110         
2111         online = tny_device_is_online (modest_runtime_get_device());
2112
2113         if (online) {
2114                 /* already online -- the item is simply not there... */
2115                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2116                                                  GTK_DIALOG_MODAL,
2117                                                  GTK_MESSAGE_WARNING,
2118                                                  GTK_BUTTONS_NONE,
2119                                                  _("The %s you selected cannot be found"),
2120                                                  item);
2121                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2122                 gtk_dialog_run (GTK_DIALOG(dialog));
2123         } else {
2124                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2125                                                       GTK_WINDOW (win),
2126                                                       GTK_DIALOG_MODAL,
2127                                                       _("mcen_bd_dialog_cancel"),
2128                                                       GTK_RESPONSE_REJECT,
2129                                                       _("mcen_bd_dialog_ok"),
2130                                                       GTK_RESPONSE_ACCEPT,
2131                                                       NULL);
2132                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2133                                          "Do you want to get online?"), item);
2134                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2135                                     gtk_label_new (txt), FALSE, FALSE, 0);
2136                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2137                 g_free (txt);
2138
2139                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2140                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2141                         /* TODO: Comment about why is this commented out: */
2142                         /* modest_platform_connect_and_wait (); */
2143                 }
2144         }
2145         gtk_widget_destroy (dialog);
2146 }
2147
2148 void
2149 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2150                                      ModestWindow *win)
2151 {
2152         /* g_message ("%s %s", __FUNCTION__, link); */
2153 }       
2154
2155
2156 void
2157 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2158                                         ModestWindow *win)
2159 {
2160         modest_platform_activate_uri (link);
2161 }
2162
2163 void
2164 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2165                                           ModestWindow *win)
2166 {
2167         modest_platform_show_uri_popup (link);
2168 }
2169
2170 void
2171 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2172                                              ModestWindow *win)
2173 {
2174         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2175 }
2176
2177 void
2178 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2179                                           const gchar *address,
2180                                           ModestWindow *win)
2181 {
2182         /* g_message ("%s %s", __FUNCTION__, address); */
2183 }
2184
2185 static void
2186 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2187                       TnyMsg *saved_draft,
2188                       gpointer user_data)
2189 {
2190         ModestMsgEditWindow *edit_window;
2191
2192         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2193
2194         /* If there was any error do nothing */
2195         if (modest_mail_operation_get_error (mail_op) != NULL)
2196                 return;
2197
2198         modest_msg_edit_window_set_draft (edit_window, saved_draft);
2199 }
2200
2201 void
2202 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2203 {
2204         TnyTransportAccount *transport_account;
2205         ModestMailOperation *mail_operation;
2206         MsgData *data;
2207         gchar *account_name, *from;
2208         ModestAccountMgr *account_mgr;
2209         gchar *info_text = NULL;
2210
2211         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2212         
2213         data = modest_msg_edit_window_get_msg_data (edit_window);
2214
2215         account_name = g_strdup (data->account_name);
2216         account_mgr = modest_runtime_get_account_mgr();
2217         if (!account_name)
2218                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2219         if (!account_name) 
2220                 account_name = modest_account_mgr_get_default_account (account_mgr);
2221         if (!account_name) {
2222                 g_printerr ("modest: no account found\n");
2223                 modest_msg_edit_window_free_msg_data (edit_window, data);
2224                 return;
2225         }
2226
2227         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2228                 account_name = g_strdup (data->account_name);
2229         }
2230
2231         transport_account =
2232                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2233                                       (modest_runtime_get_account_store(),
2234                                        account_name,
2235                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2236         if (!transport_account) {
2237                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2238                 g_free (account_name);
2239                 modest_msg_edit_window_free_msg_data (edit_window, data);
2240                 return;
2241         }
2242         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2243
2244         /* Create the mail operation */         
2245         mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2246         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2247
2248         modest_mail_operation_save_to_drafts (mail_operation,
2249                                               transport_account,
2250                                               data->draft_msg,
2251                                               from,
2252                                               data->to, 
2253                                               data->cc, 
2254                                               data->bcc,
2255                                               data->subject, 
2256                                               data->plain_body, 
2257                                               data->html_body,
2258                                               data->attachments,
2259                                               data->images,
2260                                               data->priority_flags,
2261                                               on_save_to_drafts_cb,
2262                                               edit_window);
2263         /* Frees */
2264         g_free (from);
2265         g_free (account_name);
2266         g_object_unref (G_OBJECT (transport_account));
2267         g_object_unref (G_OBJECT (mail_operation));
2268
2269         modest_msg_edit_window_free_msg_data (edit_window, data);
2270
2271         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2272         modest_platform_information_banner (NULL, NULL, info_text);
2273         modest_msg_edit_window_reset_modified (edit_window);
2274         g_free (info_text);
2275 }
2276
2277 /* For instance, when clicking the Send toolbar button when editing a message: */
2278 void
2279 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2280 {
2281         TnyTransportAccount *transport_account = NULL;
2282
2283         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2284
2285         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2286                 return;
2287         
2288         /* FIXME: Code added just for testing. The final version will
2289            use the send queue provided by tinymail and some
2290            classifier */
2291         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2292
2293         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2294         gchar *account_name = g_strdup (data->account_name);
2295         if (!account_name)
2296                 g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2297
2298         if (!account_name) 
2299                 account_name = modest_account_mgr_get_default_account (account_mgr);
2300                 
2301         if (!account_name) {
2302                 modest_msg_edit_window_free_msg_data (edit_window, data);
2303                 /* Run account setup wizard */
2304                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window)))
2305                         return;
2306         }
2307         
2308         /* Get the currently-active transport account for this modest account: */
2309 /*      TnyTransportAccount *transport_account = */
2310 /*              TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection */
2311 /*                                    (modest_runtime_get_account_store(), */
2312 /*                                     account_name)); */
2313         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2314                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2315                                                           (modest_runtime_get_account_store(),
2316                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2317         }
2318         
2319         if (!transport_account) {
2320                 /* Run account setup wizard */
2321                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2322                         return;
2323         }
2324         
2325         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2326
2327         /* Create the mail operation */
2328         ModestMailOperation *mail_operation = modest_mail_operation_new (G_OBJECT(edit_window));
2329         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2330
2331         modest_mail_operation_send_new_mail (mail_operation,
2332                                              transport_account,
2333                                              data->draft_msg,
2334                                              from,
2335                                              data->to, 
2336                                              data->cc, 
2337                                              data->bcc,
2338                                              data->subject, 
2339                                              data->plain_body, 
2340                                              data->html_body,
2341                                              data->attachments,
2342                                              data->images,
2343                                              data->priority_flags);
2344                                              
2345         /* Free data: */
2346         g_free (from);
2347         g_free (account_name);
2348         g_object_unref (G_OBJECT (transport_account));
2349         g_object_unref (G_OBJECT (mail_operation));
2350
2351         modest_msg_edit_window_free_msg_data (edit_window, data);
2352         modest_msg_edit_window_set_sent (edit_window, TRUE);
2353
2354         /* Save settings and close the window: */
2355         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2356 }
2357
2358 void 
2359 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2360                                   ModestMsgEditWindow *window)
2361 {
2362         ModestMsgEditFormatState *format_state = NULL;
2363
2364         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2365         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2366
2367         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2368                 return;
2369
2370         format_state = modest_msg_edit_window_get_format_state (window);
2371         g_return_if_fail (format_state != NULL);
2372
2373         format_state->bold = gtk_toggle_action_get_active (action);
2374         modest_msg_edit_window_set_format_state (window, format_state);
2375         g_free (format_state);
2376         
2377 }
2378
2379 void 
2380 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2381                                      ModestMsgEditWindow *window)
2382 {
2383         ModestMsgEditFormatState *format_state = NULL;
2384
2385         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2386         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2387
2388         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2389                 return;
2390
2391         format_state = modest_msg_edit_window_get_format_state (window);
2392         g_return_if_fail (format_state != NULL);
2393
2394         format_state->italics = gtk_toggle_action_get_active (action);
2395         modest_msg_edit_window_set_format_state (window, format_state);
2396         g_free (format_state);
2397         
2398 }
2399
2400 void 
2401 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2402                                      ModestMsgEditWindow *window)
2403 {
2404         ModestMsgEditFormatState *format_state = NULL;
2405
2406         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2407         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2408
2409         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2410                 return;
2411
2412         format_state = modest_msg_edit_window_get_format_state (window);
2413         g_return_if_fail (format_state != NULL);
2414
2415         format_state->bullet = gtk_toggle_action_get_active (action);
2416         modest_msg_edit_window_set_format_state (window, format_state);
2417         g_free (format_state);
2418         
2419 }
2420
2421 void 
2422 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2423                                      GtkRadioAction *selected,
2424                                      ModestMsgEditWindow *window)
2425 {
2426         ModestMsgEditFormatState *format_state = NULL;
2427         GtkJustification value;
2428
2429         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2430
2431         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2432                 return;
2433
2434         value = gtk_radio_action_get_current_value (selected);
2435
2436         format_state = modest_msg_edit_window_get_format_state (window);
2437         g_return_if_fail (format_state != NULL);
2438
2439         format_state->justification = value;
2440         modest_msg_edit_window_set_format_state (window, format_state);
2441         g_free (format_state);
2442 }
2443
2444 void 
2445 modest_ui_actions_on_select_editor_color (GtkAction *action,
2446                                           ModestMsgEditWindow *window)
2447 {
2448         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2449         g_return_if_fail (GTK_IS_ACTION (action));
2450
2451         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2452                 return;
2453
2454         modest_msg_edit_window_select_color (window);
2455 }
2456
2457 void 
2458 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2459                                                      ModestMsgEditWindow *window)
2460 {
2461         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2462         g_return_if_fail (GTK_IS_ACTION (action));
2463
2464         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2465                 return;
2466
2467         modest_msg_edit_window_select_background_color (window);
2468 }
2469
2470 void 
2471 modest_ui_actions_on_insert_image (GtkAction *action,
2472                                    ModestMsgEditWindow *window)
2473 {
2474         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2475         g_return_if_fail (GTK_IS_ACTION (action));
2476
2477         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2478                 return;
2479
2480         modest_msg_edit_window_insert_image (window);
2481 }
2482
2483 void 
2484 modest_ui_actions_on_attach_file (GtkAction *action,
2485                                   ModestMsgEditWindow *window)
2486 {
2487         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2488         g_return_if_fail (GTK_IS_ACTION (action));
2489
2490         modest_msg_edit_window_offer_attach_file (window);
2491 }
2492
2493 void 
2494 modest_ui_actions_on_remove_attachments (GtkAction *action,
2495                                          ModestMsgEditWindow *window)
2496 {
2497         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2498         g_return_if_fail (GTK_IS_ACTION (action));
2499
2500         modest_msg_edit_window_remove_attachments (window, NULL);
2501 }
2502
2503 static void
2504 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2505                                             gpointer user_data)
2506 {
2507         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2508         const GError *error = modest_mail_operation_get_error (mail_op);
2509
2510         if(error) {
2511                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2512                                                     _("mail_in_ui_folder_create_error"));
2513         }
2514 }
2515
2516 static void
2517 modest_ui_actions_create_folder(GtkWidget *parent_window,
2518                                 GtkWidget *folder_view)
2519 {
2520         TnyFolderStore *parent_folder;
2521
2522         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2523         
2524         if (parent_folder) {
2525                 gboolean finished = FALSE;
2526                 gint result;
2527                 gchar *folder_name = NULL, *suggested_name = NULL;
2528                 const gchar *proto_str = NULL;
2529                 TnyAccount *account;
2530
2531                 if (TNY_IS_ACCOUNT (parent_folder))
2532                         account = g_object_ref (parent_folder);
2533                 else
2534                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2535                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2536
2537                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2538                     MODEST_PROTOCOL_STORE_POP) {
2539                         finished = TRUE;
2540                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2541                 }
2542                 g_object_unref (account);
2543
2544                 /* Run the new folder dialog */
2545                 while (!finished) {
2546                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2547                                                                         parent_folder,
2548                                                                         suggested_name,
2549                                                                         &folder_name);
2550
2551                         g_free (suggested_name);
2552                         suggested_name = NULL;
2553
2554                         if (result == GTK_RESPONSE_ACCEPT) {
2555                                 ModestMailOperation *mail_op;
2556                                 TnyFolder *new_folder = NULL;
2557
2558                                 mail_op  = modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2559                                                                                           modest_ui_actions_new_folder_error_handler,
2560                                                                                           parent_window, NULL);
2561
2562                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2563                                                                  mail_op);
2564                                 new_folder = modest_mail_operation_create_folder (mail_op,
2565                                                                                   parent_folder,
2566                                                                                   (const gchar *) folder_name);
2567                                 if (new_folder) {
2568                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2569                                                                           new_folder, TRUE);
2570
2571                                         g_object_unref (new_folder);
2572                                         finished = TRUE;
2573                                 }
2574                                 g_object_unref (mail_op);
2575                         } else {
2576                                 finished = TRUE;
2577                         }
2578
2579                         suggested_name = folder_name;
2580                         folder_name = NULL;
2581                 }
2582
2583                 g_object_unref (parent_folder);
2584         }
2585 }
2586
2587 void 
2588 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2589 {
2590         GtkWidget *folder_view;
2591         
2592         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2593
2594         folder_view = modest_main_window_get_child_widget (main_window,
2595                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2596         if (!folder_view)
2597                 return;
2598
2599         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2600 }
2601
2602 static void
2603 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2604                                                gpointer user_data)
2605 {
2606         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2607         const GError *error = NULL;
2608         const gchar *message = NULL;
2609         
2610         /* Get error message */
2611         error = modest_mail_operation_get_error (mail_op);
2612         if (!error)
2613                 g_return_if_reached ();
2614
2615         switch (error->code) {
2616         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2617                 message = _CS("ckdg_ib_folder_already_exists");
2618                 break;
2619         default:
2620                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2621                            error->code, error->message);
2622                 return;
2623         }
2624
2625         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2626 }
2627
2628 void 
2629 modest_ui_actions_on_rename_folder (GtkAction *action,
2630                                      ModestMainWindow *main_window)
2631 {
2632         TnyFolderStore *folder;
2633         GtkWidget *folder_view;
2634         GtkWidget *header_view; 
2635
2636         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2637
2638         folder_view = modest_main_window_get_child_widget (main_window,
2639                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2640         if (!folder_view)
2641                 return;
2642
2643         header_view = modest_main_window_get_child_widget (main_window,
2644                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2645         
2646         if (!header_view)
2647                 return;
2648
2649         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2650
2651         if (!folder)
2652                 return;
2653
2654         if (TNY_IS_FOLDER (folder)) {
2655                 gchar *folder_name;
2656                 gint response;
2657                 const gchar *current_name;
2658                 TnyFolderStore *parent;
2659                 gboolean do_rename = TRUE;
2660
2661                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2662                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2663                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2664                                                                      parent, current_name, 
2665                                                                      &folder_name);
2666                 g_object_unref (parent);
2667
2668                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2669                         do_rename = FALSE;
2670                 } else if (modest_platform_is_network_folderstore(folder) &&
2671                            !tny_device_is_online (modest_runtime_get_device())) {
2672                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2673                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2674                         g_object_unref(account);
2675                 }
2676
2677                 if (do_rename) {
2678                         ModestMailOperation *mail_op;
2679                         GtkTreeSelection *sel = NULL;
2680
2681                         mail_op = 
2682                                 modest_mail_operation_new_with_error_handling (G_OBJECT(main_window),
2683                                                                                modest_ui_actions_rename_folder_error_handler,
2684                                                                                main_window, NULL);
2685
2686                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2687                                                          mail_op);
2688
2689                         /* Clear the headers view */
2690                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2691                         gtk_tree_selection_unselect_all (sel);
2692
2693                         /* Select *after* the changes */
2694                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2695                                                           TNY_FOLDER(folder), TRUE);
2696
2697                         /* Actually rename the folder */
2698                         modest_mail_operation_rename_folder (mail_op,
2699                                                              TNY_FOLDER (folder),
2700                                                              (const gchar *) folder_name);
2701
2702                         g_object_unref (mail_op);
2703                         g_free (folder_name);
2704                 }
2705         }
2706         g_object_unref (folder);
2707 }
2708
2709 static void
2710 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2711                                                gpointer user_data)
2712 {
2713         GObject *win = modest_mail_operation_get_source (mail_op);
2714
2715         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2716                                                 _("mail_in_ui_folder_delete_error"));
2717         g_object_unref (win);
2718 }
2719
2720 static gboolean
2721 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2722 {
2723         TnyFolderStore *folder;
2724         GtkWidget *folder_view;
2725         gint response;
2726         gchar *message;
2727         gboolean do_delete = TRUE;
2728
2729         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (main_window), FALSE);
2730
2731         folder_view = modest_main_window_get_child_widget (main_window,
2732                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2733         if (!folder_view)
2734                 return FALSE;
2735
2736         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2737
2738         /* Show an error if it's an account */
2739         if (!TNY_IS_FOLDER (folder)) {
2740                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2741                                                         _("mail_in_ui_folder_delete_error"));
2742                 g_object_unref (G_OBJECT (folder));
2743                 return FALSE;
2744         }
2745
2746         /* Ask the user */      
2747         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2748                                     tny_folder_get_name (TNY_FOLDER (folder)));
2749         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2750                                                             (const gchar *) message);
2751         g_free (message);
2752
2753         if (response != GTK_RESPONSE_OK) {
2754                 do_delete = FALSE;
2755         } else if (modest_platform_is_network_folderstore(folder) &&
2756                    !tny_device_is_online (modest_runtime_get_device())) {
2757                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2758                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2759                 g_object_unref(account);
2760         }
2761
2762         if (do_delete) {
2763                 ModestMailOperation *mail_op;
2764                 GtkTreeSelection *sel;
2765
2766                 /* Unselect the folder before deleting it to free the headers */
2767                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2768                 gtk_tree_selection_unselect_all (sel);
2769
2770                 /* Create the mail operation */
2771                 mail_op =
2772                         modest_mail_operation_new_with_error_handling (G_OBJECT(main_window),
2773                                                                        modest_ui_actions_delete_folder_error_handler,
2774                                                                        NULL, NULL);
2775
2776                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2777                                                  mail_op);
2778                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2779                 g_object_unref (G_OBJECT (mail_op));
2780         }
2781
2782         g_object_unref (G_OBJECT (folder));
2783
2784         return do_delete;
2785 }
2786
2787 void 
2788 modest_ui_actions_on_delete_folder (GtkAction *action,
2789                                      ModestMainWindow *main_window)
2790 {
2791         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2792
2793         delete_folder (main_window, FALSE);
2794 }
2795
2796 void 
2797 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2798 {
2799         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2800         
2801         delete_folder (main_window, TRUE);
2802 }
2803
2804
2805 static void
2806 show_error (GtkWidget *parent_widget, const gchar* text)
2807 {
2808         hildon_banner_show_information(parent_widget, NULL, text);
2809         
2810 #if 0
2811         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2812         /*
2813           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2814           (GtkDialogFlags)0,
2815           GTK_MESSAGE_ERROR,
2816           GTK_BUTTONS_OK,
2817           text ));
2818         */
2819                  
2820         gtk_dialog_run (dialog);
2821         gtk_widget_destroy (GTK_WIDGET (dialog));
2822 #endif
2823 }
2824
2825 void
2826 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2827                                          const gchar* server_account_name,
2828                                          gchar **username,
2829                                          gchar **password, 
2830                                          gboolean *cancel, 
2831                                          gboolean *remember,
2832                                          ModestMainWindow *main_window)
2833 {
2834         g_return_if_fail(server_account_name);
2835         
2836         /* Initalize output parameters: */
2837         if (cancel)
2838                 *cancel = FALSE;
2839                 
2840         if (remember)
2841                 *remember = TRUE;
2842                 
2843 #ifdef MODEST_PLATFORM_MAEMO
2844         /* Maemo uses a different (awkward) button order,
2845          * It should probably just use gtk_alternative_dialog_button_order ().
2846          */
2847         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2848                                               NULL,
2849                                               GTK_DIALOG_MODAL,
2850                                               _("mcen_bd_dialog_ok"),
2851                                               GTK_RESPONSE_ACCEPT,
2852                                               _("mcen_bd_dialog_cancel"),
2853                                               GTK_RESPONSE_REJECT,
2854                                               NULL);
2855 #else
2856         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2857                                               NULL,
2858                                               GTK_DIALOG_MODAL,
2859                                               GTK_STOCK_CANCEL,
2860                                               GTK_RESPONSE_REJECT,
2861                                               GTK_STOCK_OK,
2862                                               GTK_RESPONSE_ACCEPT,
2863                                               NULL);
2864 #endif /* MODEST_PLATFORM_MAEMO */
2865
2866         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2867         
2868         gchar *server_name = modest_account_mgr_get_server_account_hostname (
2869                 modest_runtime_get_account_mgr(), server_account_name);
2870         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2871                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2872                 if (cancel)
2873                         *cancel = TRUE;
2874                 return;
2875         }
2876         
2877         /* This causes a warning because the logical ID has no %s in it, 
2878          * though the translation does, but there is not much we can do about that: */
2879         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2880         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2881                             FALSE, FALSE, 0);
2882         g_free (txt);
2883         g_free (server_name);
2884         server_name = NULL;
2885
2886         /* username: */
2887         gchar *initial_username = modest_account_mgr_get_server_account_username (
2888                 modest_runtime_get_account_mgr(), server_account_name);
2889         
2890         GtkWidget *entry_username = gtk_entry_new ();
2891         if (initial_username)
2892                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2893         /* Dim this if a connection has ever succeeded with this username,
2894          * as per the UI spec: */
2895         const gboolean username_known = 
2896                 modest_account_mgr_get_server_account_username_has_succeeded(
2897                         modest_runtime_get_account_mgr(), server_account_name);
2898         gtk_widget_set_sensitive (entry_username, !username_known);
2899         
2900 #ifdef MODEST_PLATFORM_MAEMO
2901         /* Auto-capitalization is the default, so let's turn it off: */
2902         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2903         
2904         /* Create a size group to be used by all captions.
2905          * Note that HildonCaption does not create a default size group if we do not specify one.
2906          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2907         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2908         
2909         GtkWidget *caption = hildon_caption_new (sizegroup, 
2910                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2911         gtk_widget_show (entry_username);
2912         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2913                 FALSE, FALSE, MODEST_MARGIN_HALF);
2914         gtk_widget_show (caption);
2915 #else 
2916         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2917                             TRUE, FALSE, 0);
2918 #endif /* MODEST_PLATFORM_MAEMO */      
2919                             
2920         /* password: */
2921         GtkWidget *entry_password = gtk_entry_new ();
2922         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2923         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2924         
2925 #ifdef MODEST_PLATFORM_MAEMO
2926         /* Auto-capitalization is the default, so let's turn it off: */
2927         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2928                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2929         
2930         caption = hildon_caption_new (sizegroup, 
2931                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2932         gtk_widget_show (entry_password);
2933         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2934                 FALSE, FALSE, MODEST_MARGIN_HALF);
2935         gtk_widget_show (caption);
2936         g_object_unref (sizegroup);
2937 #else 
2938         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2939                             TRUE, FALSE, 0);
2940 #endif /* MODEST_PLATFORM_MAEMO */      
2941
2942         if (initial_username != NULL)
2943                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
2944                                 
2945 /* This is not in the Maemo UI spec:
2946         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2947         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2948                             TRUE, FALSE, 0);
2949 */
2950
2951         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2952         
2953         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2954                 if (username) {
2955                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2956                         
2957                         modest_account_mgr_set_server_account_username (
2958                                  modest_runtime_get_account_mgr(), server_account_name, 
2959                                  *username);
2960                                  
2961                         const gboolean username_was_changed = 
2962                                 (strcmp (*username, initial_username) != 0);
2963                         if (username_was_changed) {
2964                                 g_warning ("%s: tinymail does not yet support changing the "
2965                                         "username in the get_password() callback.\n", __FUNCTION__);
2966                         }
2967                 }
2968                         
2969                 if (password) {
2970                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2971                         
2972                         /* We do not save the password in the configuration, 
2973                          * because this function is only called for passwords that should 
2974                          * not be remembered:
2975                         modest_server_account_set_password (
2976                                  modest_runtime_get_account_mgr(), server_account_name, 
2977                                  *password);
2978                         */
2979                 }
2980                 
2981                 if (cancel)
2982                         *cancel   = FALSE;
2983                         
2984         } else {
2985                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2986                 
2987                 if (username)
2988                         *username = NULL;
2989                         
2990                 if (password)
2991                         *password = NULL;
2992                         
2993                 if (cancel)
2994                         *cancel   = TRUE;
2995         }
2996
2997 /* This is not in the Maemo UI spec:
2998         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2999                 *remember = TRUE;
3000         else
3001                 *remember = FALSE;
3002 */
3003
3004         gtk_widget_destroy (dialog);
3005         
3006         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3007 }
3008
3009 void
3010 modest_ui_actions_on_cut (GtkAction *action,
3011                           ModestWindow *window)
3012 {
3013         GtkWidget *focused_widget;
3014         GtkClipboard *clipboard;
3015
3016         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3017         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3018         if (GTK_IS_EDITABLE (focused_widget)) {
3019                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3020                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3021                 gtk_clipboard_store (clipboard);
3022         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3023                 GtkTextBuffer *buffer;
3024
3025                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3026                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3027                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3028                 gtk_clipboard_store (clipboard);
3029         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3030                 TnyList *header_list = modest_header_view_get_selected_headers (
3031                                 MODEST_HEADER_VIEW (focused_widget));
3032                 gboolean continue_download = FALSE;
3033                 gint num_of_unc_msgs;
3034
3035                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3036
3037                 if (num_of_unc_msgs) {
3038                         TnyAccount *account = get_account_from_header_list (header_list);
3039                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3040                         g_object_unref (account);
3041                 }
3042
3043                 if (num_of_unc_msgs == 0 || continue_download) {
3044 /*                      modest_platform_information_banner (
3045                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3046                         modest_header_view_cut_selection (
3047                                         MODEST_HEADER_VIEW (focused_widget));
3048                 }
3049
3050                 g_object_unref (header_list);
3051         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3052                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3053         }
3054 }
3055
3056 void
3057 modest_ui_actions_on_copy (GtkAction *action,
3058                            ModestWindow *window)
3059 {
3060         GtkClipboard *clipboard;
3061         GtkWidget *focused_widget;
3062         gboolean copied = TRUE;
3063
3064         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3065         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3066
3067         if (GTK_IS_LABEL (focused_widget)) {
3068                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
3069                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3070                 gtk_clipboard_store (clipboard);
3071         } else if (GTK_IS_EDITABLE (focused_widget)) {
3072                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3073                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3074                 gtk_clipboard_store (clipboard);
3075         } else if (GTK_IS_HTML (focused_widget)) {
3076                 gtk_html_copy (GTK_HTML (focused_widget));
3077                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3078                 gtk_clipboard_store (clipboard);
3079         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3080                 GtkTextBuffer *buffer;
3081                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3082                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
3083                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3084                 gtk_clipboard_store (clipboard);
3085         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3086                 TnyList *header_list = modest_header_view_get_selected_headers (
3087                                 MODEST_HEADER_VIEW (focused_widget));
3088                 gboolean continue_download = FALSE;
3089                 gint num_of_unc_msgs;
3090
3091                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3092
3093                 if (num_of_unc_msgs) {
3094                         TnyAccount *account = get_account_from_header_list (header_list);
3095                         continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3096                         g_object_unref (account);
3097                 }
3098
3099                 if (num_of_unc_msgs == 0 || continue_download) {
3100                         modest_platform_information_banner (
3101                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3102                         modest_header_view_copy_selection (
3103                                         MODEST_HEADER_VIEW (focused_widget));
3104                 } else
3105                         copied = FALSE;
3106
3107                 g_object_unref (header_list);
3108
3109         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3110                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3111         }
3112
3113         /* Show information banner if there was a copy to clipboard */
3114         if(copied)
3115                 modest_platform_information_banner (
3116                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3117 }
3118
3119 void
3120 modest_ui_actions_on_undo (GtkAction *action,
3121                            ModestWindow *window)
3122 {
3123         ModestEmailClipboard *clipboard = NULL;
3124
3125         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3126                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3127         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3128                 /* Clear clipboard source */
3129                 clipboard = modest_runtime_get_email_clipboard ();
3130                 modest_email_clipboard_clear (clipboard);               
3131         }
3132         else {
3133                 g_return_if_reached ();
3134         }
3135 }
3136
3137 void
3138 modest_ui_actions_on_redo (GtkAction *action,
3139                            ModestWindow *window)
3140 {
3141         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3142                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3143         }
3144         else {
3145                 g_return_if_reached ();
3146         }
3147 }
3148
3149
3150 static void
3151 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3152 {
3153         /* destroy information note */
3154         gtk_widget_destroy (GTK_WIDGET(user_data));
3155 }
3156
3157
3158 static void
3159 paste_as_attachment_free (gpointer data)
3160 {
3161         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3162
3163         gtk_widget_destroy (helper->banner);
3164         g_object_unref (helper->banner);
3165         g_free (helper);
3166 }
3167
3168 static void
3169 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3170                             TnyHeader *header,
3171                             TnyMsg *msg,
3172                             gpointer userdata)
3173 {
3174         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3175         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3176
3177         if (msg == NULL)
3178                 return;
3179
3180         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3181         
3182 }
3183
3184 void
3185 modest_ui_actions_on_paste (GtkAction *action,
3186                             ModestWindow *window)
3187 {
3188         GtkWidget *focused_widget = NULL;
3189         GtkWidget *inf_note = NULL;
3190         ModestMailOperation *mail_op = NULL;
3191
3192         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3193         if (GTK_IS_EDITABLE (focused_widget)) {
3194                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3195         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3196                 ModestEmailClipboard *e_clipboard = NULL;
3197                 e_clipboard = modest_runtime_get_email_clipboard ();
3198                 if (modest_email_clipboard_cleared (e_clipboard)) {
3199                         GtkTextBuffer *buffer;
3200                         GtkClipboard *clipboard;
3201
3202                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3203                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3204                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3205                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3206                         ModestMailOperation *mail_op;
3207                         TnyFolder *src_folder;
3208                         TnyList *data;
3209                         gboolean delete;
3210                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3211                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3212                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3213                                                                            _CS("ckct_nw_pasting"));
3214                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3215                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3216                         if (helper->banner != NULL) {
3217                                 g_object_ref (G_OBJECT (helper->banner));
3218                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3219                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3220                         }
3221
3222                         if (data != NULL) {
3223                                 modest_mail_operation_get_msgs_full (mail_op, 
3224                                                                      data,
3225                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3226                                                                      helper,
3227                                                                      paste_as_attachment_free);
3228                         }
3229                 }
3230         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3231                 ModestEmailClipboard *clipboard = NULL;
3232                 TnyFolder *src_folder = NULL;
3233                 TnyFolderStore *folder_store = NULL;
3234                 TnyList *data = NULL;           
3235                 gboolean delete = FALSE;
3236                 
3237                 /* Check clipboard source */
3238                 clipboard = modest_runtime_get_email_clipboard ();
3239                 if (modest_email_clipboard_cleared (clipboard)) 
3240                         return;
3241                 
3242                 /* Get elements to paste */
3243                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3244
3245                 /* Create a new mail operation */
3246                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3247                 
3248                 /* Get destination folder */
3249                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3250
3251                 /* transfer messages  */
3252                 if (data != NULL) {
3253                         gint response = 0;
3254
3255                         /* Ask for user confirmation */
3256                         response = 
3257                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3258                                                                              TNY_FOLDER (folder_store), 
3259                                                                              delete,
3260                                                                              data);
3261                         
3262                         if (response == GTK_RESPONSE_OK) {
3263                                 /* Launch notification */
3264                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3265                                                                              _CS("ckct_nw_pasting"));
3266                                 if (inf_note != NULL)  {
3267                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3268                                         gtk_widget_show (GTK_WIDGET(inf_note));
3269                                 }
3270
3271                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3272                                 modest_mail_operation_xfer_msgs (mail_op, 
3273                                                                  data,
3274                                                                  TNY_FOLDER (folder_store),
3275                                                                  delete,
3276                                                                  destroy_information_note,
3277                                                                  inf_note);                             
3278                         } else {
3279                                 g_object_unref (mail_op);
3280                         }
3281                         
3282                 } else if (src_folder != NULL) {                        
3283                         /* Launch notification */
3284                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3285                                                                      _CS("ckct_nw_pasting"));
3286                         if (inf_note != NULL)  {
3287                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3288                                 gtk_widget_show (GTK_WIDGET(inf_note));
3289                         }
3290                         
3291                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3292                         modest_mail_operation_xfer_folder (mail_op, 
3293                                                            src_folder,
3294                                                            folder_store,
3295                                                            delete,
3296                                                            destroy_information_note,
3297                                                            inf_note);
3298                 }
3299
3300                 /* Free */
3301                 if (data != NULL) 
3302                         g_object_unref (data);
3303                 if (src_folder != NULL) 
3304                         g_object_unref (src_folder);
3305                 if (folder_store != NULL) 
3306                         g_object_unref (folder_store);
3307         }
3308 }
3309
3310
3311 void
3312 modest_ui_actions_on_select_all (GtkAction *action,
3313                                  ModestWindow *window)
3314 {
3315         GtkWidget *focused_widget;
3316
3317         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3318         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3319                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3320         } else if (GTK_IS_LABEL (focused_widget)) {
3321                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3322         } else if (GTK_IS_EDITABLE (focused_widget)) {
3323                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3324         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3325                 GtkTextBuffer *buffer;
3326                 GtkTextIter start, end;
3327
3328                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3329                 gtk_text_buffer_get_start_iter (buffer, &start);
3330                 gtk_text_buffer_get_end_iter (buffer, &end);
3331                 gtk_text_buffer_select_range (buffer, &start, &end);
3332         } else if (GTK_IS_HTML (focused_widget)) {
3333                 gtk_html_select_all (GTK_HTML (focused_widget));
3334         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3335                 GtkWidget *header_view = focused_widget;
3336                 GtkTreeSelection *selection = NULL;
3337                 
3338                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3339                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3340                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3341                 }
3342                                 
3343                 /* Disable window dimming management */
3344                 modest_window_disable_dimming (MODEST_WINDOW(window));
3345                 
3346                 /* Select all messages */
3347                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3348                 gtk_tree_selection_select_all (selection);
3349
3350                 /* Set focuse on header view */
3351                 gtk_widget_grab_focus (header_view);
3352
3353
3354                 /* Enable window dimming management */
3355                 modest_window_enable_dimming (MODEST_WINDOW(window));
3356                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3357         }
3358
3359 }
3360
3361 void
3362 modest_ui_actions_on_mark_as_read (GtkAction *action,
3363                                    ModestWindow *window)
3364 {       
3365         g_return_if_fail (MODEST_IS_WINDOW(window));
3366                 
3367         /* Mark each header as read */
3368         do_headers_action (window, headers_action_mark_as_read, NULL);
3369 }
3370
3371 void
3372 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3373                                      ModestWindow *window)
3374 {       
3375         g_return_if_fail (MODEST_IS_WINDOW(window));
3376                 
3377         /* Mark each header as read */
3378         do_headers_action (window, headers_action_mark_as_unread, NULL);
3379 }
3380
3381 void
3382 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3383                                   GtkRadioAction *selected,
3384                                   ModestWindow *window)
3385 {
3386         gint value;
3387
3388         value = gtk_radio_action_get_current_value (selected);
3389         if (MODEST_IS_WINDOW (window)) {
3390                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3391         }
3392 }
3393
3394 void     
3395 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3396                                                GtkRadioAction *selected,
3397                                                ModestWindow *window)
3398 {
3399         TnyHeaderFlags flags;
3400         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3401
3402         flags = gtk_radio_action_get_current_value (selected);
3403         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3404 }
3405
3406 void     
3407 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3408                                                   GtkRadioAction *selected,
3409                                                   ModestWindow *window)
3410 {
3411         gint file_format;
3412
3413         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3414
3415         file_format = gtk_radio_action_get_current_value (selected);
3416         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3417 }
3418
3419
3420 void     
3421 modest_ui_actions_on_zoom_plus (GtkAction *action,
3422                                 ModestWindow *window)
3423 {
3424         g_return_if_fail (MODEST_IS_WINDOW (window));
3425
3426         modest_window_zoom_plus (MODEST_WINDOW (window));
3427 }
3428
3429 void     
3430 modest_ui_actions_on_zoom_minus (GtkAction *action,
3431                                  ModestWindow *window)
3432 {
3433         g_return_if_fail (MODEST_IS_WINDOW (window));
3434
3435         modest_window_zoom_minus (MODEST_WINDOW (window));
3436 }
3437
3438 void     
3439 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3440                                            ModestWindow *window)
3441 {
3442         ModestWindowMgr *mgr;
3443         gboolean fullscreen, active;
3444         g_return_if_fail (MODEST_IS_WINDOW (window));
3445
3446         mgr = modest_runtime_get_window_mgr ();
3447
3448         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3449         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3450
3451         if (active != fullscreen) {
3452                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3453                 gtk_window_present (GTK_WINDOW (window));
3454         }
3455 }
3456
3457 void
3458 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3459                                         ModestWindow *window)
3460 {
3461         ModestWindowMgr *mgr;
3462         gboolean fullscreen;
3463
3464         g_return_if_fail (MODEST_IS_WINDOW (window));
3465
3466         mgr = modest_runtime_get_window_mgr ();
3467         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3468         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3469
3470         gtk_window_present (GTK_WINDOW (window));
3471 }
3472
3473 /* 
3474  * Used by modest_ui_actions_on_details to call do_headers_action 
3475  */
3476 static void
3477 headers_action_show_details (TnyHeader *header, 
3478                              ModestWindow *window,
3479                              gpointer user_data)
3480
3481 {
3482         GtkWidget *dialog;
3483         
3484         /* Create dialog */
3485         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3486
3487         /* Run dialog */
3488         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3489         gtk_widget_show_all (dialog);
3490         gtk_dialog_run (GTK_DIALOG (dialog));
3491
3492         gtk_widget_destroy (dialog);
3493 }
3494
3495 /*
3496  * Show the folder details in a ModestDetailsDialog widget
3497  */
3498 static void
3499 show_folder_details (TnyFolder *folder, 
3500                      GtkWindow *window)
3501 {
3502         GtkWidget *dialog;
3503         
3504         /* Create dialog */
3505         dialog = modest_details_dialog_new_with_folder (window, folder);
3506
3507         /* Run dialog */
3508         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3509         gtk_widget_show_all (dialog);
3510         gtk_dialog_run (GTK_DIALOG (dialog));
3511
3512         gtk_widget_destroy (dialog);
3513 }
3514
3515 /*
3516  * Show the header details in a ModestDetailsDialog widget
3517  */
3518 void     
3519 modest_ui_actions_on_details (GtkAction *action, 
3520                               ModestWindow *win)
3521 {
3522         TnyList * headers_list;
3523         TnyIterator *iter;
3524         TnyHeader *header;              
3525
3526         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3527                 TnyMsg *msg;
3528
3529                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3530                 if (!msg)
3531                         return;
3532                 g_object_unref (msg);           
3533
3534                 headers_list = get_selected_headers (win);
3535                 if (!headers_list)
3536                         return;
3537
3538                 iter = tny_list_create_iterator (headers_list);
3539
3540                 header = TNY_HEADER (tny_iterator_get_current (iter));
3541                 if (header) {
3542                         headers_action_show_details (header, win, NULL);
3543                         g_object_unref (header);
3544                 }
3545
3546                 g_object_unref (iter);
3547                 g_object_unref (headers_list);
3548
3549         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3550                 GtkWidget *folder_view, *header_view;
3551
3552                 /* Check which widget has the focus */
3553                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3554                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3555                 if (gtk_widget_is_focus (folder_view)) {
3556                         TnyFolderStore *folder_store
3557                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3558                         if (!folder_store) {
3559                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3560                                 return; 
3561                         }
3562                         /* Show only when it's a folder */
3563                         /* This function should not be called for account items, 
3564                          * because we dim the menu item for them. */
3565                         if (TNY_IS_FOLDER (folder_store)) {
3566                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3567                         }
3568
3569                         g_object_unref (folder_store);
3570
3571                 } else {
3572                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3573                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3574                         /* Show details of each header */
3575                         do_headers_action (win, headers_action_show_details, header_view);
3576                 }
3577         }
3578 }
3579
3580 void     
3581 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3582                                      ModestMsgEditWindow *window)
3583 {
3584         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3585
3586         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3587 }
3588
3589 void     
3590 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3591                                       ModestMsgEditWindow *window)
3592 {
3593         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3594
3595         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3596 }
3597
3598 void
3599 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3600                                        ModestMainWindow *main_window)
3601 {
3602         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3603
3604         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3605                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3606         else
3607                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3608 }
3609
3610 void 
3611 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3612                                      ModestWindow *window)
3613 {
3614         gboolean active, fullscreen = FALSE;
3615         ModestWindowMgr *mgr;
3616
3617         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3618
3619         /* Check if we want to toggle the toolbar vuew in fullscreen
3620            or normal mode */
3621         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3622                      "ViewShowToolbarFullScreen")) {
3623                 fullscreen = TRUE;
3624         }
3625
3626         /* Toggle toolbar */
3627         mgr = modest_runtime_get_window_mgr ();
3628         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3629 }
3630
3631 void     
3632 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3633                                            ModestMsgEditWindow *window)
3634 {
3635         modest_msg_edit_window_select_font (window);
3636 }
3637
3638 void
3639 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3640                                                   const gchar *display_name,
3641                                                   GtkWindow *window)
3642 {
3643         /* Do not change the application name if the widget has not
3644            the focus. This callback could be called even if the folder
3645            view has not the focus, because the handled signal could be
3646            emitted when the folder view is redrawn */
3647         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3648                 if (display_name)
3649                         gtk_window_set_title (window, display_name);
3650                 else
3651                         gtk_window_set_title (window, " ");
3652         }
3653 }
3654
3655 void
3656 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3657 {
3658         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3659         modest_msg_edit_window_select_contacts (window);
3660 }
3661
3662 void
3663 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3664 {
3665         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3666         modest_msg_edit_window_check_names (window, FALSE);
3667 }
3668
3669 static void
3670 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3671 {
3672         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3673                                          GTK_WIDGET (user_data));
3674 }
3675
3676 /*
3677  * This function is used to track changes in the selection of the
3678  * folder view that is inside the "move to" dialog to enable/disable
3679  * the OK button because we do not want the user to select a disallowed
3680  * destination for a folder.
3681  * The user also not desired to be able to use NEW button on items where
3682  * folder creation is not possibel.
3683  */
3684 static void
3685 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3686                                             TnyFolderStore *folder_store,
3687                                             gboolean selected,
3688                                             gpointer user_data)
3689 {
3690         GtkWidget *dialog = NULL;
3691         GtkWidget *ok_button = NULL, *new_button = NULL;
3692         GList *children = NULL;
3693         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3694         gboolean moving_folder = FALSE;
3695         gboolean is_local_account = TRUE;
3696         GtkWidget *folder_view = NULL;
3697         ModestTnyFolderRules rules;
3698
3699         if (!selected)
3700                 return;
3701
3702         /* Get the OK button */
3703         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3704         if (!dialog)
3705                 return;
3706
3707         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3708         ok_button = GTK_WIDGET (children->next->next->data);
3709         new_button = GTK_WIDGET (children->next->data);
3710         g_list_free (children);
3711
3712         /* check if folder_store is an remote account */
3713         if (TNY_IS_ACCOUNT (folder_store)) {
3714                 TnyAccount *local_account = NULL;
3715                 TnyAccount *mmc_account = NULL;
3716                 ModestTnyAccountStore *account_store = NULL;
3717
3718                 account_store = modest_runtime_get_account_store ();
3719                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3720                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
3721
3722                 if ((gpointer) local_account != (gpointer) folder_store &&
3723                     (gpointer) mmc_account != (gpointer) folder_store) {
3724                         is_local_account = FALSE;
3725                         /* New button should be dimmed on remote
3726                            account root */
3727                         new_sensitive = FALSE;
3728                 }
3729                 g_object_unref (local_account);
3730         }
3731
3732         /* Check the target folder rules */
3733         if (TNY_IS_FOLDER (folder_store)) {
3734                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3735                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3736                         ok_sensitive = FALSE;
3737                         new_sensitive = FALSE;
3738                         goto end;
3739                 }
3740         }
3741
3742         /* Check if we're moving a folder */
3743         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3744                 /* Get the widgets */
3745                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3746                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3747                 if (gtk_widget_is_focus (folder_view))
3748                         moving_folder = TRUE;
3749         }
3750
3751         if (moving_folder) {
3752                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3753
3754                 /* Get the folder to move */
3755                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3756                 
3757                 /* Check that we're not moving to the same folder */
3758                 if (TNY_IS_FOLDER (moved_folder)) {
3759                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3760                         if (parent == folder_store)
3761                                 ok_sensitive = FALSE;
3762                         g_object_unref (parent);
3763                 } 
3764
3765                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3766                         /* Do not allow to move to an account unless it's the
3767                            local folders account */
3768                         if (!is_local_account)
3769                                 ok_sensitive = FALSE;
3770                 } 
3771
3772                 if (ok_sensitive && (moved_folder == folder_store)) {
3773                         /* Do not allow to move to itself */
3774                         ok_sensitive = FALSE;
3775                 }
3776                 g_object_unref (moved_folder);
3777         } else {
3778                 TnyHeader *header = NULL;
3779                 TnyFolder *src_folder = NULL;
3780
3781                 /* Moving a message */
3782                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3783                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3784                         src_folder = tny_header_get_folder (header);
3785                         g_object_unref (header);
3786                 } else {
3787                         src_folder = 
3788                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3789                 }
3790
3791                 /* Do not allow to move the msg to the same folder */
3792                 /* Do not allow to move the msg to an account */
3793                 if ((gpointer) src_folder == (gpointer) folder_store ||
3794                     TNY_IS_ACCOUNT (folder_store))
3795                         ok_sensitive = FALSE;
3796                 g_object_unref (src_folder);
3797         }
3798
3799  end:
3800         /* Set sensitivity of the OK button */
3801         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3802         /* Set sensitivity of the NEW button */
3803         gtk_widget_set_sensitive (new_button, new_sensitive);
3804 }
3805
3806 static GtkWidget*
3807 create_move_to_dialog (GtkWindow *win,
3808                        GtkWidget *folder_view,
3809                        GtkWidget **tree_view)
3810 {
3811         GtkWidget *dialog, *scroll;
3812         GtkWidget *new_button;
3813
3814         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3815                                               GTK_WINDOW (win),
3816                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3817                                               NULL);
3818
3819         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3820         /* We do this manually so GTK+ does not associate a response ID for
3821          * the button. */
3822         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3823         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3824         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3825
3826         /* Create scrolled window */
3827         scroll = gtk_scrolled_window_new (NULL, NULL);
3828         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3829                                          GTK_POLICY_AUTOMATIC,
3830                                          GTK_POLICY_AUTOMATIC);
3831
3832         /* Create folder view */
3833         *tree_view = modest_platform_create_folder_view (NULL);
3834
3835         /* Track changes in the selection to
3836          * disable the OK button whenever "Move to" is not possible
3837          * disbale NEW button whenever New is not possible */
3838         g_signal_connect (*tree_view,
3839                           "folder_selection_changed",
3840                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3841                           win);
3842
3843         /* Listen to clicks on New button */
3844         g_signal_connect (G_OBJECT (new_button), 
3845                           "clicked", 
3846                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3847                           *tree_view);
3848
3849         /* It could happen that we're trying to move a message from a
3850            window (msg window for example) after the main window was
3851            closed, so we can not just get the model of the folder
3852            view */
3853         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3854                 const gchar *visible_id = NULL;
3855
3856                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3857                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3858                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3859                                                MODEST_FOLDER_VIEW(*tree_view));
3860
3861                 visible_id = 
3862                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3863
3864                 /* Show the same account than the one that is shown in the main window */
3865                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3866                                                                              visible_id);
3867         } else {
3868                 const gchar *active_account_name = NULL;
3869                 ModestAccountMgr *mgr = NULL;
3870                 ModestAccountData *acc_data = NULL;
3871
3872                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
3873                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
3874                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3875                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3876
3877                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3878                 mgr = modest_runtime_get_account_mgr ();
3879                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3880
3881                 /* Set the new visible & active account */
3882                 if (acc_data && acc_data->store_account) { 
3883                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3884                                                                                      acc_data->store_account->account_name);
3885                         modest_account_mgr_free_account_data (mgr, acc_data);
3886                 }
3887         }
3888
3889         /* Hide special folders */
3890         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3891         
3892         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3893
3894         /* Add scroll to dialog */
3895         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3896                             scroll, TRUE, TRUE, 0);
3897
3898         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3899         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3900
3901         return dialog;
3902 }
3903
3904 /*
3905  * Returns TRUE if at least one of the headers of the list belongs to
3906  * a message that has been fully retrieved.
3907  */
3908 #if 0 /* no longer in use. delete in 2007.10 */
3909 static gboolean
3910 has_retrieved_msgs (TnyList *list)
3911 {
3912         TnyIterator *iter;
3913         gboolean found = FALSE;
3914
3915         iter = tny_list_create_iterator (list);
3916         while (!tny_iterator_is_done (iter) && !found) {
3917                 TnyHeader *header;
3918                 TnyHeaderFlags flags = 0;
3919
3920                 header = TNY_HEADER (tny_iterator_get_current (iter));
3921                 if (header) {
3922                         flags = tny_header_get_flags (header);
3923                         if (flags & TNY_HEADER_FLAG_CACHED)
3924 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3925                                 found = TRUE;
3926
3927                         g_object_unref (header);
3928                 }
3929
3930                 if (!found)
3931                         tny_iterator_next (iter);
3932         }
3933         g_object_unref (iter);
3934
3935         return found;
3936 }
3937 #endif /* 0 */
3938
3939
3940 /*
3941  * Shows a confirmation dialog to the user when we're moving messages
3942  * from a remote server to the local storage. Returns the dialog
3943  * response. If it's other kind of movement then it always returns
3944  * GTK_RESPONSE_OK
3945  *
3946  * This one is used by the next functions:
3947  *      modest_ui_actions_on_paste                      - commented out
3948  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3949  */
3950 gint
3951 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
3952                                              TnyFolder *dest_folder,
3953                                              gboolean delete,
3954                                              TnyList *headers)
3955 {
3956         gint response = GTK_RESPONSE_OK;
3957         TnyAccount *account = NULL;
3958         TnyFolder *src_folder = NULL;
3959         TnyIterator *iter = NULL;
3960         TnyHeader *header = NULL;
3961
3962         /* return with OK if the destination is a remote folder */
3963         if (modest_tny_folder_is_remote_folder (dest_folder))
3964                 return GTK_RESPONSE_OK;
3965
3966         /* Get source folder */
3967         iter = tny_list_create_iterator (headers);
3968         header = TNY_HEADER (tny_iterator_get_current (iter));
3969         if (header) {
3970                 src_folder = tny_header_get_folder (header);
3971                 g_object_unref (header);
3972         }
3973         g_object_unref (iter);
3974
3975         /* if no src_folder, message may be an attahcment */
3976         if (src_folder == NULL) 
3977                 return GTK_RESPONSE_CANCEL;
3978
3979         /* If the source is a local or MMC folder */
3980         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3981                 g_object_unref (src_folder);
3982                 return GTK_RESPONSE_OK;
3983         }
3984
3985         /* Get the account */
3986         account = tny_folder_get_account (src_folder);
3987
3988         /* now if offline we ask the user */
3989         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
3990                 response = GTK_RESPONSE_OK;
3991         else
3992                 response = GTK_RESPONSE_CANCEL;
3993
3994         /* Frees */
3995         g_object_unref (src_folder);
3996         g_object_unref (account);
3997
3998         return response;
3999 }
4000
4001
4002
4003 static void
4004 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
4005 {
4006         MoveToHelper *helper = (MoveToHelper *) user_data;
4007
4008         /* Note that the operation could have failed, in that case do
4009            nothing */
4010         if (modest_mail_operation_get_status (mail_op) == 
4011             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4012
4013                 GObject *object = modest_mail_operation_get_source (mail_op);
4014                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4015                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4016
4017                         if (!modest_msg_view_window_select_next_message (self))
4018                                 if (!modest_msg_view_window_select_previous_message (self))
4019                                         /* No more messages to view, so close this window */
4020                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4021                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4022                         GtkWidget *header_view;
4023                         GtkTreePath *path;
4024                         GtkTreeSelection *sel;
4025
4026                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4027                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4028                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4029                         path = gtk_tree_row_reference_get_path (helper->reference);
4030                         gtk_tree_selection_select_path (sel, path);
4031                         gtk_tree_path_free (path);
4032                 }
4033                 g_object_unref (object);
4034         }
4035
4036         /* Close the "Pasting" information banner */
4037         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4038         if (helper->reference != NULL)
4039                 gtk_tree_row_reference_free (helper->reference);
4040         g_free (helper);
4041 }
4042
4043 void
4044 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4045                                              gpointer user_data)
4046 {
4047         ModestWindow *main_window = NULL;
4048         GObject *win = NULL;
4049         const GError *error = NULL;
4050         const gchar *message = NULL;
4051         
4052         /* Get error message */
4053         error = modest_mail_operation_get_error (mail_op);
4054         if (error != NULL && error->message != NULL) {
4055                 message = error->message;
4056         } else {
4057                 message = _("mail_in_ui_folder_move_target_error");
4058         }
4059         
4060         /* Disable next automatic folder selection */
4061         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4062                                                          FALSE); /* don't create */
4063         if (main_window) {
4064                 GtkWidget *folder_view = NULL;
4065         
4066                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4067                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4068                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4069                 
4070                 if (user_data && TNY_IS_FOLDER (user_data)) {
4071                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4072                                                           TNY_FOLDER (user_data), FALSE);
4073                 }
4074         }
4075
4076         /* Show notification dialog */
4077         win = modest_mail_operation_get_source (mail_op);
4078         if (G_IS_OBJECT (win)) {
4079                 modest_platform_run_information_dialog (GTK_WINDOW (win), message);
4080                 g_object_unref (win);
4081         }
4082 }
4083
4084 void
4085 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4086                                               gpointer user_data)
4087 {
4088         GObject *win = modest_mail_operation_get_source (mail_op);
4089         const GError *error = modest_mail_operation_get_error (mail_op);
4090
4091         g_return_if_fail (error != NULL);
4092         if (error->message != NULL)             
4093                 g_printerr ("modest: %s\n", error->message);
4094         else
4095                 g_printerr ("modest: unkonw error on send&receive operation");
4096
4097         /* Show error message */
4098 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4099 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4100 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4101 /*      else  */
4102 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4103 /*                                                      _CS("sfil_ib_unable_to_send")); */
4104         g_object_unref (win);
4105 }
4106
4107 static void
4108 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4109                        TnyHeader *header, 
4110                        TnyMsg *msg, 
4111                        gpointer user_data)
4112 {
4113         TnyList *parts;
4114         TnyIterator *iter;
4115         gint pending_purges = 0;
4116         gboolean some_purged = FALSE;
4117         ModestWindow *win = MODEST_WINDOW (user_data);
4118         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4119
4120         /* If there was any error */
4121         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4122                 modest_window_mgr_unregister_header (mgr, header);
4123                 return;
4124         }
4125
4126         /* Once the message has been retrieved for purging, we check if
4127          * it's all ok for purging */
4128
4129         parts = tny_simple_list_new ();
4130         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4131         iter = tny_list_create_iterator (parts);
4132
4133         while (!tny_iterator_is_done (iter)) {
4134                 TnyMimePart *part;
4135                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4136                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4137                         if (tny_mime_part_is_purged (part))
4138                                 some_purged = TRUE;
4139                         else
4140                                 pending_purges++;
4141                 }
4142
4143                 if (part)
4144                         g_object_unref (part);
4145
4146                 tny_iterator_next (iter);
4147         }
4148         g_object_unref (iter);
4149         
4150
4151         if (pending_purges>0) {
4152                 gint response;
4153                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4154
4155                 if (response == GTK_RESPONSE_OK) {
4156                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4157                         iter = tny_list_create_iterator (parts);
4158                         while (!tny_iterator_is_done (iter)) {
4159                                 TnyMimePart *part;
4160                                 
4161                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4162                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4163                                         tny_mime_part_set_purged (part);
4164
4165                                 if (part)
4166                                         g_object_unref (part);
4167
4168                                 tny_iterator_next (iter);
4169                         }
4170                         
4171                         tny_msg_rewrite_cache (msg);
4172                 }
4173         } else {
4174                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4175         }
4176         g_object_unref (iter);
4177
4178         modest_window_mgr_unregister_header (mgr, header);
4179
4180         g_object_unref (parts);
4181 }
4182
4183 static void
4184 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4185                                                      ModestMainWindow *win)
4186 {
4187         GtkWidget *header_view;
4188         TnyList *header_list;
4189         TnyIterator *iter;
4190         TnyHeader *header;
4191         TnyHeaderFlags flags;
4192         ModestWindow *msg_view_window =  NULL;
4193         gboolean found;
4194
4195         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4196
4197         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4198                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4199
4200         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4201         if (!header_list) {
4202                 g_warning ("%s: no header selected", __FUNCTION__);
4203                 return;
4204         }
4205         
4206         if (tny_list_get_length (header_list) == 1) {
4207                 iter = tny_list_create_iterator (header_list);
4208                 header = TNY_HEADER (tny_iterator_get_current (iter));
4209                 g_object_unref (iter);
4210         } else
4211                 return;
4212         
4213         if (!header || !TNY_IS_HEADER(header)) {
4214                 g_warning ("%s: header is not valid", __FUNCTION__);
4215                 return;
4216         }
4217         
4218         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4219                                                           header, &msg_view_window);
4220         flags = tny_header_get_flags (header);
4221         if (!(flags & TNY_HEADER_FLAG_CACHED))
4222                 return;
4223         if (found) {
4224                 if (msg_view_window != NULL) 
4225                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4226                 else {
4227                         /* do nothing; uid was registered before, so window is probably on it's way */
4228                         g_warning ("debug: header %p has already been registered", header);
4229                 }
4230         } else {
4231                 ModestMailOperation *mail_op = NULL;
4232                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4233                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4234                                                                          modest_ui_actions_get_msgs_full_error_handler,
4235                                                                          NULL, NULL);
4236                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4237                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4238                 
4239                 g_object_unref (mail_op);
4240         }
4241         if (header)
4242                 g_object_unref (header);
4243         if (header_list)
4244                 g_object_unref (header_list);
4245 }
4246
4247 /**
4248  * Utility function that transfer messages from both the main window
4249  * and the msg view window when using the "Move to" dialog
4250  */
4251 static void
4252 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4253                                               ModestWindow *win)
4254 {
4255         TnyList *headers = NULL;
4256         TnyAccount *dst_account = NULL;
4257         const gchar *proto_str = NULL;
4258         gboolean dst_is_pop = FALSE;
4259
4260         if (!TNY_IS_FOLDER (dst_folder)) {
4261                 modest_platform_information_banner (GTK_WIDGET (win),
4262                                                     NULL,
4263                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4264                 return;
4265         }
4266
4267         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4268         proto_str = tny_account_get_proto (dst_account);
4269
4270         /* tinymail will return NULL for local folders it seems */
4271         dst_is_pop = proto_str &&
4272                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4273                  MODEST_PROTOCOL_STORE_POP);
4274
4275         g_object_unref (dst_account);
4276
4277         /* Get selected headers */
4278         headers = get_selected_headers (MODEST_WINDOW (win));
4279         if (!headers) {
4280                 g_warning ("%s: no headers selected", __FUNCTION__);
4281                 return;
4282         }
4283
4284
4285         if (dst_is_pop) {
4286                 modest_platform_information_banner (GTK_WIDGET (win),
4287                                                     NULL,
4288                                                     ngettext("mail_in_ui_folder_move_target_error",
4289                                                              "mail_in_ui_folder_move_targets_error",
4290                                                              tny_list_get_length (headers)));
4291                 g_object_unref (headers);
4292                 return;
4293         }
4294
4295         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4296         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4297                                                            _CS("ckct_nw_pasting"));
4298         if (helper->banner != NULL)  {
4299                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4300                 gtk_widget_show (GTK_WIDGET(helper->banner));
4301         }
4302
4303         if (MODEST_IS_MAIN_WINDOW (win)) {
4304                 GtkWidget *header_view = 
4305                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4306                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4307                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4308         }
4309
4310         ModestMailOperation *mail_op = 
4311                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4312                                                                modest_ui_actions_move_folder_error_handler,
4313                                                                NULL, NULL);
4314         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4315                                          mail_op);
4316
4317         modest_mail_operation_xfer_msgs (mail_op, 
4318                                          headers,
4319                                          TNY_FOLDER (dst_folder),
4320                                          TRUE,
4321                                          move_to_cb,
4322                                          helper);
4323
4324         g_object_unref (G_OBJECT (mail_op));
4325         g_object_unref (headers);
4326 }
4327
4328 /*
4329  * UI handler for the "Move to" action when invoked from the
4330  * ModestMainWindow
4331  */
4332 static void 
4333 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4334                                           GtkWidget *folder_view,
4335                                           TnyFolderStore *dst_folder,
4336                                           ModestMainWindow *win)
4337 {
4338         ModestHeaderView *header_view = NULL;
4339         ModestMailOperation *mail_op = NULL;
4340         TnyFolderStore *src_folder;
4341         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4342
4343         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4344
4345         /* Get the source folder */
4346         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4347
4348         /* Get header view */
4349         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4350
4351         /* Get folder or messages to transfer */
4352         if (gtk_widget_is_focus (folder_view)) {
4353                 GtkTreeSelection *sel;
4354                 gboolean do_xfer = TRUE;
4355
4356                 /* Allow only to transfer folders to the local root folder */
4357                 if (TNY_IS_ACCOUNT (dst_folder) && 
4358                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4359                         do_xfer = FALSE;
4360                 } else if (!TNY_IS_FOLDER (src_folder)) {
4361                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4362                         do_xfer = FALSE;
4363                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4364                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER (src_folder));
4365                         TnyAccount *account = tny_folder_get_account (TNY_FOLDER (src_folder));
4366                         if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4367                                 do_xfer = FALSE;
4368                         g_object_unref (account);
4369                 }
4370
4371                 if (do_xfer) {
4372                         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4373                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4374                                                                            _CS("ckct_nw_pasting"));
4375                         if (helper->banner != NULL)  {
4376                                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4377                                 gtk_widget_show (GTK_WIDGET(helper->banner));
4378                         }
4379                         /* Clean folder on header view before moving it */
4380                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4381                         gtk_tree_selection_unselect_all (sel);
4382
4383                         /* Let gtk events run. We need that the folder
4384                            view frees its reference to the source
4385                            folder *before* issuing the mail operation
4386                            so we need the signal handler of selection
4387                            changed to happen before the mail
4388                            operation */
4389                         while (gtk_events_pending ())
4390                                 gtk_main_iteration ();
4391
4392                         mail_op =
4393                           modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4394                                                                          modest_ui_actions_move_folder_error_handler,
4395                                                                          src_folder, NULL);
4396                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4397                                                          mail_op);
4398
4399                         /* Select *after* the changes */
4400                         /* TODO: this function hangs UI after transfer */ 
4401 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4402 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4403                         
4404                         modest_mail_operation_xfer_folder (mail_op,
4405                                                            TNY_FOLDER (src_folder),
4406                                                            dst_folder,
4407                                                            TRUE, 
4408                                                            move_to_cb, 
4409                                                            helper);
4410                         /* Unref mail operation */
4411                         g_object_unref (G_OBJECT (mail_op));
4412                 }
4413         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4414                 gboolean do_xfer = TRUE;
4415                 /* Ask for confirmation if the source folder is remote and we're not connected */
4416                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4417                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4418                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4419                                 guint num_headers = tny_list_get_length(headers);
4420                                 TnyAccount *account = get_account_from_header_list (headers);
4421                                 if (!connect_to_get_msg(MODEST_WINDOW (win), num_headers, account))
4422                                         do_xfer = FALSE;
4423                                 g_object_unref (account);
4424                         }
4425                         g_object_unref(headers);
4426                 }
4427                 if (do_xfer) /* Transfer messages */
4428                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4429         }
4430
4431     if (src_folder)
4432         g_object_unref (src_folder);
4433 }
4434
4435
4436 /*
4437  * UI handler for the "Move to" action when invoked from the
4438  * ModestMsgViewWindow
4439  */
4440 static void 
4441 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4442                                               TnyFolderStore *dst_folder,
4443                                               ModestMsgViewWindow *win)
4444 {
4445         TnyHeader *header = NULL;
4446         TnyFolder *src_folder = NULL;
4447         TnyAccount *account = NULL;
4448         gboolean do_xfer = FALSE;
4449
4450         /* Create header list */
4451         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4452         src_folder = TNY_FOLDER (tny_header_get_folder(header));
4453         g_object_unref (header);
4454
4455         account = tny_folder_get_account (src_folder);
4456         if (!modest_platform_is_network_folderstore(TNY_FOLDER_STORE(src_folder))) {
4457                 /* Transfer if the source folder is local */
4458                 do_xfer = TRUE;
4459         } else if (remote_folder_is_pop(TNY_FOLDER_STORE(src_folder))) {
4460                 /* Transfer if the source folder is POP (as it means
4461                  * that the message is already downloaded) */
4462                 do_xfer = TRUE;
4463         } else if (connect_to_get_msg(MODEST_WINDOW(win), 1, account)) {
4464                 /* Transfer after asking confirmation */
4465                 do_xfer = TRUE;
4466         }
4467
4468         if (do_xfer) {
4469                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4470         }
4471         g_object_unref (account);
4472         g_object_unref (src_folder);
4473 }
4474
4475 void 
4476 modest_ui_actions_on_move_to (GtkAction *action, 
4477                               ModestWindow *win)
4478 {
4479         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4480         gint result = 0;
4481         TnyFolderStore *dst_folder = NULL;
4482         ModestMainWindow *main_window;
4483
4484         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4485                           MODEST_IS_MSG_VIEW_WINDOW (win));
4486
4487         /* Get the main window if exists */
4488         if (MODEST_IS_MAIN_WINDOW (win))
4489                 main_window = MODEST_MAIN_WINDOW (win);
4490         else
4491                 main_window = 
4492                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4493                                                                                FALSE)); /* don't create */
4494
4495         /* Get the folder view widget if exists */
4496         if (main_window)
4497                 folder_view = modest_main_window_get_child_widget (main_window,
4498                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4499         else
4500                 folder_view = NULL;
4501
4502         /* Create and run the dialog */
4503         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4504         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4505         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4506         result = gtk_dialog_run (GTK_DIALOG(dialog));
4507         g_object_ref (tree_view);
4508         gtk_widget_destroy (dialog);
4509
4510         if (result != GTK_RESPONSE_ACCEPT)
4511                 return;
4512
4513         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4514         /* Do window specific stuff */
4515         if (MODEST_IS_MAIN_WINDOW (win)) {
4516                 modest_ui_actions_on_main_window_move_to (action,
4517                                                           folder_view,
4518                                                           dst_folder,
4519                                                           MODEST_MAIN_WINDOW (win));
4520         } else {
4521                 modest_ui_actions_on_msg_view_window_move_to (action,
4522                                                               dst_folder,
4523                                                               MODEST_MSG_VIEW_WINDOW (win));
4524         }
4525
4526         if (dst_folder)
4527                 g_object_unref (dst_folder);
4528 }
4529
4530 /*
4531  * Calls #HeadersFunc for each header already selected in the main
4532  * window or the message currently being shown in the msg view window
4533  */
4534 static void
4535 do_headers_action (ModestWindow *win, 
4536                    HeadersFunc func,
4537                    gpointer user_data)
4538 {
4539         TnyList *headers_list = NULL;
4540         TnyIterator *iter = NULL;
4541         TnyHeader *header = NULL;
4542         TnyFolder *folder = NULL;
4543
4544         /* Get headers */
4545         headers_list = get_selected_headers (win);
4546         if (!headers_list)
4547                 return;
4548
4549         /* Get the folder */
4550         iter = tny_list_create_iterator (headers_list);
4551         header = TNY_HEADER (tny_iterator_get_current (iter));
4552         if (header) {
4553                 folder = tny_header_get_folder (header);
4554                 g_object_unref (header);
4555         }
4556
4557         /* Call the function for each header */
4558         while (!tny_iterator_is_done (iter)) {
4559                 header = TNY_HEADER (tny_iterator_get_current (iter));
4560                 func (header, win, user_data);
4561                 g_object_unref (header);
4562                 tny_iterator_next (iter);
4563         }
4564
4565         /* Trick: do a poke status in order to speed up the signaling
4566            of observers */
4567         tny_folder_poke_status (folder);
4568
4569         /* Frees */
4570         g_object_unref (folder);
4571         g_object_unref (iter);
4572         g_object_unref (headers_list);
4573 }
4574
4575 void 
4576 modest_ui_actions_view_attachment (GtkAction *action,
4577                                    ModestWindow *window)
4578 {
4579         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4580                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4581         } else {
4582                 /* not supported window for this action */
4583                 g_return_if_reached ();
4584         }
4585 }
4586
4587 void
4588 modest_ui_actions_save_attachments (GtkAction *action,
4589                                     ModestWindow *window)
4590 {
4591         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4592                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4593         } else {
4594                 /* not supported window for this action */
4595                 g_return_if_reached ();
4596         }
4597 }
4598
4599 void
4600 modest_ui_actions_remove_attachments (GtkAction *action,
4601                                       ModestWindow *window)
4602 {
4603         if (MODEST_IS_MAIN_WINDOW (window)) {
4604                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4605         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4606                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4607         } else {
4608                 /* not supported window for this action */
4609                 g_return_if_reached ();
4610         }
4611 }
4612
4613 void 
4614 modest_ui_actions_on_settings (GtkAction *action, 
4615                                ModestWindow *win)
4616 {
4617         GtkWidget *dialog;
4618
4619         dialog = modest_platform_get_global_settings_dialog ();
4620         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4621         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4622         gtk_widget_show_all (dialog);
4623
4624         gtk_dialog_run (GTK_DIALOG (dialog));
4625
4626         gtk_widget_destroy (dialog);
4627 }
4628
4629 void 
4630 modest_ui_actions_on_help (GtkAction *action, 
4631                            GtkWindow *win)
4632 {
4633         const gchar *help_id;
4634
4635         g_return_if_fail (action);
4636         g_return_if_fail (win && GTK_IS_WINDOW(win));
4637         
4638         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
4639         
4640         if (help_id)
4641                 modest_platform_show_help (GTK_WINDOW (win), help_id);
4642         else
4643                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
4644 }
4645
4646 void 
4647 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4648                                             ModestWindow *window)
4649 {
4650         ModestMailOperation *mail_op;
4651         TnyList *headers;
4652
4653         /* Get headers */
4654         headers = get_selected_headers (window);
4655         if (!headers)
4656                 return;
4657
4658         /* Create mail operation */
4659         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (window),
4660                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4661                                                                  NULL, NULL);
4662         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4663         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4664
4665         /* Frees */
4666         g_object_unref (headers);
4667         g_object_unref (mail_op);
4668 }
4669
4670 void
4671 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4672                                           ModestWindow *window)
4673 {
4674         g_return_if_fail (MODEST_IS_WINDOW (window));
4675         
4676         /* Update dimmed */     
4677         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4678 }
4679
4680 void
4681 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4682                                           ModestWindow *window)
4683 {
4684         g_return_if_fail (MODEST_IS_WINDOW (window));
4685
4686         /* Update dimmed */     
4687         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4688 }
4689
4690 void
4691 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4692                                           ModestWindow *window)
4693 {
4694         g_return_if_fail (MODEST_IS_WINDOW (window));
4695
4696         /* Update dimmed */     
4697         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4698 }
4699
4700 void
4701 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4702                                             ModestWindow *window)
4703 {
4704         g_return_if_fail (MODEST_IS_WINDOW (window));
4705
4706         /* Update dimmed */     
4707         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4708 }
4709
4710 void
4711 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4712                                           ModestWindow *window)
4713 {
4714         g_return_if_fail (MODEST_IS_WINDOW (window));
4715
4716         /* Update dimmed */     
4717         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4718 }
4719
4720 void
4721 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4722                                           ModestWindow *window)
4723 {
4724         g_return_if_fail (MODEST_IS_WINDOW (window));
4725
4726         /* Update dimmed */     
4727         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4728 }
4729
4730 void
4731 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4732                                                  ModestWindow *window)
4733 {
4734         g_return_if_fail (MODEST_IS_WINDOW (window));
4735
4736         /* Update dimmed */     
4737         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4738 }
4739
4740 void
4741 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4742                                                      ModestWindow *window)
4743 {
4744         g_return_if_fail (MODEST_IS_WINDOW (window));
4745
4746         /* Update dimmed */     
4747         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4748 }
4749
4750 void
4751 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4752                                                      ModestWindow *window)
4753 {
4754         g_return_if_fail (MODEST_IS_WINDOW (window));
4755
4756         /* Update dimmed */     
4757         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4758 }
4759
4760 void
4761 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4762 {
4763         g_return_if_fail (MODEST_IS_WINDOW (window));
4764
4765         /* Update dimmed */     
4766         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4767 }
4768
4769 void
4770 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4771 {
4772         g_return_if_fail (MODEST_IS_WINDOW (window));
4773
4774         modest_platform_show_search_messages (GTK_WINDOW (window));
4775 }
4776
4777 void     
4778 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4779 {
4780         g_return_if_fail (MODEST_IS_WINDOW (win));
4781         modest_platform_show_addressbook (GTK_WINDOW (win));
4782 }
4783
4784
4785 void
4786 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4787                                           ModestWindow *window)
4788 {
4789         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4790
4791         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4792 }
4793
4794 static void 
4795 on_send_receive_finished (ModestMailOperation  *mail_op, 
4796                            gpointer user_data)
4797 {
4798         /* Set send/receive operation finished */       
4799         modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW (user_data));      
4800 }
4801
4802
4803 void 
4804 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4805                                                 TnyHeader *header, 
4806                                                 TnyMsg *msg, 
4807                                                 GError *err, 
4808                                                 gpointer user_data)
4809 {
4810         const gchar* server_name = NULL;
4811         TnyTransportAccount *server_account;
4812         gchar *message = NULL;
4813
4814         /* Don't show anything if the user cancelled something */
4815         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4816                 return;
4817
4818         /* Get the server name: */
4819         server_account = 
4820                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4821         if (server_account) {
4822                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4823                         
4824                 g_object_unref (server_account);
4825                 server_account = NULL;
4826         }
4827         
4828         g_return_if_fail (server_name);
4829
4830         /* Show the appropriate message text for the GError: */
4831         switch (err->code) {
4832         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4833                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4834                 break;
4835         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4836                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4837                 break;
4838         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4839                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4840                 break;
4841         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4842                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4843                 break;
4844         default:
4845                 g_return_if_reached ();
4846         }
4847         
4848         /* TODO if the username or the password where not defined we
4849            should show the Accounts Settings dialog or the Connection
4850            specific SMTP server window */
4851
4852         modest_platform_run_information_dialog (NULL, message);
4853         g_free (message);
4854 }
4855
4856 void
4857 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
4858                                                 gchar *msg_id, 
4859                                                 guint status,
4860                                                 gpointer user_data)
4861 {
4862         ModestMainWindow *main_window = NULL;
4863         ModestWindowMgr *mgr = NULL;
4864         GtkWidget *folder_view = NULL, *header_view = NULL;
4865         TnyFolderStore *selected_folder = NULL;
4866         TnyFolderType folder_type;
4867
4868         mgr = modest_runtime_get_window_mgr ();
4869         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
4870                                                                              FALSE));/* don't create */
4871         if (!main_window)
4872                 return;
4873
4874         /* Check if selected folder is OUTBOX */
4875         folder_view = modest_main_window_get_child_widget (main_window,
4876                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4877         header_view = modest_main_window_get_child_widget (main_window,
4878                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4879
4880         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4881         if (!TNY_IS_FOLDER (selected_folder)) 
4882                 goto frees;
4883
4884         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
4885 #if GTK_CHECK_VERSION(2, 8, 0) 
4886         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
4887         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
4888                 GtkTreeViewColumn *tree_column;
4889
4890                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
4891                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
4892                 gtk_tree_view_column_queue_resize (tree_column);
4893         }
4894 #else
4895         gtk_widget_queue_draw (header_view);
4896 #endif          
4897         
4898         /* Free */
4899  frees:
4900         if (selected_folder != NULL)
4901                 g_object_unref (selected_folder);
4902 }