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