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