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