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