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