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