8f88d16a5e10326245b9411cde73aec2650a55ba
[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-defs.h>
39 #include <modest-tny-folder.h>
40 #include <modest-tny-msg.h>
41 #include <modest-tny-account.h>
42 #include <modest-address-book.h>
43 #include "modest-error.h"
44 #include "modest-ui-actions.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-error.h>
50 #include <tny-camel-folder.h>
51 #include <tny-camel-imap-folder.h>
52 #include <tny-camel-pop-folder.h>
53 #ifdef MODEST_TOOLKIT_HILDON2
54 #include <modest-accounts-window.h>
55 #include <hildon/hildon-gtk.h>
56 #include <modest-header-window.h>
57 #include <modest-folder-window.h>
58 #include <modest-maemo-utils.h>
59 #endif
60 #include "modest-utils.h"
61 #include "widgets/modest-connection-specific-smtp-window.h"
62 #include "widgets/modest-ui-constants.h"
63 #include <widgets/modest-main-window.h>
64 #include <widgets/modest-msg-view-window.h>
65 #include <widgets/modest-account-view-window.h>
66 #include <widgets/modest-details-dialog.h>
67 #include <widgets/modest-attachments-view.h>
68 #include "widgets/modest-folder-view.h"
69 #include "widgets/modest-global-settings-dialog.h"
70 #include "modest-account-mgr-helpers.h"
71 #include "modest-mail-operation.h"
72 #include "modest-text-utils.h"
73 #include <modest-widget-memory.h>
74 #include <tny-error.h>
75 #include <tny-simple-list.h>
76 #include <tny-msg-view.h>
77 #include <tny-device.h>
78 #include <tny-merge-folder.h>
79
80 #include <gtkhtml/gtkhtml.h>
81
82 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
83
84 typedef struct _GetMsgAsyncHelper {
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         gchar *mailbox;
104         GtkWidget *parent_window;
105         TnyHeader *header;
106 } ReplyForwardHelper;
107
108 typedef struct _MoveToHelper {
109         GtkTreeRowReference *reference;
110         GtkWidget *banner;
111 } MoveToHelper;
112
113 typedef struct _PasteAsAttachmentHelper {
114         ModestMsgEditWindow *window;
115         GtkWidget *banner;
116 } PasteAsAttachmentHelper;
117
118 typedef struct {
119         TnyList *list;
120         ModestWindow *win;
121 } MoveToInfo;
122
123 /*
124  * The do_headers_action uses this kind of functions to perform some
125  * action to each member of a list of headers
126  */
127 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
128
129 static void     do_headers_action     (ModestWindow *win,
130                                        HeadersFunc func,
131                                        gpointer user_data);
132
133 static void     open_msg_cb            (ModestMailOperation *mail_op,
134                                         TnyHeader *header,
135                                         gboolean canceled,
136                                         TnyMsg *msg,
137                                         GError *err,
138                                         gpointer user_data);
139
140 static void     reply_forward_cb       (ModestMailOperation *mail_op,
141                                         TnyHeader *header,
142                                         gboolean canceled,
143                                         TnyMsg *msg,
144                                         GError *err,
145                                         gpointer user_data);
146
147 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
148
149 #ifndef MODEST_TOOLKIT_HILDON2
150 static void     folder_refreshed_cb    (ModestMailOperation *mail_op,
151                                         TnyFolder *folder,
152                                         gpointer user_data);
153
154 static void     on_send_receive_finished (ModestMailOperation  *mail_op,
155                                           gpointer user_data);
156 #endif
157
158 static gint header_list_count_uncached_msgs (TnyList *header_list);
159
160 static gboolean connect_to_get_msg (ModestWindow *win,
161                                     gint num_of_uncached_msgs,
162                                     TnyAccount *account);
163
164 static gboolean remote_folder_has_leave_on_server (TnyFolderStore *folder);
165
166 static void     do_create_folder (GtkWindow *window,
167                                   TnyFolderStore *parent_folder,
168                                   const gchar *suggested_name);
169
170 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
171
172 #ifndef MODEST_TOOLKIT_HILDON2
173 static void modest_ui_actions_on_main_window_move_to (GtkAction *action,
174                                                       GtkWidget *folder_view,
175                                                       TnyFolderStore *dst_folder,
176                                                       ModestMainWindow *win);
177
178 #else
179 static void modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
180                                                         TnyFolderStore *dst_folder,
181                                                         TnyList *selection,
182                                                         GtkWindow *win);
183 #endif
184
185 static void modest_ui_actions_on_window_move_to (GtkAction *action,
186                                                  TnyList *list_to_move,
187                                                  TnyFolderStore *dst_folder,
188                                                  ModestWindow *win);
189
190 /*
191  * This function checks whether a TnyFolderStore is a pop account
192  */
193 static gboolean
194 remote_folder_has_leave_on_server (TnyFolderStore *folder)
195 {
196         TnyAccount *account;
197         gboolean result;
198
199         g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
200
201         account = get_account_from_folder_store (folder);
202         result = (modest_protocol_registry_protocol_type_has_leave_on_server (modest_runtime_get_protocol_registry (),
203                                                                               modest_tny_account_get_protocol_type (account)));
204         g_object_unref (account);
205
206         return result;
207 }
208
209 /* FIXME: this should be merged with the similar code in modest-account-view-window */
210 /* Show the account creation wizard dialog.
211  * returns: TRUE if an account was created. FALSE if the user cancelled.
212  */
213 gboolean
214 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
215 {
216         gboolean result = FALSE;
217         GtkWindow *wizard;
218         gint dialog_response;
219
220         /* there is no such wizard yet */
221         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
222         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (wizard), (GtkWindow *) win);
223
224 #ifndef MODEST_TOOLKIT_HILDON2
225         /* always present a main window in the background
226          * we do it here, so we cannot end up with two wizards (as this
227          * function might be called in modest_window_mgr_get_main_window as well */
228         if (!win)
229                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
230                                                          TRUE);  /* create if not existent */
231 #else
232         if (!win) {
233                 GList *window_list;
234                 ModestWindowMgr *mgr;
235
236                 mgr = modest_runtime_get_window_mgr ();
237
238                 window_list = modest_window_mgr_get_window_list (mgr);
239                 if (window_list == NULL) {
240                         win = MODEST_WINDOW (modest_accounts_window_new ());
241                         if (modest_window_mgr_register_window (mgr, win, NULL)) {
242                                 gtk_widget_show_all (GTK_WIDGET (win));
243                         } else {
244                                 gtk_widget_destroy (GTK_WIDGET (win));
245                                 win = NULL;
246                         }
247
248                 } else {
249                         g_list_free (window_list);
250                 }
251         }
252 #endif
253
254         if (win)
255                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
256
257         /* make sure the mainwindow is visible. We need to present the
258            wizard again to give it the focus back. show_all are needed
259            in order to get the widgets properly drawn (MainWindow main
260            paned won't be in its right position and the dialog will be
261            missplaced */
262 #ifndef MODEST_TOOLKIT_HILDON2
263         gtk_widget_show_all (GTK_WIDGET (win));
264         gtk_widget_show_all (GTK_WIDGET (wizard));
265         gtk_window_present (GTK_WINDOW (win));
266         gtk_window_present (GTK_WINDOW (wizard));
267 #endif
268
269         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
270         gtk_widget_destroy (GTK_WIDGET (wizard));
271         if (gtk_events_pending ())
272                 gtk_main_iteration ();
273
274         if (dialog_response == GTK_RESPONSE_CANCEL) {
275                 result = FALSE;
276         } else {
277                 /* Check whether an account was created: */
278                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
279         }
280         return result;
281 }
282
283
284 void
285 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
286 {
287         GtkWidget *about;
288         const gchar *authors[] = {
289                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
290                 NULL
291         };
292         about = gtk_about_dialog_new ();
293         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
294         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
295         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
296                                         _("Copyright (c) 2006, Nokia Corporation\n"
297                                           "All rights reserved."));
298         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
299                                        _("a modest e-mail client\n\n"
300                                          "design and implementation: Dirk-Jan C. Binnema\n"
301                                          "contributions from the fine people at KC and Ig\n"
302                                          "uses the tinymail email framework written by Philip van Hoof"));
303         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
304         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
305         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
306         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
307
308         gtk_dialog_run (GTK_DIALOG (about));
309         gtk_widget_destroy(about);
310 }
311
312 /*
313  * Gets the list of currently selected messages. If the win is the
314  * main window, then it returns a newly allocated list of the headers
315  * selected in the header view. If win is the msg view window, then
316  * the value returned is a list with just a single header.
317  *
318  * The caller of this funcion must free the list.
319  */
320 static TnyList *
321 get_selected_headers (ModestWindow *win)
322 {
323         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
324                 /* for MsgViewWindows, we simply return a list with one element */
325                 TnyHeader *header;
326                 TnyList *list = NULL;
327
328                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
329                 if (header != NULL) {
330                         list = tny_simple_list_new ();
331                         tny_list_prepend (list, G_OBJECT(header));
332                         g_object_unref (G_OBJECT(header));
333                 }
334
335                 return list;
336 #ifndef MODEST_TOOLKIT_HILDON2
337         } else if (MODEST_IS_MAIN_WINDOW(win)) {
338                 GtkWidget *header_view;
339
340                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
341                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
342                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
343 #else
344         } else if (MODEST_IS_HEADER_WINDOW (win)) {
345                 GtkWidget *header_view;
346
347                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
348                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
349 #endif
350         } else {
351                 return NULL;
352         }
353 }
354
355 #ifndef MODEST_TOOLKIT_HILDON2
356 static GtkTreeRowReference *
357 get_next_after_selected_headers (ModestHeaderView *header_view)
358 {
359         GtkTreeSelection *sel;
360         GList *selected_rows, *node;
361         GtkTreePath *path;
362         GtkTreeRowReference *result;
363         GtkTreeModel *model;
364
365         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
366         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
367         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
368
369         if (selected_rows == NULL)
370                 return NULL;
371
372         node = g_list_last (selected_rows);
373         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
374         gtk_tree_path_next (path);
375
376         result = gtk_tree_row_reference_new (model, path);
377
378         gtk_tree_path_free (path);
379         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
380         g_list_free (selected_rows);
381
382         return result;
383 }
384 #endif
385
386 static void
387 headers_action_mark_as_read (TnyHeader *header,
388                              ModestWindow *win,
389                              gpointer user_data)
390 {
391         TnyHeaderFlags flags;
392
393         g_return_if_fail (TNY_IS_HEADER(header));
394
395         flags = tny_header_get_flags (header);
396         if (flags & TNY_HEADER_FLAG_SEEN) return;
397         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
398 }
399
400 static void
401 headers_action_mark_as_unread (TnyHeader *header,
402                                ModestWindow *win,
403                                gpointer user_data)
404 {
405         TnyHeaderFlags flags;
406
407         g_return_if_fail (TNY_IS_HEADER(header));
408
409         flags = tny_header_get_flags (header);
410         if (flags & TNY_HEADER_FLAG_SEEN)  {
411                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
412         }
413 }
414
415 /** After deleing a message that is currently visible in a window,
416  * show the next message from the list, or close the window if there are no more messages.
417  **/
418 void
419 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
420 {
421         /* Close msg view window or select next */
422         if (!modest_msg_view_window_select_next_message (win) &&
423             !modest_msg_view_window_select_previous_message (win)) {
424                 gboolean ret_value;
425                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
426         }
427 }
428
429
430 void
431 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
432 {
433         modest_ui_actions_on_edit_mode_delete_message (win);
434 }
435
436 gboolean
437 modest_ui_actions_on_edit_mode_delete_message (ModestWindow *win)
438 {
439         TnyList *header_list = NULL;
440         TnyIterator *iter = NULL;
441         TnyHeader *header = NULL;
442         gchar *message = NULL;
443         gchar *desc = NULL;
444         gint response;
445         ModestWindowMgr *mgr;
446         gboolean retval = TRUE;
447
448         g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
449
450 #ifndef MODEST_TOOLKIT_HILDON2
451         /* Check first if the header view has the focus */
452         if (MODEST_IS_MAIN_WINDOW (win)) {
453                 GtkWidget *header_view = NULL;
454
455                 header_view =
456                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
457                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
458                 if (!gtk_widget_is_focus (header_view))
459                         return FALSE;
460         }
461 #endif
462         /* Get the headers, either from the header view (if win is the main window),
463          * or from the message view window: */
464         header_list = get_selected_headers (win);
465         if (!header_list) return FALSE;
466
467         /* Check if any of the headers are already opened, or in the process of being opened */
468 #ifndef MODEST_TOOLKIT_HILDON2
469         if (MODEST_IS_MAIN_WINDOW (win)) {
470                 gint opened_headers = 0;
471
472                 iter = tny_list_create_iterator (header_list);
473                 mgr = modest_runtime_get_window_mgr ();
474                 while (!tny_iterator_is_done (iter)) {
475                         header = TNY_HEADER (tny_iterator_get_current (iter));
476                         if (header) {
477                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
478                                         opened_headers++;
479                                 g_object_unref (header);
480                         }
481                         tny_iterator_next (iter);
482                 }
483                 g_object_unref (iter);
484
485                 if (opened_headers > 0) {
486                         gchar *msg;
487
488                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
489                                                opened_headers);
490
491                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
492
493                         g_free (msg);
494                         g_object_unref (header_list);
495                         return FALSE;
496                 }
497         }
498 #endif
499
500         /* Select message */
501         if (tny_list_get_length(header_list) == 1) {
502                 iter = tny_list_create_iterator (header_list);
503                 header = TNY_HEADER (tny_iterator_get_current (iter));
504                 if (header) {
505                         gchar *subject;
506                         subject = tny_header_dup_subject (header);
507                         if (!subject)
508                                 subject = g_strdup (_("mail_va_no_subject"));
509                         desc = g_strdup_printf ("%s", subject);
510                         g_free (subject);
511                         g_object_unref (header);
512                 }
513
514                 g_object_unref (iter);
515         }
516         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
517                                            tny_list_get_length(header_list)), desc);
518
519         /* Confirmation dialog */
520         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
521                                                             message);
522
523         if (response == GTK_RESPONSE_OK) {
524                 GtkTreeSelection *sel = NULL;
525                 GList *sel_list = NULL;
526                 ModestMailOperation *mail_op = NULL;
527
528                 /* Find last selected row */
529 #ifndef MODEST_TOOLKIT_HILDON2
530                 if (MODEST_IS_MAIN_WINDOW (win)) {
531                         GList *tmp = NULL;
532                         ModestWindowMgr *mgr = NULL;
533                         GtkTreeModel *model = NULL;
534                         GtkTreeRowReference *next_row_reference = NULL, *prev_row_reference = NULL;
535                         GtkTreePath *next_path = NULL, *prev_path = NULL;
536
537                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
538                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
539                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
540                         for (tmp=sel_list; tmp; tmp=tmp->next) {
541                                 if (tmp->next == NULL) {
542                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
543                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
544
545                                         gtk_tree_path_prev (prev_path);
546                                         gtk_tree_path_next (next_path);
547
548                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
549                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
550                                 }
551                         }
552                 }
553 #endif
554
555                 /* Disable window dimming management */
556                 modest_window_disable_dimming (win);
557
558                 /* Remove each header. If it's a view window header_view == NULL */
559                 mail_op = modest_mail_operation_new ((GObject *) win);
560                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
561                                                  mail_op);
562                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
563                 g_object_unref (mail_op);
564
565                 /* Enable window dimming management */
566                 if (sel != NULL) {
567                         gtk_tree_selection_unselect_all (sel);
568                 }
569                 modest_window_enable_dimming (win);
570
571                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
572                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
573
574                         /* Get main window */
575                         mgr = modest_runtime_get_window_mgr ();
576 #ifndef MODEST_TOOLKIT_HILDON2
577                 } else if (MODEST_IS_MAIN_WINDOW (win)) {
578                         /* Select next or previous row */
579                         if (gtk_tree_row_reference_valid (next_row_reference)) {
580                                 gtk_tree_selection_select_path (sel, next_path);
581                         }
582                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {
583                                 gtk_tree_selection_select_path (sel, prev_path);
584                         }
585
586                         /* Free */
587                         if (gtk_tree_row_reference_valid (next_row_reference))
588                                 gtk_tree_row_reference_free (next_row_reference);
589                         if (next_path != NULL)
590                                 gtk_tree_path_free (next_path);
591                         if (gtk_tree_row_reference_valid (prev_row_reference))
592                                 gtk_tree_row_reference_free (prev_row_reference);
593                         if (prev_path != NULL)
594                                 gtk_tree_path_free (prev_path);
595 #endif
596                 }
597
598                 /* Update toolbar dimming state */
599                 modest_ui_actions_check_menu_dimming_rules (win);
600                 modest_ui_actions_check_toolbar_dimming_rules (win);
601
602                 /* Free */
603                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
604                 g_list_free (sel_list);
605                 retval = TRUE;
606         } else {
607                 retval = FALSE;
608         }
609
610         /* Free*/
611         g_free(message);
612         g_free(desc);
613         g_object_unref (header_list);
614
615         return retval;
616 }
617
618
619
620
621 /* delete either message or folder, based on where we are */
622 void
623 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
624 {
625         g_return_if_fail (MODEST_IS_WINDOW(win));
626
627         /* Check first if the header view has the focus */
628 #ifndef MODEST_TOOLKIT_HILDON2
629         if (MODEST_IS_MAIN_WINDOW (win)) {
630                 GtkWidget *w;
631                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
632                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
633                 if (gtk_widget_is_focus (w)) {
634                         modest_ui_actions_on_delete_folder (action, MODEST_WINDOW(win));
635                         return;
636                 }
637         }
638 #endif
639         modest_ui_actions_on_delete_message (action, win);
640 }
641
642 void
643 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
644 {
645         ModestWindowMgr *mgr = NULL;
646
647 #ifdef MODEST_PLATFORM_MAEMO
648         modest_window_mgr_save_state_for_all_windows (modest_runtime_get_window_mgr ());
649 #endif /* MODEST_PLATFORM_MAEMO */
650
651         g_debug ("closing down, clearing %d item(s) from operation queue",
652                  modest_mail_operation_queue_num_elements
653                  (modest_runtime_get_mail_operation_queue()));
654
655         /* cancel all outstanding operations */
656         modest_mail_operation_queue_cancel_all
657                 (modest_runtime_get_mail_operation_queue());
658
659         g_debug ("queue has been cleared");
660
661
662         /* Check if there are opened editing windows */
663         mgr = modest_runtime_get_window_mgr ();
664         modest_window_mgr_close_all_windows (mgr);
665
666         /* note: when modest-tny-account-store is finalized,
667            it will automatically set all network connections
668            to offline */
669
670 /*      gtk_main_quit (); */
671 }
672
673 void
674 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
675 {
676         gboolean ret_value;
677
678         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
679
680 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
681 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
682 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
683 /*              gboolean ret_value; */
684 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
685 /*      } else if (MODEST_IS_WINDOW (win)) { */
686 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
687 /*      } else { */
688 /*              g_return_if_reached (); */
689 /*      } */
690 }
691
692 void
693 modest_ui_actions_add_to_contacts (GtkAction *action, ModestWindow *win)
694 {
695        g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
696
697        modest_msg_view_window_add_to_contacts (MODEST_MSG_VIEW_WINDOW (win));
698 }
699
700 void
701 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
702 {
703         GtkClipboard *clipboard = NULL;
704         gchar *selection = NULL;
705
706         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
707         selection = gtk_clipboard_wait_for_text (clipboard);
708
709         if (selection) {
710                 modest_address_book_add_address (selection, (GtkWindow *) win);
711                 g_free (selection);
712         }
713 }
714
715 void
716 modest_ui_actions_on_new_account (GtkAction *action,
717                                   ModestWindow *window)
718 {
719         if (!modest_ui_actions_run_account_setup_wizard (window)) {
720                 g_debug ("%s: wizard was already running", __FUNCTION__);
721         }
722 }
723
724 void
725 modest_ui_actions_on_accounts (GtkAction *action,
726                                ModestWindow *win)
727 {
728         /* This is currently only implemented for Maemo */
729         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
730                 if (!modest_ui_actions_run_account_setup_wizard (win))
731                         g_debug ("%s: wizard was already running", __FUNCTION__);
732
733                 return;
734         } else {
735                 /* Show the list of accounts */
736                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
737
738                 /* The accounts dialog must be modal */
739                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (account_win), (GtkWindow *) win);
740                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
741         }
742 }
743
744 void
745 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
746 {
747         /* This is currently only implemented for Maemo,
748          * because it requires an API (libconic) to detect different connection
749          * possiblities.
750          */
751 #ifndef MODEST_TOOLKIT_GTK /* Defined in config.h */
752
753         /* Create the window if necessary: */
754         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
755         modest_connection_specific_smtp_window_fill_with_connections (
756                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
757                 modest_runtime_get_account_mgr());
758
759         /* Show the window: */
760         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
761                                      GTK_WINDOW (specific_window), (GtkWindow *) win);
762         gtk_widget_show (specific_window);
763 #endif /* !MODEST_TOOLKIT_GTK */
764 }
765
766 static guint64
767 count_part_size (const gchar *part)
768 {
769         GnomeVFSURI *vfs_uri;
770         gchar *escaped_filename;
771         gchar *filename;
772         GnomeVFSFileInfo *info;
773         guint64 result;
774
775         /* Estimation of attachment size if we cannot get it from file info */
776         result = 32768;
777
778         vfs_uri = gnome_vfs_uri_new (part);
779
780         escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
781         filename = gnome_vfs_unescape_string_for_display (escaped_filename);
782         g_free (escaped_filename);
783         gnome_vfs_uri_unref (vfs_uri);
784
785         info = gnome_vfs_file_info_new ();
786         
787         if (gnome_vfs_get_file_info (part, 
788                                      info, 
789                                      GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
790             == GNOME_VFS_OK) {
791                 if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
792                         result = info->size;
793                 }
794         }
795         g_free (filename);
796         gnome_vfs_file_info_unref (info);
797
798         return result;
799 }
800
801 static guint64 
802 count_parts_size (GSList *parts)
803 {
804         GSList *node;
805         guint64 result = 0;
806
807         for (node = parts; node != NULL; node = g_slist_next (node)) {
808                 result += count_part_size ((const gchar *) node->data);
809         }
810
811         return result;
812 }
813
814 void
815 modest_ui_actions_compose_msg(ModestWindow *win,
816                               const gchar *to_str,
817                               const gchar *cc_str,
818                               const gchar *bcc_str,
819                               const gchar *subject_str,
820                               const gchar *body_str,
821                               GSList *attachments,
822                               gboolean set_as_modified)
823 {
824         gchar *account_name = NULL;
825         const gchar *mailbox;
826         TnyMsg *msg = NULL;
827         TnyAccount *account = NULL;
828         TnyFolder *folder = NULL;
829         gchar *from_str = NULL, *signature = NULL, *body = NULL;
830         gchar *recipient = NULL;
831         gboolean use_signature = FALSE;
832         ModestWindow *msg_win = NULL;
833         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
834         ModestTnyAccountStore *store = modest_runtime_get_account_store();
835         GnomeVFSFileSize total_size, allowed_size;
836         guint64 available_disk, expected_size, parts_size;
837         guint parts_count;
838
839         /* we check for low-mem */
840         if (modest_platform_check_memory_low (win, TRUE))
841                 goto cleanup;
842
843         available_disk = modest_utils_get_available_space (NULL);
844         parts_count = g_slist_length (attachments);
845         parts_size = count_parts_size (attachments);
846         expected_size = modest_tny_msg_estimate_size (body, NULL, parts_count, parts_size);
847
848         /* Double check: disk full condition or message too big */
849         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
850             expected_size > available_disk) {
851                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
852                 modest_platform_system_banner (NULL, NULL, msg);
853                 g_free (msg);
854
855                 return;
856         }
857
858         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
859                 modest_platform_run_information_dialog (
860                         GTK_WINDOW(win),
861                         _("mail_ib_error_attachment_size"),
862                         TRUE);
863                 return;
864         }
865
866
867 #ifdef MODEST_TOOLKIT_HILDON2
868         if (win)
869                 account_name = g_strdup (modest_window_get_active_account(win));
870 #endif
871         if (!account_name) {
872                 account_name = modest_account_mgr_get_default_account(mgr);
873         }
874         if (!account_name) {
875                 g_printerr ("modest: no account found\n");
876                 goto cleanup;
877         }
878
879         if (win)
880                 mailbox = modest_window_get_active_mailbox (win);
881         else
882                 mailbox = NULL;
883         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
884         if (!account) {
885                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
886                 goto cleanup;
887         }
888         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
889         if (!folder) {
890                 g_printerr ("modest: failed to find Drafts folder\n");
891                 goto cleanup;
892         }
893         from_str = modest_account_mgr_get_from_string (mgr, account_name, mailbox);
894         if (!from_str) {
895                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
896                 goto cleanup;
897         }
898
899         recipient = modest_text_utils_get_email_address (from_str);
900         signature = modest_account_mgr_get_signature_from_recipient (mgr, recipient, &use_signature);
901         g_free (recipient);
902         if (body_str != NULL) {
903                 body = use_signature ? g_strconcat(body_str, "\n",
904                                                    MODEST_TEXT_UTILS_SIGNATURE_MARKER,
905                                                    "\n", signature, NULL) : g_strdup(body_str);
906         } else {
907                 body = use_signature ? g_strconcat("\n", MODEST_TEXT_UTILS_SIGNATURE_MARKER,
908                                                    "\n", signature, NULL) : g_strdup("");
909         }
910
911         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, NULL, NULL, body, NULL, NULL, NULL);
912         if (!msg) {
913                 g_printerr ("modest: failed to create new msg\n");
914                 goto cleanup;
915         }
916
917         /* Create and register edit window */
918         /* This is destroyed by TODO. */
919         total_size = 0;
920         allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
921         msg_win = modest_msg_edit_window_new (msg, account_name, mailbox, FALSE);
922
923         if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, win)) {
924                 gtk_widget_destroy (GTK_WIDGET (msg_win));
925                 goto cleanup;
926         }
927         modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
928         gtk_widget_show_all (GTK_WIDGET (msg_win));
929
930         while (attachments) {
931                 GnomeVFSFileSize att_size;
932                 att_size =
933                         modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
934                                                                attachments->data, allowed_size);
935                 total_size += att_size;
936
937                 if (att_size > allowed_size) {
938                         g_debug ("%s: total size: %u",
939                                  __FUNCTION__, (unsigned int)total_size);
940                         break;
941                 }
942                 allowed_size -= att_size;
943
944                 attachments = g_slist_next(attachments);
945         }
946
947 cleanup:
948         g_free (from_str);
949         g_free (signature);
950         g_free (body);
951         g_free (account_name);
952         if (account)
953                 g_object_unref (G_OBJECT(account));
954         if (folder)
955                 g_object_unref (G_OBJECT(folder));
956         if (msg)
957                 g_object_unref (G_OBJECT(msg));
958 }
959
960 void
961 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
962 {
963         /* if there are no accounts yet, just show the wizard */
964         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
965                 if (!modest_ui_actions_run_account_setup_wizard (win))
966                         return;
967
968         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
969 }
970
971
972 gboolean
973 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
974                                        TnyHeader *header,
975                                        TnyMsg *msg)
976 {
977         ModestMailOperationStatus status;
978
979         /* If there is no message or the operation was not successful */
980         status = modest_mail_operation_get_status (mail_op);
981         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
982                 const GError *error;
983
984                 /* If it's a memory low issue, then show a banner */
985                 error = modest_mail_operation_get_error (mail_op);
986                 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
987                     error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
988                         GObject *source = modest_mail_operation_get_source (mail_op);
989                         modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
990                                                                 _KR("memr_ib_operation_disabled"),
991                                                                 TRUE);
992                         g_object_unref (source);
993                 }
994
995                 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
996                               error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
997                         gchar *subject, *msg, *format = NULL;
998                         TnyAccount *account;
999
1000                         subject = (header) ? tny_header_dup_subject (header) : NULL;
1001                         if (!subject)
1002                                 subject = g_strdup (_("mail_va_no_subject"));
1003
1004                         account = modest_mail_operation_get_account (mail_op);
1005                         if (account) {
1006                                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
1007                                 ModestProtocol *protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), proto);
1008
1009                                 if (protocol) {
1010                                         if (tny_account_get_connection_status (account) ==
1011                                             TNY_CONNECTION_STATUS_CONNECTED) {
1012                                                 format = modest_protocol_get_translation (protocol,
1013                                                                                           MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE,
1014                                                                                           subject);
1015                                         } else {
1016                                                 format = g_strdup_printf (_("mail_ib_backend_server_invalid"),
1017                                                                           tny_account_get_hostname (account));
1018                                         }
1019                                 }
1020                                 g_object_unref (account);
1021                         }
1022
1023                         if (!format)
1024                                 format = g_strdup (_("emev_ni_ui_imap_message_not_available_in_server"));
1025
1026                         msg = g_strdup_printf (format, subject);
1027                         modest_platform_run_information_dialog (NULL, msg, FALSE);
1028                         g_free (msg);
1029                         g_free (format);
1030                         g_free (subject);
1031                 }
1032
1033                 /* Remove the header from the preregistered uids */
1034                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1035                                                      header);
1036
1037                 return FALSE;
1038         }
1039
1040         return TRUE;
1041 }
1042
1043 typedef struct {
1044         guint idle_handler;
1045         gchar *message;
1046         GtkWidget *banner;
1047 } OpenMsgBannerInfo;
1048
1049 typedef struct {
1050         GtkTreeModel *model;
1051         TnyHeader *header;
1052         ModestWindow *caller_window;
1053         OpenMsgBannerInfo *banner_info;
1054         GtkTreeRowReference *rowref;
1055 } OpenMsgHelper;
1056
1057 gboolean
1058 open_msg_banner_idle (gpointer userdata)
1059 {
1060         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
1061
1062         gdk_threads_enter ();
1063         banner_info->idle_handler = 0;
1064         banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
1065         if (banner_info->banner)
1066                 g_object_ref (banner_info->banner);
1067
1068         gdk_threads_leave ();
1069
1070         return FALSE;
1071 }
1072
1073 static GtkWidget *
1074 get_header_view_from_window (ModestWindow *window)
1075 {
1076         GtkWidget *header_view;
1077
1078 #ifndef MODEST_TOOLKIT_HILDON2
1079         if (MODEST_IS_MAIN_WINDOW (window)) {
1080                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
1081                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1082 #else
1083         if (MODEST_IS_HEADER_WINDOW (window)){
1084                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
1085 #endif
1086         } else {
1087                 header_view = NULL;
1088         }
1089
1090         return header_view;
1091 }
1092
1093 static gchar *
1094 get_info_from_header (TnyHeader *header, gboolean *is_draft, gboolean *can_open)
1095 {
1096         TnyFolder *folder;
1097         gchar *account = NULL;
1098         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1099
1100         *is_draft = FALSE;
1101         *can_open = TRUE;
1102
1103         folder = tny_header_get_folder (header);
1104         /* Gets folder type (OUTBOX headers will be opened in edit window */
1105         if (modest_tny_folder_is_local_folder (folder)) {
1106                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1107                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1108                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1109         }
1110
1111         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1112                 TnyTransportAccount *traccount = NULL;
1113                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
1114                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
1115                 if (traccount) {
1116                         ModestTnySendQueue *send_queue = NULL;
1117                         ModestTnySendQueueStatus status;
1118                         gchar *msg_id;
1119                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
1120                                                    TNY_ACCOUNT(traccount)));
1121                         send_queue = modest_runtime_get_send_queue(traccount, TRUE);
1122                         if (TNY_IS_SEND_QUEUE (send_queue)) {
1123                                 msg_id = modest_tny_send_queue_get_msg_id (header);
1124                                 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
1125                                 g_free (msg_id);
1126                                 /* Only open messages in outbox with the editor if they are in Failed state */
1127                                 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
1128                                         *is_draft = TRUE;
1129                                 }
1130 #ifdef MODEST_TOOLKIT_HILDON2
1131                                 else {
1132                                         /* In Fremantle we can not
1133                                            open any message from
1134                                            outbox which is not in
1135                                            failed state */
1136                                         *can_open = FALSE;
1137                                 }
1138 #endif
1139                         }
1140                         g_object_unref(traccount);
1141                 } else {
1142                         g_warning("Cannot get transport account for message in outbox!!");
1143                 }
1144         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
1145                 *is_draft = TRUE; /* Open in editor if the message is in the Drafts folder */
1146         }
1147
1148         if (!account) {
1149                 TnyAccount *acc = tny_folder_get_account (folder);
1150                 if (acc) {
1151                         account =
1152                                 g_strdup (modest_tny_account_get_parent_modest_account_name_for_server_account (acc));
1153                         g_object_unref (acc);
1154                 }
1155         }
1156
1157         g_object_unref (folder);
1158
1159         return account;
1160 }
1161
1162 static void
1163 open_msg_cb (ModestMailOperation *mail_op,
1164              TnyHeader *header,
1165              gboolean canceled,
1166              TnyMsg *msg,
1167              GError *err,
1168              gpointer user_data)
1169 {
1170         ModestWindowMgr *mgr = NULL;
1171         ModestWindow *parent_win = NULL;
1172         ModestWindow *win = NULL;
1173         gchar *account = NULL;
1174         gboolean open_in_editor = FALSE;
1175         gboolean can_open;
1176         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1177
1178         /* Do nothing if there was any problem with the mail
1179            operation. The error will be shown by the error_handler of
1180            the mail operation */
1181         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1182                 return;
1183
1184         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
1185
1186         /* Mark header as read */
1187         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
1188
1189         account = get_info_from_header (header, &open_in_editor, &can_open);
1190
1191         /* Get account */
1192         if (!account)
1193                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
1194         if (!account)
1195                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1196
1197         if (open_in_editor) {
1198                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
1199                 gchar *from_header = NULL, *acc_name;
1200                 gchar *mailbox = NULL;
1201
1202                 from_header = tny_header_dup_from (header);
1203
1204                 /* we cannot edit without a valid account... */
1205                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
1206                         if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
1207                                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1208                                                                      header);
1209                                 g_free (from_header);
1210                                 goto cleanup;
1211                         }
1212                 }
1213
1214                 acc_name = modest_utils_get_account_name_from_recipient (from_header, &mailbox);
1215                 g_free (from_header);
1216                 if (acc_name) {
1217                         g_free (account);
1218                         account = acc_name;
1219                 }
1220
1221                 win = modest_msg_edit_window_new (msg, account, mailbox, TRUE);
1222                 if (mailbox)
1223                         g_free (mailbox);
1224         } else {
1225                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
1226                 const gchar *mailbox = NULL;
1227
1228                 if (parent_win && MODEST_IS_WINDOW (parent_win))
1229                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_win));
1230
1231                 if (helper->rowref && helper->model) {
1232                         win = modest_msg_view_window_new_with_header_model (msg, account, mailbox, (const gchar*) uid,
1233                                                                             helper->model, helper->rowref);
1234                 } else {
1235                         win = modest_msg_view_window_new_for_attachment (msg, account, mailbox, (const gchar*) uid);
1236                 }
1237                 g_free (uid);
1238         }
1239
1240         /* Register and show new window */
1241         if (win != NULL) {
1242                 mgr = modest_runtime_get_window_mgr ();
1243                 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1244                         gtk_widget_destroy (GTK_WIDGET (win));
1245                         goto cleanup;
1246                 }
1247                 gtk_widget_show_all (GTK_WIDGET(win));
1248         }
1249
1250 #ifndef MODEST_TOOLKIT_HILDON2
1251         /* Update toolbar dimming state */
1252         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1253                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1254         }
1255 #endif
1256
1257 cleanup:
1258         /* Free */
1259         g_free(account);
1260         g_object_unref (parent_win);
1261 }
1262
1263 void
1264 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1265                                                  gpointer user_data)
1266 {
1267         const GError *error;
1268         GObject *win = NULL;
1269         ModestMailOperationStatus status;
1270
1271         win = modest_mail_operation_get_source (mail_op);
1272         error = modest_mail_operation_get_error (mail_op);
1273         status = modest_mail_operation_get_status (mail_op);
1274
1275         /* If the mail op has been cancelled then it's not an error:
1276            don't show any message */
1277         if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1278                 TnyAccount *account = modest_mail_operation_get_account (mail_op);
1279                 if (modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
1280                                                                  (GError *) error, account)) {
1281                         gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
1282                         modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
1283                         g_free (msg);
1284                 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1285                         modest_platform_information_banner ((GtkWidget *) win,
1286                                                             NULL, _("emev_ui_imap_inbox_select_error"));
1287                 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1288                            error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1289                         modest_platform_information_banner ((GtkWidget *) win,
1290                                                             NULL, _CS ("sfil_ni_unable_to_open_file_not_found"));
1291                 } else if (user_data) {
1292                         modest_platform_information_banner ((GtkWidget *) win,
1293                                                             NULL, user_data);
1294                 }
1295                 if (account)
1296                         g_object_unref (account);
1297         }
1298
1299         if (win)
1300                 g_object_unref (win);
1301 }
1302
1303 /**
1304  * Returns the account a list of headers belongs to. It returns a
1305  * *new* reference so don't forget to unref it
1306  */
1307 static TnyAccount*
1308 get_account_from_header_list (TnyList *headers)
1309 {
1310         TnyAccount *account = NULL;
1311
1312         if (tny_list_get_length (headers) > 0) {
1313                 TnyIterator *iter = tny_list_create_iterator (headers);
1314                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1315                 TnyFolder *folder = tny_header_get_folder (header);
1316
1317                 if (!folder) {
1318                         g_object_unref (header);
1319
1320                         while (!tny_iterator_is_done (iter)) {
1321                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1322                                 folder = tny_header_get_folder (header);
1323                                 if (folder)
1324                                         break;
1325                                 g_object_unref (header);
1326                                 header = NULL;
1327                                 tny_iterator_next (iter);
1328                         }
1329                 }
1330
1331                 if (folder) {
1332                         account = tny_folder_get_account (folder);
1333                         g_object_unref (folder);
1334                 }
1335
1336                 if (header)
1337                         g_object_unref (header);
1338
1339                 g_object_unref (iter);
1340         }
1341         return account;
1342 }
1343
1344 static TnyAccount*
1345 get_account_from_header (TnyHeader *header)
1346 {
1347         TnyAccount *account = NULL;
1348         TnyFolder *folder;
1349
1350         folder = tny_header_get_folder (header);
1351
1352         if (folder) {
1353                 account = tny_folder_get_account (folder);
1354                 g_object_unref (folder);
1355         }
1356         return account;
1357 }
1358
1359 static void
1360 caller_win_destroyed (OpenMsgHelper *helper, GObject *object)
1361 {
1362         if (helper->caller_window)
1363                 helper->caller_window = NULL;
1364 }
1365
1366 static void
1367 open_msg_helper_destroyer (gpointer user_data)
1368 {
1369         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1370
1371         if (helper->caller_window) {
1372                 g_object_weak_unref ((GObject *) helper->caller_window, (GWeakNotify) caller_win_destroyed, helper);
1373                 helper->caller_window = NULL;
1374         }
1375
1376         if (helper->banner_info) {
1377                 g_free (helper->banner_info->message);
1378                 if (helper->banner_info->idle_handler > 0) {
1379                         g_source_remove (helper->banner_info->idle_handler);
1380                         helper->banner_info->idle_handler = 0;
1381                 }
1382                 if (helper->banner_info->banner != NULL) {
1383                         gtk_widget_destroy (helper->banner_info->banner);
1384                         g_object_unref (helper->banner_info->banner);
1385                         helper->banner_info->banner = NULL;
1386                 }
1387                 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1388                 helper->banner_info = NULL;
1389         }
1390         g_object_unref (helper->model);
1391         g_object_unref (helper->header);
1392         gtk_tree_row_reference_free (helper->rowref);
1393         g_slice_free (OpenMsgHelper, helper);
1394 }
1395
1396 static void
1397 open_msg_performer(gboolean canceled,
1398                     GError *err,
1399                     GtkWindow *parent_window,
1400                     TnyAccount *account,
1401                     gpointer user_data)
1402 {
1403         ModestMailOperation *mail_op = NULL;
1404         gchar *error_msg = NULL;
1405         ModestProtocolType proto;
1406         TnyConnectionStatus status;
1407         OpenMsgHelper *helper = NULL;
1408         ModestProtocol *protocol;
1409         ModestProtocolRegistry *protocol_registry;
1410         gchar *subject;
1411
1412         helper = (OpenMsgHelper *) user_data;
1413
1414         status = tny_account_get_connection_status (account);
1415         if (err || canceled || helper->caller_window == NULL) {
1416                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1417                 /* Free the helper */
1418                 open_msg_helper_destroyer (helper);
1419
1420                 /* In disk full conditions we could get this error here */
1421                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
1422                                                                 (GtkWidget *) parent_window, err,
1423                                                                 account, NULL);
1424
1425                 goto clean;
1426         }
1427
1428         /* Get the error message depending on the protocol */
1429         proto = modest_tny_account_get_protocol_type (account);
1430         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1431                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1432         }
1433
1434         protocol_registry = modest_runtime_get_protocol_registry ();
1435         subject = tny_header_dup_subject (helper->header);
1436
1437         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1438         error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1439         if (subject)
1440                 g_free (subject);
1441
1442         if (error_msg == NULL) {
1443                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1444         }
1445
1446 #ifndef MODEST_TOOLKIT_HILDON2
1447         gboolean show_open_draft = FALSE;
1448         if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1449                                                             proto,
1450                                                             MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) {
1451                 TnyFolder *folder;
1452                 TnyFolderType folder_type;
1453
1454                 folder = tny_header_get_folder (helper->header);
1455                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1456                 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1457                 g_object_unref (folder);
1458         }
1459 #endif
1460
1461 #ifdef MODEST_TOOLKIT_HILDON2
1462         gboolean is_draft;
1463         gboolean can_open;
1464         gchar *account_name = get_info_from_header (helper->header, &is_draft, &can_open);
1465
1466         if (!can_open) {
1467                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1468                 g_free (account_name);
1469                 open_msg_helper_destroyer (helper);
1470                 goto clean;
1471         }
1472
1473         if (!is_draft) {
1474                 ModestWindow *window;
1475                 GtkWidget *header_view;
1476                 gchar *uid;
1477
1478                 header_view = get_header_view_from_window (MODEST_WINDOW (parent_window));
1479                 uid = modest_tny_folder_get_header_unique_id (helper->header);
1480                 if (header_view) {
1481                         const gchar *mailbox = NULL;
1482                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_window));
1483                         window = modest_msg_view_window_new_from_header_view 
1484                                 (MODEST_HEADER_VIEW (header_view), account_name, mailbox, uid, helper->rowref);
1485                         if (window != NULL) {
1486                                 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
1487                                                                         window, NULL)) {
1488                                         gtk_widget_destroy (GTK_WIDGET (window));
1489                                 } else {
1490                                         gtk_widget_show_all (GTK_WIDGET(window));
1491                                 }
1492                         }
1493                 }
1494                 g_free (account_name);
1495                 g_free (uid);
1496                 open_msg_helper_destroyer (helper);
1497                 goto clean;
1498         }
1499         g_free (account_name);
1500 #endif
1501         /* Create the mail operation */
1502         mail_op =
1503                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1504                                                                modest_ui_actions_disk_operations_error_handler,
1505                                                                g_strdup (error_msg), g_free);
1506         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1507                                          mail_op);
1508
1509
1510 #ifndef MODEST_TOOLKIT_HILDON2
1511         if (show_open_draft) {
1512                 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1513                 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1514                 helper->banner_info->banner = NULL;
1515                 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1516                                                                    helper->banner_info);
1517         }
1518 #endif
1519
1520
1521         TnyList *headers;
1522         headers = TNY_LIST (tny_simple_list_new ());
1523         tny_list_prepend (headers, G_OBJECT (helper->header));
1524         modest_mail_operation_get_msgs_full (mail_op,
1525                                              headers,
1526                                              open_msg_cb,
1527                                              helper,
1528                                              open_msg_helper_destroyer);
1529         g_object_unref (headers);
1530
1531         /* Frees */
1532  clean:
1533         if (error_msg)
1534                 g_free (error_msg);
1535         if (mail_op)
1536                 g_object_unref (mail_op);
1537         g_object_unref (account);
1538 }
1539
1540 /*
1541  * This function is used by both modest_ui_actions_on_open and
1542  * modest_ui_actions_on_header_activated. This way we always do the
1543  * same when trying to open messages.
1544  */
1545 static void
1546 open_msg_from_header (TnyHeader *header, GtkTreeRowReference *rowref, ModestWindow *win)
1547 {
1548         ModestWindowMgr *mgr = NULL;
1549         TnyAccount *account;
1550         gboolean cached = FALSE;
1551         gboolean found;
1552         GtkWidget *header_view = NULL;
1553         OpenMsgHelper *helper;
1554         ModestWindow *window;
1555
1556         g_return_if_fail (header != NULL && rowref != NULL && gtk_tree_row_reference_valid (rowref));
1557
1558         mgr = modest_runtime_get_window_mgr ();
1559
1560         /* get model */
1561         header_view = get_header_view_from_window (MODEST_WINDOW (win));
1562         if (header_view == NULL)
1563                 return;
1564
1565         /* Get the account */
1566         account = get_account_from_header (header);
1567         if (!account)
1568                 return;
1569
1570         window = NULL;
1571         found = modest_window_mgr_find_registered_header (mgr, header, &window);
1572
1573         /* Do not open again the message and present the
1574            window to the user */
1575         if (found) {
1576                 if (window) {
1577 #ifndef MODEST_TOOLKIT_HILDON2
1578                         gtk_window_present (GTK_WINDOW (window));
1579 #endif
1580                 } else {
1581                         /* the header has been registered already, we don't do
1582                          * anything but wait for the window to come up*/
1583                         g_debug ("header %p already registered, waiting for window", header);
1584                 }
1585                 goto cleanup;
1586         }
1587
1588         /* Open each message */
1589         cached = tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED;
1590         if (!cached) {
1591                 /* Allways download if we are online. */
1592                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1593                         gint response;
1594
1595                         /* If ask for user permission to download the messages */
1596                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1597                                                                             _("mcen_nc_get_msg"));
1598
1599                         /* End if the user does not want to continue */
1600                         if (response == GTK_RESPONSE_CANCEL) {
1601                                 goto cleanup;
1602                         }
1603                 }
1604         }
1605
1606         /* We register the window for opening */
1607         modest_window_mgr_register_header (mgr, header, NULL);
1608
1609         /* Create the helper. We need to get a reference to the model
1610            here because it could change while the message is readed
1611            (the user could switch between folders) */
1612         helper = g_slice_new (OpenMsgHelper);
1613         helper->model = g_object_ref (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
1614         helper->caller_window = win;
1615         g_object_weak_ref ((GObject *) helper->caller_window, (GWeakNotify) caller_win_destroyed, helper);
1616         helper->header = g_object_ref (header);
1617         helper->rowref = gtk_tree_row_reference_copy (rowref);
1618         helper->banner_info = NULL;
1619
1620         /* Connect to the account and perform */
1621         if (!cached) {
1622                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1623                                                      open_msg_performer, helper);
1624         } else {
1625                 /* Call directly the performer, do not need to connect */
1626                 open_msg_performer (FALSE, NULL, (GtkWindow *) win,
1627                                     g_object_ref (account), helper);
1628         }
1629 cleanup:
1630         /* Clean */
1631         if (account)
1632                 g_object_unref (account);
1633 }
1634
1635 void
1636 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1637 {
1638         TnyList *headers;
1639         TnyHeader *header;
1640         gint headers_count;
1641         TnyIterator *iter;
1642
1643         /* we check for low-mem; in that case, show a warning, and don't allow
1644          * opening
1645          */
1646         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1647                 return;
1648
1649         /* Get headers */
1650         headers = get_selected_headers (win);
1651         if (!headers)
1652                 return;
1653
1654         headers_count = tny_list_get_length (headers);
1655         if (headers_count != 1) {
1656                 if (headers_count > 1) {
1657                         /* Don't allow activation if there are more than one message selected */
1658                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1659                 }
1660
1661                 g_object_unref (headers);
1662                 return;
1663         }
1664
1665         iter = tny_list_create_iterator (headers);
1666         header = TNY_HEADER (tny_iterator_get_current (iter));
1667         g_object_unref (iter);
1668
1669         /* Open them */
1670         if (header) {
1671                 open_msg_from_header (header, NULL, win);
1672                 g_object_unref (header);
1673         }
1674
1675         g_object_unref(headers);
1676 }
1677
1678 static void
1679 rf_helper_window_closed (gpointer data,
1680                          GObject *object)
1681 {
1682         ReplyForwardHelper *helper = (ReplyForwardHelper *) data;
1683
1684         helper->parent_window = NULL;
1685 }
1686
1687 static ReplyForwardHelper*
1688 create_reply_forward_helper (ReplyForwardAction action,
1689                              ModestWindow *win,
1690                              guint reply_forward_type,
1691                              TnyHeader *header)
1692 {
1693         ReplyForwardHelper *rf_helper = NULL;
1694         const gchar *active_acc = modest_window_get_active_account (win);
1695         const gchar *active_mailbox = modest_window_get_active_mailbox (win);
1696
1697         rf_helper = g_slice_new0 (ReplyForwardHelper);
1698         rf_helper->reply_forward_type = reply_forward_type;
1699         rf_helper->action = action;
1700         rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1701         rf_helper->header = (header) ? g_object_ref (header) : NULL;
1702         rf_helper->account_name = (active_acc) ?
1703                 g_strdup (active_acc) :
1704                 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1705         rf_helper->mailbox = g_strdup (active_mailbox);
1706
1707         /* Note that window could be destroyed just AFTER calling
1708            register_window so we must ensure that this pointer does
1709            not hold invalid references */
1710         if (rf_helper->parent_window)
1711                 g_object_weak_ref (G_OBJECT (rf_helper->parent_window),
1712                                    rf_helper_window_closed, rf_helper);
1713
1714         return rf_helper;
1715 }
1716
1717 static void
1718 free_reply_forward_helper (gpointer data)
1719 {
1720         ReplyForwardHelper *helper;
1721
1722         helper = (ReplyForwardHelper *) data;
1723         g_free (helper->account_name);
1724         g_free (helper->mailbox);
1725         if (helper->header)
1726                 g_object_unref (helper->header);
1727         if (helper->parent_window)
1728                 g_object_weak_unref (G_OBJECT (helper->parent_window),
1729                                      rf_helper_window_closed, helper);
1730         g_slice_free (ReplyForwardHelper, helper);
1731 }
1732
1733 static void
1734 reply_forward_cb (ModestMailOperation *mail_op,
1735                   TnyHeader *header,
1736                   gboolean canceled,
1737                   TnyMsg *msg,
1738                   GError *err,
1739                   gpointer user_data)
1740 {
1741         TnyMsg *new_msg = NULL;
1742         ReplyForwardHelper *rf_helper;
1743         ModestWindow *msg_win = NULL;
1744         ModestEditType edit_type;
1745         gchar *from = NULL;
1746         TnyAccount *account = NULL;
1747         ModestWindowMgr *mgr = NULL;
1748         gchar *signature = NULL;
1749         gboolean use_signature;
1750         gchar *recipient;
1751
1752         /* If there was any error. The mail operation could be NULL,
1753            this means that we already have the message downloaded and
1754            that we didn't do a mail operation to retrieve it */
1755         rf_helper = (ReplyForwardHelper *) user_data;
1756         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1757                 goto cleanup;
1758
1759         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1760                                                    rf_helper->account_name, rf_helper->mailbox);
1761         recipient = modest_text_utils_get_email_address (from);
1762         signature = modest_account_mgr_get_signature_from_recipient (modest_runtime_get_account_mgr(), 
1763                                                                      recipient, 
1764                                                                      &use_signature);
1765         g_free (recipient);
1766
1767         /* Create reply mail */
1768         switch (rf_helper->action) {
1769                 /* Use the msg_header to ensure that we have all the
1770                    information. The summary can lack some data */
1771                 TnyHeader *msg_header;
1772         case ACTION_REPLY:
1773                 msg_header = tny_msg_get_header (msg);
1774                 new_msg =
1775                         modest_tny_msg_create_reply_msg (msg, msg_header, from,
1776                                                          (use_signature) ? signature : NULL,
1777                                                          rf_helper->reply_forward_type,
1778                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1779                 g_object_unref (msg_header);
1780                 break;
1781         case ACTION_REPLY_TO_ALL:
1782                 msg_header = tny_msg_get_header (msg);
1783                 new_msg =
1784                         modest_tny_msg_create_reply_msg (msg, msg_header, from,
1785                                                          (use_signature) ? signature : NULL,
1786                                                          rf_helper->reply_forward_type,
1787                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1788                 edit_type = MODEST_EDIT_TYPE_REPLY;
1789                 g_object_unref (msg_header);
1790                 break;
1791         case ACTION_FORWARD:
1792                 new_msg =
1793                         modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1794                                                            rf_helper->reply_forward_type);
1795                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1796                 break;
1797         default:
1798                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1799                                                      header);
1800                 g_return_if_reached ();
1801                 return;
1802         }
1803
1804         g_free (from);
1805         g_free (signature);
1806
1807         if (!new_msg) {
1808                 g_warning ("%s: failed to create message\n", __FUNCTION__);
1809                 goto cleanup;
1810         }
1811
1812         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1813                                                                        rf_helper->account_name,
1814                                                                        TNY_ACCOUNT_TYPE_STORE);
1815         if (!account) {
1816                 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1817                 goto cleanup;
1818         }
1819
1820         /* Create and register the windows */
1821         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, rf_helper->mailbox, FALSE);
1822         mgr = modest_runtime_get_window_mgr ();
1823         modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1824
1825         /* Note that register_window could have deleted the account */
1826         if (MODEST_IS_WINDOW (rf_helper->parent_window)) {
1827                 gdouble parent_zoom;
1828
1829                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1830                 modest_window_set_zoom (msg_win, parent_zoom);
1831         }
1832
1833         /* Show edit window */
1834         gtk_widget_show_all (GTK_WIDGET (msg_win));
1835
1836 cleanup:
1837         /* We always unregister the header because the message is
1838            forwarded or replied so the original one is no longer
1839            opened */
1840         modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1841                                              header);
1842         if (new_msg)
1843                 g_object_unref (G_OBJECT (new_msg));
1844         if (account)
1845                 g_object_unref (G_OBJECT (account));
1846         free_reply_forward_helper (rf_helper);
1847 }
1848
1849 /* Checks a list of headers. If any of them are not currently
1850  * downloaded (CACHED) then returns TRUE else returns FALSE.
1851  */
1852 static gint
1853 header_list_count_uncached_msgs (TnyList *header_list)
1854 {
1855         TnyIterator *iter;
1856         gint uncached_messages = 0;
1857
1858         iter = tny_list_create_iterator (header_list);
1859         while (!tny_iterator_is_done (iter)) {
1860                 TnyHeader *header;
1861
1862                 header = TNY_HEADER (tny_iterator_get_current (iter));
1863                 if (header) {
1864                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1865                                 uncached_messages ++;
1866                         g_object_unref (header);
1867                 }
1868
1869                 tny_iterator_next (iter);
1870         }
1871         g_object_unref (iter);
1872
1873         return uncached_messages;
1874 }
1875
1876 /* Returns FALSE if the user does not want to download the
1877  * messages. Returns TRUE if the user allowed the download.
1878  */
1879 static gboolean
1880 connect_to_get_msg (ModestWindow *win,
1881                     gint num_of_uncached_msgs,
1882                     TnyAccount *account)
1883 {
1884         GtkResponseType response;
1885
1886         /* Allways download if we are online. */
1887         if (tny_device_is_online (modest_runtime_get_device ()))
1888                 return TRUE;
1889
1890         /* If offline, then ask for user permission to download the messages */
1891         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1892                         ngettext("mcen_nc_get_msg",
1893                         "mcen_nc_get_msgs",
1894                         num_of_uncached_msgs));
1895
1896         if (response == GTK_RESPONSE_CANCEL)
1897                 return FALSE;
1898
1899         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1900 }
1901
1902 static void
1903 reply_forward_performer (gboolean canceled,
1904                          GError *err,
1905                          GtkWindow *parent_window,
1906                          TnyAccount *account,
1907                          gpointer user_data)
1908 {
1909         ReplyForwardHelper *rf_helper = NULL;
1910         ModestMailOperation *mail_op;
1911
1912         rf_helper = (ReplyForwardHelper *) user_data;
1913
1914         if (canceled || err) {
1915                 free_reply_forward_helper (rf_helper);
1916                 return;
1917         }
1918
1919         /* Retrieve the message */
1920         modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1921         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1922                                                                  modest_ui_actions_disk_operations_error_handler,
1923                                                                  NULL, NULL);
1924         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1925         modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1926
1927         /* Frees */
1928         g_object_unref(mail_op);
1929 }
1930
1931 /*
1932  * Common code for the reply and forward actions
1933  */
1934 static void
1935 reply_forward (ReplyForwardAction action, ModestWindow *win)
1936 {
1937         ReplyForwardHelper *rf_helper = NULL;
1938         guint reply_forward_type;
1939
1940         g_return_if_fail (win && MODEST_IS_WINDOW(win));
1941
1942         /* we check for low-mem; in that case, show a warning, and don't allow
1943          * reply/forward (because it could potentially require a lot of memory */
1944         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1945                 return;
1946
1947
1948         /* we need an account when editing */
1949         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1950                 if (!modest_ui_actions_run_account_setup_wizard (win))
1951                         return;
1952         }
1953
1954         reply_forward_type =
1955                 modest_conf_get_int (modest_runtime_get_conf (),
1956                                      (action == ACTION_FORWARD) ?
1957                                      MODEST_CONF_FORWARD_TYPE :
1958                                      MODEST_CONF_REPLY_TYPE,
1959                                      NULL);
1960
1961         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1962                 TnyMsg *msg = NULL;
1963                 TnyHeader *header = NULL;
1964                 /* Get header and message. Do not free them here, the
1965                    reply_forward_cb must do it */
1966                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1967                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1968
1969                 if (msg && header) {
1970                         /* Create helper */
1971                         rf_helper = create_reply_forward_helper (action, win,
1972                                                                  reply_forward_type, header);
1973                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1974                 } else {
1975                         g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1976                 }
1977
1978                 if (msg)
1979                         g_object_unref (msg);
1980                 if (header)
1981                         g_object_unref (header);
1982         } else {
1983                 TnyHeader *header = NULL;
1984                 TnyIterator *iter;
1985                 gboolean do_retrieve = TRUE;
1986                 TnyList *header_list = NULL;
1987
1988                 header_list = get_selected_headers (win);
1989                 if (!header_list)
1990                         return;
1991                 /* Check that only one message is selected for replying */
1992                 if (tny_list_get_length (header_list) != 1) {
1993                         modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1994                                                             NULL, _("mcen_ib_select_one_message"));
1995                         g_object_unref (header_list);
1996                         return;
1997                 }
1998
1999                 /* Only reply/forward to one message */
2000                 iter = tny_list_create_iterator (header_list);
2001                 header = TNY_HEADER (tny_iterator_get_current (iter));
2002                 g_object_unref (iter);
2003
2004                 /* Retrieve messages */
2005                 do_retrieve = (action == ACTION_FORWARD) ||
2006                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
2007
2008                 if (do_retrieve) {
2009                         TnyAccount *account = NULL;
2010                         TnyFolder *folder = NULL;
2011                         gdouble download = TRUE;
2012                         guint uncached_msgs = 0;
2013
2014                         folder = tny_header_get_folder (header);
2015                         if (!folder)
2016                                 goto do_retrieve_frees;
2017                         account = tny_folder_get_account (folder);
2018                         if (!account)
2019                                 goto do_retrieve_frees;
2020
2021                         uncached_msgs = header_list_count_uncached_msgs (header_list);
2022
2023                         if (uncached_msgs > 0) {
2024                                 /* Allways download if we are online. */
2025                                 if (!tny_device_is_online (modest_runtime_get_device ())) {
2026                                         gint response;
2027
2028                                         /* If ask for user permission to download the messages */
2029                                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2030                                                                                             ngettext("mcen_nc_get_msg",
2031                                                                                                      "mcen_nc_get_msgs",
2032                                                                                                      uncached_msgs));
2033
2034                                         /* End if the user does not want to continue */
2035                                         if (response == GTK_RESPONSE_CANCEL)
2036                                                 download = FALSE;
2037                                 }
2038                         }
2039
2040                         if (download) {
2041                                 /* Create helper */
2042                                 rf_helper = create_reply_forward_helper (action, win,
2043                                                                          reply_forward_type, header);
2044                                 if (uncached_msgs > 0) {
2045                                         modest_platform_connect_and_perform (GTK_WINDOW (win),
2046                                                                              TRUE, account,
2047                                                                              reply_forward_performer,
2048                                                                              rf_helper);
2049                                 } else {
2050                                         reply_forward_performer (FALSE, NULL, GTK_WINDOW (win),
2051                                                                  account, rf_helper);
2052                                 }
2053                         }
2054                 do_retrieve_frees:
2055                         if (account)
2056                                 g_object_unref (account);
2057                         if (folder)
2058                                 g_object_unref (folder);
2059                 } else {
2060                         reply_forward_cb (NULL, header, FALSE, NULL, NULL, NULL);
2061                 }
2062                 /* Frees */
2063                 g_object_unref (header_list);
2064                 g_object_unref (header);
2065         }
2066 }
2067
2068 void
2069 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
2070 {
2071         g_return_if_fail (MODEST_IS_WINDOW(win));
2072
2073         reply_forward (ACTION_REPLY, win);
2074 }
2075
2076 void
2077 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
2078 {
2079         g_return_if_fail (MODEST_IS_WINDOW(win));
2080
2081         reply_forward (ACTION_FORWARD, win);
2082 }
2083
2084 void
2085 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
2086 {
2087         g_return_if_fail (MODEST_IS_WINDOW(win));
2088
2089         reply_forward (ACTION_REPLY_TO_ALL, win);
2090 }
2091
2092 void
2093 modest_ui_actions_on_next (GtkAction *action,
2094                            ModestWindow *window)
2095 {
2096 #ifndef MODEST_TOOLKIT_HILDON2
2097         if (MODEST_IS_MAIN_WINDOW (window)) {
2098                 GtkWidget *header_view;
2099
2100                 header_view = modest_main_window_get_child_widget (
2101                                 MODEST_MAIN_WINDOW(window),
2102                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2103                 if (!header_view)
2104                         return;
2105
2106                 modest_header_view_select_next (
2107                                 MODEST_HEADER_VIEW(header_view));
2108 #else
2109         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2110                 modest_msg_view_window_select_next_message (
2111                                 MODEST_MSG_VIEW_WINDOW (window));
2112 #endif
2113         } else {
2114                 g_return_if_reached ();
2115         }
2116 }
2117
2118 void
2119 modest_ui_actions_on_prev (GtkAction *action,
2120                            ModestWindow *window)
2121 {
2122         g_return_if_fail (MODEST_IS_WINDOW(window));
2123
2124 #ifndef MODEST_TOOLKIT_HILDON2
2125         if (MODEST_IS_MAIN_WINDOW (window)) {
2126                 GtkWidget *header_view;
2127                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2128                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2129                 if (!header_view)
2130                         return;
2131
2132                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
2133 #else
2134         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2135                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
2136 #endif
2137         } else {
2138                 g_return_if_reached ();
2139         }
2140 }
2141
2142 void
2143 modest_ui_actions_on_sort (GtkAction *action,
2144                            ModestWindow *window)
2145 {
2146         GtkWidget *header_view = NULL;
2147
2148         g_return_if_fail (MODEST_IS_WINDOW(window));
2149
2150 #ifndef MODEST_TOOLKIT_HILDON2
2151         if (MODEST_IS_MAIN_WINDOW (window)) {
2152                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2153                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2154 #else
2155         if (MODEST_IS_HEADER_WINDOW (window)) {
2156                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
2157 #endif
2158         }
2159
2160         if (!header_view) {
2161                 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
2162
2163                 return;
2164         }
2165
2166         /* Show sorting dialog */
2167         modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
2168 }
2169
2170 static void
2171 sync_folder_cb (ModestMailOperation *mail_op,
2172                 TnyFolder *folder,
2173                 gpointer user_data)
2174 {
2175         ModestHeaderView *header_view = (ModestHeaderView *) user_data;
2176
2177         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
2178                 ModestWindow *parent = (ModestWindow *) modest_mail_operation_get_source (mail_op);
2179
2180                 /* We must clear first, because otherwise set_folder will ignore */
2181                 /*    the change as the folders are the same */
2182                 modest_header_view_clear (header_view);
2183                 modest_header_view_set_folder (header_view, folder, TRUE, parent, NULL, NULL);
2184
2185                 g_object_unref (parent);
2186         }
2187
2188         g_object_unref (header_view);
2189 }
2190
2191 static gboolean
2192 idle_refresh_folder (gpointer source)
2193 {
2194         ModestHeaderView *header_view = NULL;
2195
2196         /* If the window still exists */
2197         if (!GTK_IS_WIDGET (source) ||
2198             !GTK_WIDGET_VISIBLE (source))
2199                 return FALSE;
2200
2201         /* Refresh the current view */
2202 #ifdef MODEST_TOOLKIT_HILDON2
2203         if (MODEST_IS_HEADER_WINDOW (source))
2204                 header_view = modest_header_window_get_header_view ((ModestHeaderWindow *) source);
2205 #else
2206         if (MODEST_IS_MAIN_WINDOW (source))
2207                 header_view = MODEST_HEADER_VIEW (modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source),
2208                                                                                        MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
2209 #endif
2210         if (header_view) {
2211                 TnyFolder *folder = modest_header_view_get_folder (header_view);
2212                 if (folder) {
2213                         /* Sync the folder status */
2214                         ModestMailOperation *mail_op = modest_mail_operation_new (source);
2215                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2216                         modest_mail_operation_sync_folder (mail_op, folder, FALSE, sync_folder_cb, g_object_ref (header_view));
2217                         g_object_unref (folder);
2218                         g_object_unref (mail_op);
2219                 }
2220         }
2221
2222         return FALSE;
2223 }
2224
2225 static void
2226 update_account_cb (ModestMailOperation *self,
2227                    TnyList *new_headers,
2228                    gpointer user_data)
2229 {
2230         ModestWindow *top;
2231         gboolean show_visual_notifications;
2232
2233         top = modest_window_mgr_get_current_top (modest_runtime_get_window_mgr ());
2234         show_visual_notifications = (top) ? FALSE : TRUE;
2235
2236         /* Notify new messages have been downloaded. If the
2237            send&receive was invoked by the user then do not show any
2238            visual notification, only play a sound and activate the LED
2239            (for the Maemo version) */
2240         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2241
2242                 /* We only notify about really new messages (not seen) we get */
2243                 TnyList *actually_new_list;
2244                 TnyIterator *iterator;
2245                 actually_new_list = TNY_LIST (tny_simple_list_new ());
2246                 for (iterator = tny_list_create_iterator (new_headers);
2247                      !tny_iterator_is_done (iterator);
2248                      tny_iterator_next (iterator)) {
2249                         TnyHeader *header;
2250                         TnyHeaderFlags flags;
2251                         header = TNY_HEADER (tny_iterator_get_current (iterator));
2252                         flags = tny_header_get_flags (header);
2253
2254                         if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2255                                 /* Messages are ordered from most
2256                                    recent to oldest. But we want to
2257                                    show notifications starting from
2258                                    the oldest message. That's why we
2259                                    reverse the list */
2260                                 tny_list_prepend (actually_new_list, G_OBJECT (header));
2261                         }
2262                         g_object_unref (header);
2263                 }
2264                 g_object_unref (iterator);
2265
2266                 if (tny_list_get_length (actually_new_list) > 0) {
2267                         GList *new_headers_list = NULL;
2268
2269                         new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2270
2271                         /* Send notifications */
2272                         if (new_headers_list) {
2273                                 modest_platform_on_new_headers_received (new_headers_list,
2274                                                                          show_visual_notifications);
2275                                 /* Free the list */
2276                                 modest_utils_free_notification_list (new_headers_list);
2277                         }
2278                 }
2279                 g_object_unref (actually_new_list);
2280         }
2281
2282         if (top) {
2283                 /* Refresh the current folder in an idle. We do this
2284                    in order to avoid refresh cancelations if the
2285                    currently viewed folder is the inbox */
2286                 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
2287                                  idle_refresh_folder,
2288                                  g_object_ref (top),
2289                                  g_object_unref);
2290         }
2291 }
2292
2293 typedef struct {
2294         TnyAccount *account;
2295         ModestWindow *win;
2296         gchar *account_name;
2297         gboolean poke_status;
2298         gboolean interactive;
2299         ModestMailOperation *mail_op;
2300 } SendReceiveInfo;
2301
2302 static void
2303 do_send_receive_performer (gboolean canceled,
2304                            GError *err,
2305                            GtkWindow *parent_window,
2306                            TnyAccount *account,
2307                            gpointer user_data)
2308 {
2309         SendReceiveInfo *info;
2310
2311         info = (SendReceiveInfo *) user_data;
2312
2313         if (err || canceled) {
2314                 /* In disk full conditions we could get this error here */
2315                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2316                                                                 (GtkWidget *) parent_window, err,
2317                                                                 account, NULL);
2318
2319                 if (info->mail_op) {
2320                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2321                                                             info->mail_op);
2322                 }
2323                 goto clean;
2324         }
2325
2326 #ifndef MODEST_TOOLKIT_HILDON2
2327         /* Set send/receive operation in progress */
2328         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2329                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2330         }
2331
2332         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2333                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2334                                   G_CALLBACK (on_send_receive_finished),
2335                                   info->win);
2336 #endif
2337
2338         /* Send & receive. */
2339         modest_mail_operation_update_account (info->mail_op, info->account_name,
2340                                               info->poke_status, info->interactive,
2341                                               update_account_cb, info->win);
2342
2343  clean:
2344         /* Frees */
2345         if (info->mail_op)
2346                 g_object_unref (G_OBJECT (info->mail_op));
2347         if (info->account_name)
2348                 g_free (info->account_name);
2349         if (info->win)
2350                 g_object_unref (info->win);
2351         if (info->account)
2352                 g_object_unref (info->account);
2353         g_slice_free (SendReceiveInfo, info);
2354 }
2355
2356 /*
2357  * This function performs the send & receive required actions. The
2358  * window is used to create the mail operation. Typically it should
2359  * always be the main window, but we pass it as argument in order to
2360  * be more flexible.
2361  */
2362 void
2363 modest_ui_actions_do_send_receive (const gchar *account_name,
2364                                    gboolean force_connection,
2365                                    gboolean poke_status,
2366                                    gboolean interactive,
2367                                    ModestWindow *win)
2368 {
2369         gchar *acc_name = NULL;
2370         SendReceiveInfo *info;
2371         ModestTnyAccountStore *acc_store;
2372         TnyAccount *account;
2373
2374         /* If no account name was provided then get the current account, and if
2375            there is no current account then pick the default one: */
2376         if (!account_name) {
2377                 if (win)
2378                         acc_name = g_strdup (modest_window_get_active_account (win));
2379                 if (!acc_name)
2380                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2381                 if (!acc_name) {
2382                         modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2383                         return;
2384                 }
2385         } else {
2386                 acc_name = g_strdup (account_name);
2387         }
2388
2389         acc_store = modest_runtime_get_account_store ();
2390         account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2391
2392         if (!account) {
2393                 g_free (acc_name);
2394                 modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2395                 return;
2396         }
2397
2398         /* Do not automatically refresh accounts that are flagged as
2399            NO_AUTO_UPDATE. This could be useful for accounts that
2400            handle their own update times */
2401         if (!interactive) {
2402                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2403                 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2404                         const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2405                         ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2406
2407                         if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2408                                 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2409                                 g_object_unref (account);
2410                                 g_free (acc_name);
2411                                 return;
2412                         }
2413                 }
2414         }
2415
2416         /* Create the info for the connect and perform */
2417         info = g_slice_new (SendReceiveInfo);
2418         info->account_name = acc_name;
2419         info->win = (win) ? g_object_ref (win) : NULL;
2420         info->poke_status = poke_status;
2421         info->interactive = interactive;
2422         info->account = account;
2423         /* We need to create the operation here, because otherwise it
2424            could happen that the queue emits the queue-empty signal
2425            while we're trying to connect the account */
2426         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2427                                                                        modest_ui_actions_disk_operations_error_handler,
2428                                                                        NULL, NULL);
2429         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2430
2431         /* Invoke the connect and perform */
2432         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2433                                              force_connection, info->account,
2434                                              do_send_receive_performer, info);
2435 }
2436
2437
2438 static void
2439 modest_ui_actions_do_cancel_send (const gchar *account_name,
2440                                   ModestWindow *win)
2441 {
2442         TnyTransportAccount *transport_account;
2443         TnySendQueue *send_queue = NULL;
2444         GError *error = NULL;
2445
2446         /* Get transport account */
2447         transport_account =
2448                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2449                                       (modest_runtime_get_account_store(),
2450                                        account_name,
2451                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2452         if (!transport_account) {
2453                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2454                 goto frees;
2455         }
2456
2457         /* Get send queue*/
2458         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2459         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2460                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2461                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2462                              "modest: could not find send queue for account\n");
2463         } else {
2464                 /* Cancel the current send */
2465                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2466
2467                 /* Suspend all pending messages */
2468                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2469         }
2470
2471  frees:
2472         if (transport_account != NULL)
2473                 g_object_unref (G_OBJECT (transport_account));
2474 }
2475
2476 static void
2477 modest_ui_actions_cancel_send_all (ModestWindow *win)
2478 {
2479         GSList *account_names, *iter;
2480
2481         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2482                                                           TRUE);
2483
2484         iter = account_names;
2485         while (iter) {
2486                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2487                 iter = g_slist_next (iter);
2488         }
2489
2490         modest_account_mgr_free_account_names (account_names);
2491         account_names = NULL;
2492 }
2493
2494 void
2495 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2496
2497 {
2498         /* Check if accounts exist */
2499         gboolean accounts_exist =
2500                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2501
2502         /* If not, allow the user to create an account before trying to send/receive. */
2503         if (!accounts_exist)
2504                 modest_ui_actions_on_accounts (NULL, win);
2505
2506         /* Cancel all sending operaitons */
2507         modest_ui_actions_cancel_send_all (win);
2508 }
2509
2510 /*
2511  * Refreshes all accounts. This function will be used by automatic
2512  * updates
2513  */
2514 void
2515 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2516                                        gboolean force_connection,
2517                                        gboolean poke_status,
2518                                        gboolean interactive)
2519 {
2520         GSList *account_names, *iter;
2521
2522         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2523                                                           TRUE);
2524
2525         iter = account_names;
2526         while (iter) {
2527                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2528                                                    force_connection,
2529                                                    poke_status, interactive, win);
2530                 iter = g_slist_next (iter);
2531         }
2532
2533         modest_account_mgr_free_account_names (account_names);
2534         account_names = NULL;
2535 }
2536
2537 /*
2538  * Handler of the click on Send&Receive button in the main toolbar
2539  */
2540 void
2541 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2542 {
2543         /* Check if accounts exist */
2544         gboolean accounts_exist;
2545
2546         accounts_exist =
2547                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2548
2549         /* If not, allow the user to create an account before trying to send/receive. */
2550         if (!accounts_exist)
2551                 modest_ui_actions_on_accounts (NULL, win);
2552
2553         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2554 #ifndef MODEST_TOOLKIT_HILDON2
2555         if (MODEST_IS_MAIN_WINDOW (win)) {
2556                 GtkWidget *folder_view;
2557                 TnyFolderStore *folder_store;
2558
2559                 folder_view =
2560                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2561                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2562                 if (!folder_view)
2563                         return;
2564
2565                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2566
2567                 if (folder_store)
2568                         g_object_unref (folder_store);
2569                 /* Refresh the active account. Force the connection if needed
2570                    and poke the status of all folders */
2571                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2572 #else
2573         if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2574                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2575 #endif
2576         } else {
2577                 const gchar *active_account;
2578                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2579
2580                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2581         }
2582
2583 }
2584
2585 #ifndef MODEST_TOOLKIT_HILDON2
2586 void
2587 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2588 {
2589         ModestConf *conf;
2590         GtkWidget *header_view;
2591
2592         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2593
2594         header_view = modest_main_window_get_child_widget (main_window,
2595                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2596         if (!header_view)
2597                 return;
2598
2599         conf = modest_runtime_get_conf ();
2600
2601         /* what is saved/restored is depending on the style; thus; we save with
2602          * old style, then update the style, and restore for this new style
2603          */
2604         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2605
2606         if (modest_header_view_get_style
2607             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2608                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2609                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2610         else
2611                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2612                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2613
2614         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2615                                       MODEST_CONF_HEADER_VIEW_KEY);
2616 }
2617
2618 void
2619 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2620                                       TnyHeader *header,
2621                                       ModestMainWindow *main_window)
2622 {
2623         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2624         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2625
2626         /* in the case the folder is empty, show the empty folder message and focus
2627          * folder view */
2628         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2629                 if (modest_header_view_is_empty (header_view)) {
2630                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2631                         GtkWidget *folder_view =
2632                                 modest_main_window_get_child_widget (main_window,
2633                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2634                         if (folder != NULL) {
2635                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2636                                 g_object_unref (folder);
2637                         }
2638                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2639                         return;
2640                 }
2641         }
2642         /* If no header has been selected then exit */
2643         if (!header)
2644                 return;
2645
2646         /* Update focus */
2647         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2648             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2649
2650         /* Update toolbar dimming state */
2651         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2652         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2653 }
2654 #endif
2655
2656 void
2657 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2658                                        TnyHeader *header,
2659                                        GtkTreePath *path,
2660                                        ModestWindow *window)
2661 {
2662         GtkTreeRowReference *rowref;
2663
2664         g_return_if_fail (MODEST_IS_WINDOW(window));
2665         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2666         g_return_if_fail (TNY_IS_HEADER (header));
2667
2668         if (modest_header_view_count_selected_headers (header_view) > 1) {
2669                 /* Don't allow activation if there are more than one message selected */
2670                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2671                 return;
2672         }
2673
2674         /* we check for low-mem; in that case, show a warning, and don't allow
2675          * activating headers
2676          */
2677         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2678                 return;
2679
2680 #ifndef MODEST_TOOLKIT_HILDON2
2681         GtkWidget *open_widget;
2682         if (MODEST_IS_MAIN_WINDOW (window)) {
2683                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2684                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2685                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2686                         return;
2687         }
2688 #endif
2689
2690         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2691         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2692         gtk_tree_row_reference_free (rowref);
2693 }
2694
2695 #ifndef MODEST_TOOLKIT_HILDON2
2696 static void
2697 set_active_account_from_tny_account (TnyAccount *account,
2698                                      ModestWindow *window)
2699 {
2700         const gchar *server_acc_name = tny_account_get_id (account);
2701
2702         /* We need the TnyAccount provided by the
2703            account store because that is the one that
2704            knows the name of the Modest account */
2705         TnyAccount *modest_server_account =
2706                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2707                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2708                                                              server_acc_name);
2709         if (!modest_server_account) {
2710                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2711                 return;
2712         }
2713
2714         /* Update active account, but only if it's not a pseudo-account */
2715         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2716             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2717                 const gchar *modest_acc_name =
2718                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2719                 if (modest_acc_name)
2720                         modest_window_set_active_account (window, modest_acc_name);
2721         }
2722
2723         g_object_unref (modest_server_account);
2724 }
2725
2726 static void
2727 folder_refreshed_cb (ModestMailOperation *mail_op,
2728                      TnyFolder *folder,
2729                      gpointer user_data)
2730 {
2731         ModestMainWindow *win = NULL;
2732         GtkWidget *folder_view, *header_view;
2733         const GError *error;
2734
2735         g_return_if_fail (TNY_IS_FOLDER (folder));
2736
2737         win = MODEST_MAIN_WINDOW (user_data);
2738
2739         /* Check if the operation failed due to memory low conditions */
2740         error = modest_mail_operation_get_error (mail_op);
2741         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2742             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2743                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2744                                                         _KR("memr_ib_operation_disabled"),
2745                                                         TRUE);
2746                 return;
2747         }
2748
2749         folder_view =
2750                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2751         header_view =
2752                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2753
2754         if (folder_view) {
2755                 TnyFolderStore *current_folder;
2756
2757                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2758                 if (current_folder) {
2759                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2760                         g_object_unref (current_folder);
2761                         if (different)
2762                                 return;
2763                 }
2764         }
2765
2766         /* Check if folder is empty and set headers view contents style */
2767         if ((tny_folder_get_all_count (folder) == 0) ||
2768             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2769                 modest_main_window_set_contents_style (win,
2770                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2771 }
2772
2773 void
2774 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2775                                                TnyFolderStore *folder_store,
2776                                                gboolean selected,
2777                                                ModestMainWindow *main_window)
2778 {
2779         GtkWidget *header_view;
2780
2781         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2782
2783         header_view = modest_main_window_get_child_widget(main_window,
2784                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2785         if (!header_view)
2786                 return;
2787
2788
2789         if (TNY_IS_ACCOUNT (folder_store)) {
2790                 if (selected) {
2791                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2792
2793                         /* Show account details */
2794                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2795                 }
2796         } else {
2797                 if (TNY_IS_FOLDER (folder_store) && selected) {
2798                         TnyAccount *account;
2799
2800                         /* Update the active account */
2801                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2802                         if (account) {
2803                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2804                                 g_object_unref (account);
2805                                 account = NULL;
2806                         }
2807
2808                         /* Set the header style by default, it could
2809                            be changed later by the refresh callback to
2810                            empty */
2811                         modest_main_window_set_contents_style (main_window,
2812                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2813
2814                         /* Set folder on header view. This function
2815                            will call tny_folder_refresh_async so we
2816                            pass a callback that will be called when
2817                            finished. We use that callback to set the
2818                            empty view if there are no messages */
2819                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2820                                                        TNY_FOLDER (folder_store),
2821                                                        TRUE,
2822                                                        MODEST_WINDOW (main_window),
2823                                                        folder_refreshed_cb,
2824                                                        main_window);
2825
2826                         /* Restore configuration. We need to do this
2827                            *after* the set_folder because the widget
2828                            memory asks the header view about its
2829                            folder  */
2830                         modest_widget_memory_restore (modest_runtime_get_conf (),
2831                                                       G_OBJECT(header_view),
2832                                                       MODEST_CONF_HEADER_VIEW_KEY);
2833                 } else {
2834                         /* No need to save the header view
2835                            configuration for Maemo because it only
2836                            saves the sorting stuff and that it's
2837                            already being done by the sort
2838                            dialog. Remove it when the GNOME version
2839                            has the same behaviour */
2840 #ifdef MODEST_TOOLKIT_GTK
2841                         if (modest_main_window_get_contents_style (main_window) ==
2842                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2843                                 modest_widget_memory_save (modest_runtime_get_conf (), 
2844                                                            G_OBJECT (header_view),
2845                                                            MODEST_CONF_HEADER_VIEW_KEY);
2846 #endif
2847                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2848                 }
2849         }
2850
2851         /* Update dimming state */
2852         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2853         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2854 }
2855 #endif
2856
2857 void
2858 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2859                                      ModestWindow *win)
2860 {
2861         GtkWidget *dialog;
2862         gchar *txt, *item;
2863         gboolean online;
2864
2865         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2866
2867         online = tny_device_is_online (modest_runtime_get_device());
2868
2869         if (online) {
2870                 /* already online -- the item is simply not there... */
2871                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2872                                                  GTK_DIALOG_MODAL,
2873                                                  GTK_MESSAGE_WARNING,
2874                                                  GTK_BUTTONS_NONE,
2875                                                  _("The %s you selected cannot be found"),
2876                                                  item);
2877                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2878                 gtk_dialog_run (GTK_DIALOG(dialog));
2879         } else {
2880                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2881                                                       GTK_WINDOW (win),
2882                                                       GTK_DIALOG_MODAL,
2883                                                       _("mcen_bd_dialog_cancel"),
2884                                                       GTK_RESPONSE_REJECT,
2885                                                       _("mcen_bd_dialog_ok"),
2886                                                       GTK_RESPONSE_ACCEPT,
2887                                                       NULL);
2888                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2889                                          "Do you want to get online?"), item);
2890                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2891                                     gtk_label_new (txt), FALSE, FALSE, 0);
2892                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2893                 g_free (txt);
2894
2895                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2896                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2897                         /* TODO: Comment about why is this commented out: */
2898                         /* modest_platform_connect_and_wait (); */
2899                 }
2900         }
2901         gtk_widget_destroy (dialog);
2902 }
2903
2904 void
2905 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2906                                      ModestWindow *win)
2907 {
2908         /* g_debug ("%s %s", __FUNCTION__, link); */
2909 }
2910
2911
2912 void
2913 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2914                                         ModestWindow *win)
2915 {
2916         modest_platform_activate_uri (link);
2917 }
2918
2919 void
2920 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2921                                           ModestWindow *win)
2922 {
2923         modest_platform_show_uri_popup (link);
2924 }
2925
2926 void
2927 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2928                                              ModestWindow *win)
2929 {
2930         /* we check for low-mem; in that case, show a warning, and don't allow
2931          * viewing attachments
2932          */
2933         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2934                 return;
2935
2936         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2937 }
2938
2939 void
2940 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2941                                           const gchar *address,
2942                                           ModestWindow *win)
2943 {
2944         /* g_debug ("%s %s", __FUNCTION__, address); */
2945 }
2946
2947 static void
2948 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2949                       TnyMsg *saved_draft,
2950                       gpointer user_data)
2951 {
2952         ModestMsgEditWindow *edit_window;
2953
2954         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2955 #ifndef MODEST_TOOLKIT_HILDON2
2956         ModestMainWindow *win;
2957
2958         /* FIXME. Make the header view sensitive again. This is a
2959          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2960          * for details */
2961         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2962                                          modest_runtime_get_window_mgr(), FALSE));
2963         if (win != NULL) {
2964                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2965                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2966                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2967         }
2968 #endif
2969
2970         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2971
2972         /* Set draft is there was no error */
2973         if (!modest_mail_operation_get_error (mail_op))
2974                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2975
2976         g_object_unref(edit_window);
2977 }
2978
2979 static gboolean
2980 enough_space_for_message (ModestMsgEditWindow *edit_window,
2981                           MsgData *data)
2982 {
2983         guint64 available_disk, expected_size;
2984         gint parts_count;
2985         guint64 parts_size;
2986
2987         /* Check size */
2988         available_disk = modest_utils_get_available_space (NULL);
2989         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2990         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2991                                                       data->html_body,
2992                                                       parts_count,
2993                                                       parts_size);
2994
2995         /* Double check: disk full condition or message too big */
2996         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
2997             expected_size > available_disk) {
2998                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2999                 modest_platform_information_banner (NULL, NULL, msg);
3000                 g_free (msg);
3001
3002                 return FALSE;
3003         }
3004
3005         /*
3006          * djcb: if we're in low-memory state, we only allow for
3007          * saving messages smaller than
3008          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
3009          * should still allow for sending anything critical...
3010          */
3011         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
3012             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
3013                 return FALSE;
3014
3015         /*
3016          * djcb: we also make sure that the attachments are smaller than the max size
3017          * this is for the case where we'd try to forward a message with attachments
3018          * bigger than our max allowed size, or sending an message from drafts which
3019          * somehow got past our checks when attaching.
3020          */
3021         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
3022                 modest_platform_run_information_dialog (
3023                         GTK_WINDOW(edit_window),
3024                         _("mail_ib_error_attachment_size"),
3025                         TRUE);
3026                 return FALSE;
3027         }
3028
3029         return TRUE;
3030 }
3031
3032 gboolean
3033 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3034 {
3035         TnyTransportAccount *transport_account;
3036         ModestMailOperation *mail_operation;
3037         MsgData *data;
3038         gchar *account_name;
3039         ModestAccountMgr *account_mgr;
3040         gboolean had_error = FALSE;
3041
3042         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
3043
3044         data = modest_msg_edit_window_get_msg_data (edit_window);
3045
3046         /* Check size */
3047         if (!enough_space_for_message (edit_window, data)) {
3048                 modest_msg_edit_window_free_msg_data (edit_window, data);
3049                 return FALSE;
3050         }
3051
3052         account_name = g_strdup (data->account_name);
3053         account_mgr = modest_runtime_get_account_mgr();
3054         if (!account_name)
3055                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3056         if (!account_name)
3057                 account_name = modest_account_mgr_get_default_account (account_mgr);
3058         if (!account_name) {
3059                 g_printerr ("modest: no account found\n");
3060                 modest_msg_edit_window_free_msg_data (edit_window, data);
3061                 return FALSE;
3062         }
3063
3064         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
3065                 account_name = g_strdup (data->account_name);
3066         }
3067
3068         transport_account =
3069                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3070                                       (modest_runtime_get_account_store (),
3071                                        account_name,
3072                                        TNY_ACCOUNT_TYPE_TRANSPORT));
3073         if (!transport_account) {
3074                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
3075                 g_free (account_name);
3076                 modest_msg_edit_window_free_msg_data (edit_window, data);
3077                 return FALSE;
3078         }
3079
3080         /* Create the mail operation */
3081         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
3082                                                                         NULL, NULL);
3083         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3084
3085         modest_mail_operation_save_to_drafts (mail_operation,
3086                                               transport_account,
3087                                               data->draft_msg,
3088                                               data->from,
3089                                               data->to, 
3090                                               data->cc, 
3091                                               data->bcc,
3092                                               data->subject,
3093                                               data->plain_body,
3094                                               data->html_body,
3095                                               data->attachments,
3096                                               data->images,
3097                                               data->priority_flags,
3098                                               data->references,
3099                                               data->in_reply_to,
3100                                               on_save_to_drafts_cb,
3101                                               g_object_ref(edit_window));
3102
3103 #ifdef MODEST_TOOLKIT_HILDON2
3104         /* In hildon2 we always show the information banner on saving to drafts.
3105          * It will be a system information banner in this case.
3106          */
3107         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3108         modest_platform_information_banner (NULL, NULL, text);
3109         g_free (text);
3110 #else
3111         ModestMainWindow *win = NULL;
3112
3113         /* Use the main window as the parent of the banner, if the
3114            main window does not exist it won't be shown, if the parent
3115            window exists then it's properly shown. We don't use the
3116            editor window because it could be closed (save to drafts
3117            could happen after closing the window */
3118         win = (ModestMainWindow *)
3119                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3120         if (win) {
3121                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3122                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3123                 g_free (text);
3124         }
3125 #endif
3126         modest_msg_edit_window_set_modified (edit_window, FALSE);
3127
3128         /* Frees */
3129         g_free (account_name);
3130         g_object_unref (G_OBJECT (transport_account));
3131         g_object_unref (G_OBJECT (mail_operation));
3132
3133         modest_msg_edit_window_free_msg_data (edit_window, data);
3134
3135 #ifndef MODEST_TOOLKIT_HILDON2
3136         /* ** FIXME **
3137          * If the drafts folder is selected then make the header view
3138          * insensitive while the message is being saved to drafts
3139          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3140          * is not very clean but it avoids letting the drafts folder
3141          * in an inconsistent state: the user could edit the message
3142          * being saved and undesirable things would happen.
3143          * In the average case the user won't notice anything at
3144          * all. In the worst case (the user is editing a really big
3145          * file from Drafts) the header view will be insensitive
3146          * during the saving process (10 or 20 seconds, depending on
3147          * the message). Anyway this is just a quick workaround: once
3148          * we find a better solution it should be removed
3149          * See NB#65125 (commend #18) for details.
3150          */
3151         if (!had_error && win != NULL) {
3152                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3153                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3154                 if (view != NULL) {
3155                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3156                         if (folder) {
3157                                 if (modest_tny_folder_is_local_folder(folder)) {
3158                                         TnyFolderType folder_type;
3159                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3160                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3161                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3162                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3163                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3164                                         }
3165                                 }
3166                         }
3167                         if (folder != NULL) g_object_unref(folder);
3168                 }
3169         }
3170 #endif
3171
3172         return !had_error;
3173 }
3174
3175 /* For instance, when clicking the Send toolbar button when editing a message: */
3176 gboolean
3177 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3178 {
3179         TnyTransportAccount *transport_account = NULL;
3180         gboolean had_error = FALSE;
3181         MsgData *data;
3182         ModestAccountMgr *account_mgr;
3183         gchar *account_name;
3184         ModestMailOperation *mail_operation;
3185         gchar *recipients;
3186
3187         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3188
3189         /* Check names but do not automatically add them to addressbook */
3190         if (!modest_msg_edit_window_check_names (edit_window, FALSE))
3191                 return TRUE;
3192
3193         data = modest_msg_edit_window_get_msg_data (edit_window);
3194
3195         recipients = g_strconcat (data->to?data->to:"", 
3196                                   data->cc?data->cc:"",
3197                                   data->bcc?data->bcc:"",
3198                                   NULL);
3199         if (recipients == NULL || recipients[0] == '\0') {
3200                 /* Empty subject -> no send */
3201                 g_free (recipients);
3202                 modest_msg_edit_window_free_msg_data (edit_window, data);
3203                 return FALSE;
3204         }
3205         g_free (recipients);
3206
3207         /* Check size */
3208         if (!enough_space_for_message (edit_window, data)) {
3209                 modest_msg_edit_window_free_msg_data (edit_window, data);
3210                 return FALSE;
3211         }
3212
3213         account_mgr = modest_runtime_get_account_mgr();
3214         account_name = g_strdup (data->account_name);
3215         if (!account_name)
3216                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3217
3218         if (!account_name)
3219                 account_name = modest_account_mgr_get_default_account (account_mgr);
3220
3221         if (!account_name) {
3222                 modest_msg_edit_window_free_msg_data (edit_window, data);
3223                 /* Run account setup wizard */
3224                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3225                         return TRUE;
3226                 }
3227         }
3228
3229         /* Get the currently-active transport account for this modest account: */
3230         if (account_name && strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3231                 transport_account =
3232                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3233                                               (modest_runtime_get_account_store (),
3234                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3235         }
3236
3237         if (!transport_account) {
3238                 modest_msg_edit_window_free_msg_data (edit_window, data);
3239                 /* Run account setup wizard */
3240                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3241                         return TRUE;
3242         }
3243
3244
3245         /* Create the mail operation */
3246         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3247         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3248
3249         modest_mail_operation_send_new_mail (mail_operation,
3250                                              transport_account,
3251                                              data->draft_msg,
3252                                              data->from,
3253                                              data->to,
3254                                              data->cc,
3255                                              data->bcc,
3256                                              data->subject,
3257                                              data->plain_body,
3258                                              data->html_body,
3259                                              data->attachments,
3260                                              data->images,
3261                                              data->references,
3262                                              data->in_reply_to,
3263                                              data->priority_flags);
3264
3265         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3266                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3267
3268         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3269                 const GError *error = modest_mail_operation_get_error (mail_operation);
3270                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3271                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3272                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3273                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3274                         had_error = TRUE;
3275                 }
3276         }
3277
3278         /* Free data: */
3279         g_free (account_name);
3280         g_object_unref (G_OBJECT (transport_account));
3281         g_object_unref (G_OBJECT (mail_operation));
3282
3283         modest_msg_edit_window_free_msg_data (edit_window, data);
3284
3285         if (!had_error) {
3286                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3287
3288                 /* Save settings and close the window: */
3289                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3290         }
3291
3292         return !had_error;
3293 }
3294
3295 void
3296 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3297                                   ModestMsgEditWindow *window)
3298 {
3299         ModestMsgEditFormatState *format_state = NULL;
3300
3301         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3302         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3303
3304         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3305                 return;
3306
3307         format_state = modest_msg_edit_window_get_format_state (window);
3308         g_return_if_fail (format_state != NULL);
3309
3310         format_state->bold = gtk_toggle_action_get_active (action);
3311         modest_msg_edit_window_set_format_state (window, format_state);
3312         g_free (format_state);
3313
3314 }
3315
3316 void
3317 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3318                                      ModestMsgEditWindow *window)
3319 {
3320         ModestMsgEditFormatState *format_state = NULL;
3321
3322         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3323         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3324
3325         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3326                 return;
3327
3328         format_state = modest_msg_edit_window_get_format_state (window);
3329         g_return_if_fail (format_state != NULL);
3330
3331         format_state->italics = gtk_toggle_action_get_active (action);
3332         modest_msg_edit_window_set_format_state (window, format_state);
3333         g_free (format_state);
3334
3335 }
3336
3337 void
3338 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3339                                      ModestMsgEditWindow *window)
3340 {
3341         ModestMsgEditFormatState *format_state = NULL;
3342
3343         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3344         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3345
3346         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3347                 return;
3348
3349         format_state = modest_msg_edit_window_get_format_state (window);
3350         g_return_if_fail (format_state != NULL);
3351
3352         format_state->bullet = gtk_toggle_action_get_active (action);
3353         modest_msg_edit_window_set_format_state (window, format_state);
3354         g_free (format_state);
3355
3356 }
3357
3358 void
3359 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3360                                      GtkRadioAction *selected,
3361                                      ModestMsgEditWindow *window)
3362 {
3363         ModestMsgEditFormatState *format_state = NULL;
3364         GtkJustification value;
3365
3366         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3367
3368         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3369                 return;
3370
3371         value = gtk_radio_action_get_current_value (selected);
3372
3373         format_state = modest_msg_edit_window_get_format_state (window);
3374         g_return_if_fail (format_state != NULL);
3375
3376         format_state->justification = value;
3377         modest_msg_edit_window_set_format_state (window, format_state);
3378         g_free (format_state);
3379 }
3380
3381 void
3382 modest_ui_actions_on_select_editor_color (GtkAction *action,
3383                                           ModestMsgEditWindow *window)
3384 {
3385         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3386         g_return_if_fail (GTK_IS_ACTION (action));
3387
3388         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3389                 return;
3390
3391         modest_msg_edit_window_select_color (window);
3392 }
3393
3394 void
3395 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3396                                                      ModestMsgEditWindow *window)
3397 {
3398         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3399         g_return_if_fail (GTK_IS_ACTION (action));
3400
3401         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3402                 return;
3403
3404         modest_msg_edit_window_select_background_color (window);
3405 }
3406
3407 void
3408 modest_ui_actions_on_insert_image (GObject *object,
3409                                    ModestMsgEditWindow *window)
3410 {
3411         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3412
3413
3414         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3415                 return;
3416
3417         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3418                 return;
3419
3420         modest_msg_edit_window_insert_image (window);
3421 }
3422
3423 void
3424 modest_ui_actions_on_attach_file (GtkAction *action,
3425                                   ModestMsgEditWindow *window)
3426 {
3427         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3428         g_return_if_fail (GTK_IS_ACTION (action));
3429
3430         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3431                 return;
3432
3433         modest_msg_edit_window_offer_attach_file (window);
3434 }
3435
3436 void
3437 modest_ui_actions_on_remove_attachments (GtkAction *action,
3438                                          ModestMsgEditWindow *window)
3439 {
3440         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3441
3442         modest_msg_edit_window_remove_attachments (window, NULL);
3443 }
3444
3445 static void
3446 do_create_folder_cb (ModestMailOperation *mail_op,
3447                      TnyFolderStore *parent_folder,
3448                      TnyFolder *new_folder,
3449                      gpointer user_data)
3450 {
3451         gchar *suggested_name = (gchar *) user_data;
3452         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3453         const GError *error;
3454
3455         error = modest_mail_operation_get_error (mail_op);
3456         if (error) {
3457                 gboolean disk_full = FALSE;
3458                 TnyAccount *account;
3459                 /* Show an error. If there was some problem writing to
3460                    disk, show it, otherwise show the generic folder
3461                    create error. We do it here and not in an error
3462                    handler because the call to do_create_folder will
3463                    stop the main loop in a gtk_dialog_run and then,
3464                    the message won't be shown until that dialog is
3465                    closed */
3466                 account = modest_mail_operation_get_account (mail_op);
3467                 if (account) {
3468                         disk_full =
3469                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3470                                                                                 (GtkWidget *) source_win,
3471                                                                                 (GError *) error,
3472                                                                                 account,
3473                                                                                 _("mail_in_ui_folder_create_error_memory"));
3474                         g_object_unref (account);
3475                 }
3476                 if (!disk_full) {
3477                         /* Show an error and try again if there is no
3478                            full memory condition */
3479                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3480                                                             _("mail_in_ui_folder_create_error"));
3481                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3482                 }
3483
3484         } else {
3485                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3486                  * FIXME: any other? */
3487                 GtkWidget *folder_view;
3488
3489 #ifndef MODEST_TOOLKIT_HILDON2
3490                 if (MODEST_IS_MAIN_WINDOW(source_win))
3491                         folder_view =
3492                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3493                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3494                 else
3495 #endif
3496                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3497                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3498
3499                 /* Select the newly created folder. It could happen
3500                    that the widget is no longer there (i.e. the window
3501                    has been destroyed, so we need to check this */
3502                 if (folder_view)
3503                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3504                                                           new_folder, FALSE);
3505                 g_object_unref (new_folder);
3506         }
3507         /* Free. Note that the first time it'll be NULL so noop */
3508         g_free (suggested_name);
3509         g_object_unref (source_win);
3510 }
3511
3512 typedef struct {
3513         gchar *folder_name;
3514         TnyFolderStore *parent;
3515 } CreateFolderConnect;
3516
3517 static void
3518 do_create_folder_performer (gboolean canceled,
3519                          GError *err,
3520                          GtkWindow *parent_window,
3521                          TnyAccount *account,
3522                          gpointer user_data)
3523 {
3524         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3525         ModestMailOperation *mail_op;
3526
3527         if (canceled || err) {
3528                 /* In disk full conditions we could get this error here */
3529                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3530                                                                 (GtkWidget *) parent_window, err,
3531                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
3532
3533                 /* This happens if we have selected the outbox folder
3534                    as the parent */
3535                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3536                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3537                         /* Show an error and retry */
3538                         modest_platform_information_banner ((GtkWidget *) parent_window,
3539                                                             NULL,
3540                                                             _("mail_in_ui_folder_create_error"));
3541
3542                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3543                 }
3544
3545                 goto frees;
3546         }
3547
3548         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3549         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3550                                          mail_op);
3551         modest_mail_operation_create_folder (mail_op,
3552                                              helper->parent,
3553                                              (const gchar *) helper->folder_name,
3554                                              do_create_folder_cb,
3555                                              g_strdup (helper->folder_name));
3556         g_object_unref (mail_op);
3557
3558  frees:
3559         if (helper->parent)
3560                 g_object_unref (helper->parent);
3561         if (helper->folder_name)
3562                 g_free (helper->folder_name);
3563         g_slice_free (CreateFolderConnect, helper);
3564 }
3565
3566
3567 static void
3568 do_create_folder (GtkWindow *parent_window,
3569                   TnyFolderStore *suggested_parent,
3570                   const gchar *suggested_name)
3571 {
3572         gint result;
3573         gchar *folder_name = NULL;
3574         TnyFolderStore *parent_folder = NULL;
3575
3576         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3577                                                         suggested_parent,
3578                                                         (gchar *) suggested_name,
3579                                                         &folder_name,
3580                                                         &parent_folder);
3581
3582         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3583                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3584                 helper->folder_name = g_strdup (folder_name);
3585                 helper->parent = g_object_ref (parent_folder);
3586
3587                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3588                                                                TRUE,
3589                                                                parent_folder,
3590                                                                do_create_folder_performer,
3591                                                                helper);
3592         }
3593
3594         if (folder_name)
3595                 g_free (folder_name);
3596         if (parent_folder)
3597                 g_object_unref (parent_folder);
3598 }
3599
3600 static void
3601 modest_ui_actions_create_folder(GtkWidget *parent_window,
3602                                 GtkWidget *folder_view,
3603                                 TnyFolderStore *parent_folder)
3604 {
3605         if (!parent_folder) {
3606 #ifdef MODEST_TOOLKIT_HILDON2
3607                 ModestTnyAccountStore *acc_store;
3608
3609                 acc_store = modest_runtime_get_account_store ();
3610
3611                 parent_folder = (TnyFolderStore *)
3612                         modest_tny_account_store_get_local_folders_account (acc_store);
3613 #else
3614                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3615 #endif
3616         }
3617
3618         if (parent_folder) {
3619                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3620                 g_object_unref (parent_folder);
3621         }
3622 }
3623
3624 void
3625 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3626 {
3627
3628         g_return_if_fail (MODEST_IS_WINDOW(window));
3629
3630 #ifndef MODEST_TOOLKIT_HILDON2
3631         if (MODEST_IS_MAIN_WINDOW (window)) {
3632                 GtkWidget *folder_view;
3633
3634                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3635                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3636                 if (!folder_view)
3637                         return;
3638
3639                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3640 #else
3641         if (MODEST_IS_FOLDER_WINDOW (window)) {
3642                 GtkWidget *folder_view;
3643
3644                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3645                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3646 #endif
3647         } else {
3648                 g_assert_not_reached ();
3649         }
3650 }
3651
3652 static void
3653 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3654                                                gpointer user_data)
3655 {
3656         const GError *error = NULL;
3657         gchar *message = NULL;
3658         gboolean mem_full;
3659         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3660
3661         /* Get error message */
3662         error = modest_mail_operation_get_error (mail_op);
3663         if (!error)
3664                 g_return_if_reached ();
3665
3666         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3667                                                                 (GError *) error, account);
3668         if (mem_full) {
3669                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3670         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3671                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3672                 message = _CS("ckdg_ib_folder_already_exists");
3673         } else if (error->domain == TNY_ERROR_DOMAIN &&
3674                    error->code == TNY_SERVICE_ERROR_STATE) {
3675                 /* This means that the folder is already in use (a
3676                    message is opened for example */
3677                 message = _("emev_ni_internal_error");
3678         } else {
3679                 message = _CS("ckdg_ib_unable_to_rename");
3680         }
3681
3682         /* We don't set a parent for the dialog because the dialog
3683            will be destroyed so the banner won't appear */
3684         modest_platform_information_banner (NULL, NULL, message);
3685
3686         if (account)
3687                 g_object_unref (account);
3688         if (mem_full)
3689                 g_free (message);
3690 }
3691
3692 typedef struct {
3693         TnyFolderStore *folder;
3694         gchar *new_name;
3695 } RenameFolderInfo;
3696
3697 static void
3698 on_rename_folder_cb (ModestMailOperation *mail_op,
3699                      TnyFolder *new_folder,
3700                      gpointer user_data)
3701 {
3702         ModestFolderView *folder_view;
3703
3704         /* If the window was closed when renaming a folder, or if
3705          * it's not a main window this will happen */
3706         if (!MODEST_IS_FOLDER_VIEW (user_data))
3707                 return;
3708
3709         folder_view = MODEST_FOLDER_VIEW (user_data);
3710         /* Note that if the rename fails new_folder will be NULL */
3711         if (new_folder) {
3712                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3713 #ifndef MODEST_TOOLKIT_HILDON2
3714         } else {
3715                 modest_folder_view_select_first_inbox_or_local (folder_view);
3716 #endif
3717         }
3718         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3719 }
3720
3721 static void
3722 on_rename_folder_performer (gboolean canceled,
3723                             GError *err,
3724                             GtkWindow *parent_window,
3725                             TnyAccount *account,
3726                             gpointer user_data)
3727 {
3728         ModestMailOperation *mail_op = NULL;
3729         GtkTreeSelection *sel = NULL;
3730         GtkWidget *folder_view = NULL;
3731         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3732
3733         if (canceled || err) {
3734                 /* In disk full conditions we could get this error here */
3735                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3736                                                                 (GtkWidget *) parent_window, err,
3737                                                                 account, NULL);
3738         } else {
3739
3740                 mail_op =
3741                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3742                                         modest_ui_actions_rename_folder_error_handler,
3743                                         parent_window, NULL);
3744
3745                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3746                                 mail_op);
3747 #ifndef MODEST_TOOLKIT_HILDON2
3748                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3749
3750                         folder_view = modest_main_window_get_child_widget (
3751                                 MODEST_MAIN_WINDOW (parent_window),
3752                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3753                 }
3754 #else
3755                 if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3756                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3757                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3758                 }
3759 #endif
3760
3761                 /* Clear the folders view */
3762                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3763                 gtk_tree_selection_unselect_all (sel);
3764
3765                 /* Actually rename the folder */
3766                 modest_mail_operation_rename_folder (mail_op,
3767                                                      TNY_FOLDER (data->folder),
3768                                                      (const gchar *) (data->new_name),
3769                                                      on_rename_folder_cb,
3770                                                      folder_view);
3771                 g_object_unref (mail_op);
3772         }
3773
3774         g_object_unref (data->folder);
3775         g_free (data->new_name);
3776         g_free (data);
3777 }
3778
3779 void
3780 modest_ui_actions_on_rename_folder (GtkAction *action,
3781                                      ModestWindow *window)
3782 {
3783         modest_ui_actions_on_edit_mode_rename_folder (window);
3784 }
3785
3786 gboolean
3787 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3788 {
3789         TnyFolderStore *folder;
3790         GtkWidget *folder_view;
3791         gboolean do_rename = TRUE;
3792
3793         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3794
3795 #ifndef MODEST_TOOLKIT_HILDON2
3796         if (MODEST_IS_MAIN_WINDOW (window)) {
3797                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3798                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3799                 if (!folder_view)
3800                         return FALSE;
3801 #else
3802         if (MODEST_IS_FOLDER_WINDOW (window)) {
3803                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3804 #endif
3805         } else {
3806                 return FALSE;
3807         }
3808
3809         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3810
3811         if (!folder)
3812                 return FALSE;
3813
3814         if (TNY_IS_FOLDER (folder)) {
3815                 gchar *folder_name = NULL;
3816                 gint response;
3817                 const gchar *current_name;
3818                 TnyFolderStore *parent;
3819
3820                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3821                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3822                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3823                                                                      parent, current_name,
3824                                                                      &folder_name);
3825                 g_object_unref (parent);
3826
3827                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3828                         do_rename = FALSE;
3829                 } else {
3830                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3831                         rename_folder_data->folder = g_object_ref (folder);
3832                         rename_folder_data->new_name = folder_name;
3833                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3834                                         folder, on_rename_folder_performer, rename_folder_data);
3835                 }
3836         }
3837         g_object_unref (folder);
3838         return do_rename;
3839 }
3840
3841 static void
3842 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3843                                                gpointer user_data)
3844 {
3845         GObject *win = modest_mail_operation_get_source (mail_op);
3846
3847         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3848                                                 _("mail_in_ui_folder_delete_error"),
3849                                                 FALSE);
3850         g_object_unref (win);
3851 }
3852
3853 typedef struct {
3854         TnyFolderStore *folder;
3855         gboolean move_to_trash;
3856 } DeleteFolderInfo;
3857
3858 static void
3859 on_delete_folder_cb (gboolean canceled,
3860                   GError *err,
3861                   GtkWindow *parent_window,
3862                   TnyAccount *account,
3863                   gpointer user_data)
3864 {
3865         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3866         GtkWidget *folder_view;
3867         ModestMailOperation *mail_op;
3868         GtkTreeSelection *sel;
3869
3870         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3871                 /* Note that the connection process can fail due to
3872                    memory low conditions as it can not successfully
3873                    store the summary */
3874                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3875                                                                      (GtkWidget*) parent_window, err,
3876                                                                      account, NULL))
3877                         g_debug ("Error connecting when trying to delete a folder");
3878                 g_object_unref (G_OBJECT (info->folder));
3879                 g_free (info);
3880                 return;
3881         }
3882
3883 #ifndef MODEST_TOOLKIT_HILDON2
3884         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3885                 folder_view = modest_main_window_get_child_widget (
3886                         MODEST_MAIN_WINDOW (parent_window),
3887                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3888 #else
3889         if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3890                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3891 #endif
3892         } else {
3893                 g_object_unref (G_OBJECT (info->folder));
3894                 g_free (info);
3895                 return;
3896         }
3897
3898         /* Unselect the folder before deleting it to free the headers */
3899         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3900         gtk_tree_selection_unselect_all (sel);
3901
3902         /* Create the mail operation */
3903         mail_op =
3904                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3905                                 modest_ui_actions_delete_folder_error_handler,
3906                                 NULL, NULL);
3907
3908         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3909                         mail_op);
3910         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3911
3912 #ifndef MODEST_TOOLKIT_HILDON2
3913         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3914 #endif
3915
3916         g_object_unref (mail_op);
3917         g_object_unref (info->folder);
3918         g_free (info);
3919 }
3920
3921 static gboolean
3922 delete_folder (ModestWindow *window, gboolean move_to_trash)
3923 {
3924         TnyFolderStore *folder;
3925         GtkWidget *folder_view;
3926         gint response;
3927         gchar *message;
3928
3929         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3930
3931 #ifndef MODEST_TOOLKIT_HILDON2
3932         if (MODEST_IS_MAIN_WINDOW (window)) {
3933
3934                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3935                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3936 #else
3937         if (MODEST_IS_FOLDER_WINDOW (window)) {
3938                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3939 #endif
3940         } else {
3941                 return FALSE;
3942         }
3943         if (!folder_view)
3944                 return FALSE;
3945
3946         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3947
3948         if (!folder)
3949                 return FALSE;
3950
3951         /* Show an error if it's an account */
3952         if (!TNY_IS_FOLDER (folder)) {
3953                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3954                                                         _("mail_in_ui_folder_delete_error"),
3955                                                         FALSE);
3956                 g_object_unref (G_OBJECT (folder));
3957                 return FALSE;
3958         }
3959
3960         /* Ask the user */
3961         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3962                                     tny_folder_get_name (TNY_FOLDER (folder)));
3963         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3964                                                             (const gchar *) message);
3965         g_free (message);
3966
3967         if (response == GTK_RESPONSE_OK) {
3968                 TnyAccount *account = NULL;
3969                 DeleteFolderInfo *info = NULL;
3970                 info = g_new0(DeleteFolderInfo, 1);
3971                 info->folder = g_object_ref (folder);
3972                 info->move_to_trash = move_to_trash;
3973
3974                 account = tny_folder_get_account (TNY_FOLDER (folder));
3975                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3976                                                                TRUE,
3977                                                                TNY_FOLDER_STORE (account),
3978                                                                on_delete_folder_cb, info);
3979                 g_object_unref (account);
3980                 g_object_unref (folder);
3981                 return TRUE;
3982         } else {
3983                 return FALSE;
3984         }
3985 }
3986
3987 void
3988 modest_ui_actions_on_delete_folder (GtkAction *action,
3989                                     ModestWindow *window)
3990 {
3991         modest_ui_actions_on_edit_mode_delete_folder (window);
3992 }
3993
3994 gboolean
3995 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3996 {
3997         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3998
3999         return delete_folder (window, FALSE);
4000 }
4001
4002 #ifndef MODEST_TOOLKIT_HILDON2
4003 void
4004 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
4005 {
4006         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4007
4008         delete_folder (MODEST_WINDOW (main_window), TRUE);
4009 }
4010 #endif
4011
4012 typedef struct _PasswordDialogFields {
4013         GtkWidget *username;
4014         GtkWidget *password;
4015         GtkWidget *dialog;
4016 } PasswordDialogFields;
4017
4018 static void
4019 password_dialog_check_field (GtkEditable *editable,
4020                              PasswordDialogFields *fields)
4021 {
4022         const gchar *value;
4023         gboolean any_value_empty = FALSE;
4024
4025         value = modest_entry_get_text (fields->username);
4026         if ((value == NULL) || value[0] == '\0') {
4027                 any_value_empty = TRUE;
4028         }
4029         value = modest_entry_get_text (fields->password);
4030         if ((value == NULL) || value[0] == '\0') {
4031                 any_value_empty = TRUE;
4032         }
4033         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
4034 }
4035
4036 void
4037 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
4038                                          const gchar* server_account_name,
4039                                          gchar **username,
4040                                          gchar **password,
4041                                          gboolean *cancel,
4042                                          gboolean *remember,
4043                                          ModestMainWindow *main_window)
4044 {
4045         g_return_if_fail(server_account_name);
4046         gboolean completed = FALSE;
4047         PasswordDialogFields *fields = NULL;
4048
4049         /* Initalize output parameters: */
4050         if (cancel)
4051                 *cancel = FALSE;
4052
4053         if (remember)
4054                 *remember = TRUE;
4055
4056 #ifndef MODEST_TOOLKIT_GTK
4057         /* Maemo uses a different (awkward) button order,
4058          * It should probably just use gtk_alternative_dialog_button_order ().
4059          */
4060 #ifdef MODEST_TOOLKIT_HILDON2
4061         GtkWidget *dialog =
4062                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4063                                              NULL,
4064                                              GTK_DIALOG_MODAL,
4065                                              _HL("wdgt_bd_done"),
4066                                              GTK_RESPONSE_ACCEPT,
4067                                              NULL);
4068         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
4069                                         HILDON_MARGIN_DOUBLE);
4070 #else
4071         GtkWidget *dialog =
4072                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4073                                              NULL,
4074                                              GTK_DIALOG_MODAL,
4075                                              _("mcen_bd_dialog_ok"),
4076                                              GTK_RESPONSE_ACCEPT,
4077                                              _("mcen_bd_dialog_cancel"),
4078                                              GTK_RESPONSE_REJECT,
4079                                              NULL);
4080 #endif /* MODEST_TOOLKIT_HILDON2 */
4081 #else
4082         GtkWidget *dialog =
4083                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4084                                              NULL,
4085                                              GTK_DIALOG_MODAL,
4086                                              GTK_STOCK_CANCEL,
4087                                              GTK_RESPONSE_REJECT,
4088                                              GTK_STOCK_OK,
4089                                              GTK_RESPONSE_ACCEPT,
4090                                              NULL);
4091 #endif /* MODEST_TOOLKIT_GTK */
4092
4093         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
4094
4095         gchar *server_name = modest_account_mgr_get_server_account_hostname (
4096                 modest_runtime_get_account_mgr(), server_account_name);
4097         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
4098                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
4099                 if (cancel)
4100                         *cancel = TRUE;
4101                 gtk_widget_destroy (dialog);
4102                 return;
4103         }
4104
4105         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4106         GtkWidget *label = gtk_label_new (txt);
4107         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4108         g_free (txt);
4109         g_free (server_name);
4110         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4111                             FALSE, FALSE, 0);
4112         server_name = NULL;
4113
4114         /* username: */
4115         gchar *initial_username = modest_account_mgr_get_server_account_username (
4116                 modest_runtime_get_account_mgr(), server_account_name);
4117
4118         GtkWidget *entry_username = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
4119         if (initial_username)
4120                 modest_entry_set_text (entry_username, initial_username);
4121
4122         /* Dim this if a connection has ever succeeded with this username,
4123          * as per the UI spec: */
4124         /* const gboolean username_known =  */
4125         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4126         /*              modest_runtime_get_account_mgr(), server_account_name); */
4127         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4128
4129         /* We drop the username sensitive code and disallow changing it here
4130          * as tinymail does not support really changing the username in the callback
4131          */
4132         gtk_widget_set_sensitive (entry_username, FALSE);
4133
4134 #ifndef MODEST_TOOLKIT_GTK
4135         /* Auto-capitalization is the default, so let's turn it off: */
4136         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4137
4138         /* Create a size group to be used by all captions.
4139          * Note that HildonCaption does not create a default size group if we do not specify one.
4140          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4141         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4142
4143 #ifdef MODEST_TOOLKIT_HILDON2
4144         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4145                                                                   _("mail_fi_username"), FALSE,
4146                                                                   entry_username);
4147 #else
4148         GtkWidget *caption = hildon_caption_new (sizegroup,
4149                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
4150 #endif
4151         gtk_widget_show (entry_username);
4152         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4153                 FALSE, FALSE, MODEST_MARGIN_HALF);
4154         gtk_widget_show (caption);
4155 #else
4156         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
4157                             TRUE, FALSE, 0);
4158 #endif /* !MODEST_TOOLKIT_GTK */
4159
4160         /* password: */
4161         GtkWidget *entry_password = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
4162         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4163         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4164
4165 #ifndef MODEST_TOOLKIT_GTK
4166         /* Auto-capitalization is the default, so let's turn it off: */
4167         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4168                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4169
4170         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4171                                                        _("mail_fi_password"), FALSE,
4172                                                        entry_password);
4173         gtk_widget_show (entry_password);
4174         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4175                 FALSE, FALSE, MODEST_MARGIN_HALF);
4176         gtk_widget_show (caption);
4177         g_object_unref (sizegroup);
4178 #else
4179         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4180                             TRUE, FALSE, 0);
4181 #endif /* !MODEST_TOOLKIT_GTK */
4182
4183         if (initial_username != NULL)
4184                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4185
4186 /* This is not in the Maemo UI spec:
4187         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4188         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4189                             TRUE, FALSE, 0);
4190 */
4191
4192         fields = g_slice_new0 (PasswordDialogFields);
4193         fields->username = entry_username;
4194         fields->password = entry_password;
4195         fields->dialog = dialog;
4196
4197         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4198         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4199         password_dialog_check_field (NULL, fields);
4200
4201         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4202
4203         while (!completed) {
4204
4205                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4206                         if (username) {
4207                                 *username = g_strdup (modest_entry_get_text (entry_username));
4208
4209                                 /* Note that an empty field becomes the "" string */
4210                                 if (*username && strlen (*username) > 0) {
4211                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4212                                                                                         server_account_name,
4213                                                                                         *username);
4214                                         completed = TRUE;
4215
4216                                         const gboolean username_was_changed =
4217                                                 (strcmp (*username, initial_username) != 0);
4218                                         if (username_was_changed) {
4219                                                 g_warning ("%s: tinymail does not yet support changing the "
4220                                                            "username in the get_password() callback.\n", __FUNCTION__);
4221                                         }
4222                                 } else {
4223                                         g_free (*username);
4224                                         *username = NULL;
4225                                         /* Show error */
4226                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4227                                                                             _("mcen_ib_username_pw_incorrect"));
4228                                         completed = FALSE;
4229                                 }
4230                         }
4231
4232                         if (password) {
4233                                 *password = g_strdup (modest_entry_get_text (entry_password));
4234
4235                                 /* We do not save the password in the configuration,
4236                                  * because this function is only called for passwords that should
4237                                  * not be remembered:
4238                                  modest_server_account_set_password (
4239                                  modest_runtime_get_account_mgr(), server_account_name,
4240                                  *password);
4241                                  */
4242                         }
4243                         if (cancel)
4244                                 *cancel   = FALSE;
4245                 } else {
4246 #ifndef MODEST_TOOLKIT_HILDON2
4247                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4248                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4249 #endif
4250                         completed = TRUE;
4251                         if (username)
4252                                 *username = NULL;
4253                         if (password)
4254                                 *password = NULL;
4255                         if (cancel)
4256                                 *cancel   = TRUE;
4257                 }
4258         }
4259
4260 /* This is not in the Maemo UI spec:
4261         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4262                 *remember = TRUE;
4263         else
4264                 *remember = FALSE;
4265 */
4266
4267         g_free (initial_username);
4268         gtk_widget_destroy (dialog);
4269         g_slice_free (PasswordDialogFields, fields);
4270
4271         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4272 }
4273
4274 void
4275 modest_ui_actions_on_cut (GtkAction *action,
4276                           ModestWindow *window)
4277 {
4278         GtkWidget *focused_widget;
4279         GtkClipboard *clipboard;
4280
4281         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4282         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4283         if (GTK_IS_EDITABLE (focused_widget)) {
4284                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4285                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4286                 gtk_clipboard_store (clipboard);
4287         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4288                 GtkTextBuffer *buffer;
4289
4290                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4291                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4292                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4293                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4294                         gtk_clipboard_store (clipboard);
4295                 }
4296         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4297                 TnyList *header_list = modest_header_view_get_selected_headers (
4298                                 MODEST_HEADER_VIEW (focused_widget));
4299                 gboolean continue_download = FALSE;
4300                 gint num_of_unc_msgs;
4301
4302                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4303
4304                 if (num_of_unc_msgs) {
4305                         TnyAccount *account = get_account_from_header_list (header_list);
4306                         if (account) {
4307                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4308                                 g_object_unref (account);
4309                         }
4310                 }
4311
4312                 if (num_of_unc_msgs == 0 || continue_download) {
4313 /*                      modest_platform_information_banner (
4314                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4315                         modest_header_view_cut_selection (
4316                                         MODEST_HEADER_VIEW (focused_widget));
4317                 }
4318
4319                 g_object_unref (header_list);
4320         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4321                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4322         }
4323 }
4324
4325 void
4326 modest_ui_actions_on_copy (GtkAction *action,
4327                            ModestWindow *window)
4328 {
4329         GtkClipboard *clipboard;
4330         GtkWidget *focused_widget;
4331         gboolean copied = TRUE;
4332
4333         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4334         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4335
4336         if (GTK_IS_LABEL (focused_widget)) {
4337                 gchar *selection;
4338                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4339                 gtk_clipboard_set_text (clipboard, selection, -1);
4340                 g_free (selection);
4341                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4342                 gtk_clipboard_store (clipboard);
4343         } else if (GTK_IS_EDITABLE (focused_widget)) {
4344                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4345                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4346                 gtk_clipboard_store (clipboard);
4347         } else if (GTK_IS_HTML (focused_widget)) {
4348                 const gchar *sel;
4349                 int len = -1;
4350                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4351                 if ((sel == NULL) || (sel[0] == '\0')) {
4352                         copied = FALSE;
4353                 } else {
4354                         gtk_html_copy (GTK_HTML (focused_widget));
4355                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4356                         gtk_clipboard_store (clipboard);
4357                 }
4358         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4359                 GtkTextBuffer *buffer;
4360                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4361                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4362                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4363                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4364                         gtk_clipboard_store (clipboard);
4365                 }
4366         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4367                 TnyList *header_list = modest_header_view_get_selected_headers (
4368                                 MODEST_HEADER_VIEW (focused_widget));
4369                 gboolean continue_download = FALSE;
4370                 gint num_of_unc_msgs;
4371
4372                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4373
4374                 if (num_of_unc_msgs) {
4375                         TnyAccount *account = get_account_from_header_list (header_list);
4376                         if (account) {
4377                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4378                                 g_object_unref (account);
4379                         }
4380                 }
4381
4382                 if (num_of_unc_msgs == 0 || continue_download) {
4383                         modest_platform_information_banner (
4384                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4385                         modest_header_view_copy_selection (
4386                                         MODEST_HEADER_VIEW (focused_widget));
4387                 } else
4388                         copied = FALSE;
4389
4390                 g_object_unref (header_list);
4391
4392         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4393                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4394         }
4395
4396         /* Show information banner if there was a copy to clipboard */
4397         if(copied)
4398                 modest_platform_information_banner (
4399                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4400 }
4401
4402 void
4403 modest_ui_actions_on_undo (GtkAction *action,
4404                            ModestWindow *window)
4405 {
4406         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4407                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4408 #ifndef MODEST_TOOLKIT_HILDON2
4409         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4410                 ModestEmailClipboard *clipboard = NULL;
4411                 /* Clear clipboard source */
4412                 clipboard = modest_runtime_get_email_clipboard ();
4413                 modest_email_clipboard_clear (clipboard);
4414 #endif
4415         } else {
4416                 g_return_if_reached ();
4417         }
4418 }
4419
4420 void
4421 modest_ui_actions_on_redo (GtkAction *action,
4422                            ModestWindow *window)
4423 {
4424         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4425                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4426         }
4427         else {
4428                 g_return_if_reached ();
4429         }
4430 }
4431
4432
4433 static void
4434 destroy_information_note (ModestMailOperation *mail_op,
4435                           gpointer user_data)
4436 {
4437         /* destroy information note */
4438         gtk_widget_destroy (GTK_WIDGET(user_data));
4439 }
4440
4441 static void
4442 destroy_folder_information_note (ModestMailOperation *mail_op,
4443                                  TnyFolder *new_folder,
4444                                  gpointer user_data)
4445 {
4446         /* destroy information note */
4447         gtk_widget_destroy (GTK_WIDGET(user_data));
4448 }
4449
4450
4451 static void
4452 paste_as_attachment_free (gpointer data)
4453 {
4454         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4455
4456         if (helper->banner) {
4457                 gtk_widget_destroy (helper->banner);
4458                 g_object_unref (helper->banner);
4459         }
4460         g_free (helper);
4461 }
4462
4463 static void
4464 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4465                             TnyHeader *header,
4466                             TnyMsg *msg,
4467                             gpointer userdata)
4468 {
4469         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4470         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4471
4472         if (msg == NULL)
4473                 return;
4474
4475         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4476
4477 }
4478
4479 void
4480 modest_ui_actions_on_paste (GtkAction *action,
4481                             ModestWindow *window)
4482 {
4483         GtkWidget *focused_widget = NULL;
4484         GtkWidget *inf_note = NULL;
4485         ModestMailOperation *mail_op = NULL;
4486
4487         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4488         if (GTK_IS_EDITABLE (focused_widget)) {
4489                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4490         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4491                 ModestEmailClipboard *e_clipboard = NULL;
4492                 e_clipboard = modest_runtime_get_email_clipboard ();
4493                 if (modest_email_clipboard_cleared (e_clipboard)) {
4494                         GtkTextBuffer *buffer;
4495                         GtkClipboard *clipboard;
4496
4497                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4498                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4499                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4500                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4501                         ModestMailOperation *mail_op;
4502                         TnyFolder *src_folder = NULL;
4503                         TnyList *data = NULL;
4504                         gboolean delete;
4505                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4506                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4507                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4508                                                                            _CS("ckct_nw_pasting"));
4509                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4510                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4511                         if (helper->banner != NULL) {
4512                                 g_object_ref (G_OBJECT (helper->banner));
4513                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4514                         }
4515
4516                         if (data != NULL) {
4517                                 modest_mail_operation_get_msgs_full (mail_op,
4518                                                                      data,
4519                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4520                                                                      helper,
4521                                                                      paste_as_attachment_free);
4522                         }
4523                         /* Free */
4524                         if (data)
4525                                 g_object_unref (data);
4526                         if (src_folder)
4527                                 g_object_unref (src_folder);
4528
4529                 }
4530         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4531                 ModestEmailClipboard *clipboard = NULL;
4532                 TnyFolder *src_folder = NULL;
4533                 TnyFolderStore *folder_store = NULL;
4534                 TnyList *data = NULL;
4535                 gboolean delete = FALSE;
4536
4537                 /* Check clipboard source */
4538                 clipboard = modest_runtime_get_email_clipboard ();
4539                 if (modest_email_clipboard_cleared (clipboard))
4540                         return;
4541
4542                 /* Get elements to paste */
4543                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4544
4545                 /* Create a new mail operation */
4546                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4547
4548                 /* Get destination folder */
4549                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4550
4551                 /* transfer messages  */
4552                 if (data != NULL) {
4553                         gint response = 0;
4554
4555                         /* Ask for user confirmation */
4556                         response =
4557                                 modest_ui_actions_msgs_move_to_confirmation (window,
4558                                                                              TNY_FOLDER (folder_store),
4559                                                                              delete,
4560                                                                              data);
4561
4562                         if (response == GTK_RESPONSE_OK) {
4563                                 /* Launch notification */
4564                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4565                                                                              _CS("ckct_nw_pasting"));
4566                                 if (inf_note != NULL)  {
4567                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4568                                         gtk_widget_show (GTK_WIDGET(inf_note));
4569                                 }
4570
4571                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4572                                 modest_mail_operation_xfer_msgs (mail_op,
4573                                                                  data,
4574                                                                  TNY_FOLDER (folder_store),
4575                                                                  delete,
4576                                                                  destroy_information_note,
4577                                                                  inf_note);
4578                         } else {
4579                                 g_object_unref (mail_op);
4580                         }
4581
4582                 } else if (src_folder != NULL) {
4583                         /* Launch notification */
4584                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4585                                                                      _CS("ckct_nw_pasting"));
4586                         if (inf_note != NULL)  {
4587                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4588                                 gtk_widget_show (GTK_WIDGET(inf_note));
4589                         }
4590
4591                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4592                         modest_mail_operation_xfer_folder (mail_op,
4593                                                            src_folder,
4594                                                            folder_store,
4595                                                            delete,
4596                                                            destroy_folder_information_note,
4597                                                            inf_note);
4598                 }
4599
4600                 /* Free */
4601                 if (data != NULL)
4602                         g_object_unref (data);
4603                 if (src_folder != NULL)
4604                         g_object_unref (src_folder);
4605                 if (folder_store != NULL)
4606                         g_object_unref (folder_store);
4607         }
4608 }
4609
4610
4611 void
4612 modest_ui_actions_on_select_all (GtkAction *action,
4613                                  ModestWindow *window)
4614 {
4615         GtkWidget *focused_widget;
4616
4617         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4618         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4619                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4620         } else if (GTK_IS_LABEL (focused_widget)) {
4621                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4622         } else if (GTK_IS_EDITABLE (focused_widget)) {
4623                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4624         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4625                 GtkTextBuffer *buffer;
4626                 GtkTextIter start, end;
4627
4628                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4629                 gtk_text_buffer_get_start_iter (buffer, &start);
4630                 gtk_text_buffer_get_end_iter (buffer, &end);
4631                 gtk_text_buffer_select_range (buffer, &start, &end);
4632         } else if (GTK_IS_HTML (focused_widget)) {
4633                 gtk_html_select_all (GTK_HTML (focused_widget));
4634 #ifndef MODEST_TOOLKIT_HILDON2
4635         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4636                 GtkWidget *header_view = focused_widget;
4637                 GtkTreeSelection *selection = NULL;
4638
4639                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4640                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4641                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4642                 }
4643
4644                 /* Disable window dimming management */
4645                 modest_window_disable_dimming (MODEST_WINDOW(window));
4646
4647                 /* Select all messages */
4648                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4649                 gtk_tree_selection_select_all (selection);
4650
4651                 /* Set focuse on header view */
4652                 gtk_widget_grab_focus (header_view);
4653
4654                 /* Enable window dimming management */
4655                 modest_window_enable_dimming (MODEST_WINDOW(window));
4656                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4657                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4658 #endif
4659         }
4660
4661 }
4662
4663 void
4664 modest_ui_actions_on_mark_as_read (GtkAction *action,
4665                                    ModestWindow *window)
4666 {
4667         g_return_if_fail (MODEST_IS_WINDOW(window));
4668
4669         /* Mark each header as read */
4670         do_headers_action (window, headers_action_mark_as_read, NULL);
4671 }
4672
4673 void
4674 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4675                                      ModestWindow *window)
4676 {
4677         g_return_if_fail (MODEST_IS_WINDOW(window));
4678
4679         /* Mark each header as read */
4680         do_headers_action (window, headers_action_mark_as_unread, NULL);
4681 }
4682
4683 void
4684 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4685                                   GtkRadioAction *selected,
4686                                   ModestWindow *window)
4687 {
4688         gint value;
4689
4690         value = gtk_radio_action_get_current_value (selected);
4691         if (MODEST_IS_WINDOW (window)) {
4692                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4693         }
4694 }
4695
4696 void
4697 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4698                                                GtkRadioAction *selected,
4699                                                ModestWindow *window)
4700 {
4701         TnyHeaderFlags flags;
4702         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4703
4704         flags = gtk_radio_action_get_current_value (selected);
4705         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4706 }
4707
4708 void
4709 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4710                                                   GtkRadioAction *selected,
4711                                                   ModestWindow *window)
4712 {
4713         gint file_format;
4714
4715         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4716
4717         file_format = gtk_radio_action_get_current_value (selected);
4718         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4719 }
4720
4721
4722 void
4723 modest_ui_actions_on_zoom_plus (GtkAction *action,
4724                                 ModestWindow *window)
4725 {
4726         g_return_if_fail (MODEST_IS_WINDOW (window));
4727
4728         modest_window_zoom_plus (MODEST_WINDOW (window));
4729 }
4730
4731 void
4732 modest_ui_actions_on_zoom_minus (GtkAction *action,
4733                                  ModestWindow *window)
4734 {
4735         g_return_if_fail (MODEST_IS_WINDOW (window));
4736
4737         modest_window_zoom_minus (MODEST_WINDOW (window));
4738 }
4739
4740 void
4741 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4742                                            ModestWindow *window)
4743 {
4744         ModestWindowMgr *mgr;
4745         gboolean fullscreen, active;
4746         g_return_if_fail (MODEST_IS_WINDOW (window));
4747
4748         mgr = modest_runtime_get_window_mgr ();
4749
4750         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4751         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4752
4753         if (active != fullscreen) {
4754                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4755 #ifndef MODEST_TOOLKIT_HILDON2
4756                 gtk_window_present (GTK_WINDOW (window));
4757 #endif
4758         }
4759 }
4760
4761 void
4762 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4763                                         ModestWindow *window)
4764 {
4765         ModestWindowMgr *mgr;
4766         gboolean fullscreen;
4767
4768         g_return_if_fail (MODEST_IS_WINDOW (window));
4769
4770         mgr = modest_runtime_get_window_mgr ();
4771         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4772         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4773
4774 #ifndef MODEST_TOOLKIT_HILDON2
4775         gtk_window_present (GTK_WINDOW (window));
4776 #endif
4777 }
4778
4779 /*
4780  * Used by modest_ui_actions_on_details to call do_headers_action
4781  */
4782 static void
4783 headers_action_show_details (TnyHeader *header,
4784                              ModestWindow *window,
4785                              gpointer user_data)
4786
4787 {
4788         gboolean async_retrieval;
4789         TnyMsg *msg = NULL;
4790
4791         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4792                 async_retrieval = TRUE;
4793                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4794         } else {
4795                 async_retrieval = FALSE;
4796         }
4797         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4798         if (msg)
4799                 g_object_unref (msg);
4800 }
4801
4802 /*
4803  * Show the header details in a ModestDetailsDialog widget
4804  */
4805 void
4806 modest_ui_actions_on_details (GtkAction *action,
4807                               ModestWindow *win)
4808 {
4809         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4810                 TnyMsg *msg;
4811                 TnyHeader *header;
4812
4813                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4814                 if (!msg)
4815                         return;
4816
4817                 header = tny_msg_get_header (msg);
4818                 if (header) {
4819                         headers_action_show_details (header, win, NULL);
4820                         g_object_unref (header);
4821                 }
4822                 g_object_unref (msg);
4823 #ifndef MODEST_TOOLKIT_HILDON2
4824         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4825                 GtkWidget *folder_view, *header_view;
4826
4827                 /* Check which widget has the focus */
4828                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4829                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4830                 if (gtk_widget_is_focus (folder_view)) {
4831                         TnyFolderStore *folder_store
4832                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4833                         if (!folder_store) {
4834                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4835                                 return;
4836                         }
4837                         /* Show only when it's a folder */
4838                         /* This function should not be called for account items,
4839                          * because we dim the menu item for them. */
4840                         if (TNY_IS_FOLDER (folder_store)) {
4841                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4842                                                                            TNY_FOLDER (folder_store));
4843                         }
4844
4845                         g_object_unref (folder_store);
4846
4847                 } else {
4848                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4849                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4850                         /* Show details of each header */
4851                         do_headers_action (win, headers_action_show_details, header_view);
4852                 }
4853 #else
4854         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4855                 TnyFolder *folder;
4856                 GtkWidget *header_view;
4857
4858                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4859                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4860                 if (folder) {
4861                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4862                                                                    folder);
4863                         g_object_unref (folder);
4864                 }
4865 #endif
4866         }
4867 }
4868
4869 void
4870 modest_ui_actions_on_limit_error (GtkAction *action,
4871                                   ModestWindow *win)
4872 {
4873         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
4874
4875         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
4876
4877 }
4878
4879 void
4880 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4881                                      ModestMsgEditWindow *window)
4882 {
4883         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4884
4885         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4886 }
4887
4888 void
4889 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4890                                       ModestMsgEditWindow *window)
4891 {
4892         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4893
4894         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4895 }
4896
4897 #ifndef MODEST_TOOLKIT_HILDON2
4898 void
4899 modest_ui_actions_toggle_folders_view (GtkAction *action,
4900                                        ModestMainWindow *main_window)
4901 {
4902         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4903
4904         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4905                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4906         else
4907                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4908 }
4909 #endif
4910
4911 void
4912 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4913                                      ModestWindow *window)
4914 {
4915         gboolean active, fullscreen = FALSE;
4916         ModestWindowMgr *mgr;
4917
4918         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4919
4920         /* Check if we want to toggle the toolbar view in fullscreen
4921            or normal mode */
4922         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4923                      "ViewShowToolbarFullScreen")) {
4924                 fullscreen = TRUE;
4925         }
4926
4927         /* Toggle toolbar */
4928         mgr = modest_runtime_get_window_mgr ();
4929         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4930 }
4931
4932 void
4933 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4934                                            ModestMsgEditWindow *window)
4935 {
4936         modest_msg_edit_window_select_font (window);
4937 }
4938
4939
4940 void
4941 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4942                                                   const gchar *display_name,
4943                                                   GtkWindow *window)
4944 {
4945         /* don't update the display name if it was already set;
4946          * updating the display name apparently is expensive */
4947         const gchar* old_name = gtk_window_get_title (window);
4948
4949         if (display_name == NULL)
4950                 display_name = " ";
4951
4952         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4953                 return; /* don't do anything */
4954
4955         /* This is usually used to change the title of the main window, which
4956          * is the one that holds the folder view. Note that this change can
4957          * happen even when the widget doesn't have the focus. */
4958         gtk_window_set_title (window, display_name);
4959
4960 }
4961
4962 void
4963 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4964 {
4965         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4966         modest_msg_edit_window_select_contacts (window);
4967 }
4968
4969 void
4970 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4971 {
4972         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4973         modest_msg_edit_window_check_names (window, FALSE);
4974 }
4975
4976 #ifndef MODEST_TOOLKIT_HILDON2
4977 /*
4978  * This function is used to track changes in the selection of the
4979  * folder view that is inside the "move to" dialog to enable/disable
4980  * the OK button because we do not want the user to select a disallowed
4981  * destination for a folder.
4982  * The user also not desired to be able to use NEW button on items where
4983  * folder creation is not possibel.
4984  */
4985 static void
4986 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4987                                             TnyFolderStore *folder_store,
4988                                             gboolean selected,
4989                                             gpointer user_data)
4990 {
4991         GtkWidget *dialog = NULL;
4992         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4993         gboolean moving_folder = FALSE;
4994         gboolean is_local_account = TRUE;
4995         GtkWidget *folder_view = NULL;
4996         ModestTnyFolderRules rules;
4997
4998         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4999
5000         if (!selected)
5001                 return;
5002
5003         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
5004         if (!dialog)
5005                 return;
5006
5007         /* check if folder_store is an remote account */
5008         if (TNY_IS_ACCOUNT (folder_store)) {
5009                 TnyAccount *local_account = NULL;
5010                 TnyAccount *mmc_account = NULL;
5011                 ModestTnyAccountStore *account_store = NULL;
5012
5013                 account_store = modest_runtime_get_account_store ();
5014                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
5015                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
5016
5017                 if ((gpointer) local_account != (gpointer) folder_store &&
5018                     (gpointer) mmc_account != (gpointer) folder_store) {
5019                         ModestProtocolType proto;
5020                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
5021                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
5022                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
5023                         }
5024                         is_local_account = FALSE;
5025                         /* New button should be dimmed on remote
5026                            POP account root */
5027                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5028                                                                                          proto,
5029                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
5030                 }
5031                 g_object_unref (local_account);
5032
5033                 /* It could not exist */
5034                 if (mmc_account)
5035                         g_object_unref (mmc_account);
5036         }
5037
5038         /* Check the target folder rules */
5039         if (TNY_IS_FOLDER (folder_store)) {
5040                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
5041                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
5042                         ok_sensitive = FALSE;
5043                         new_sensitive = FALSE;
5044                         goto end;
5045                 }
5046         }
5047
5048         /* Check if we're moving a folder */
5049         if (MODEST_IS_MAIN_WINDOW (user_data)) {
5050                 /* Get the widgets */
5051                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
5052                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5053                 if (gtk_widget_is_focus (folder_view))
5054                         moving_folder = TRUE;
5055         }
5056
5057         if (moving_folder) {
5058                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
5059
5060                 /* Get the folder to move */
5061                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5062
5063                 /* Check that we're not moving to the same folder */
5064                 if (TNY_IS_FOLDER (moved_folder)) {
5065                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
5066                         if (parent == folder_store)
5067                                 ok_sensitive = FALSE;
5068                         g_object_unref (parent);
5069                 }
5070
5071                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
5072                         /* Do not allow to move to an account unless it's the
5073                            local folders account */
5074                         if (!is_local_account)
5075                                 ok_sensitive = FALSE;
5076                 }
5077
5078                 if (ok_sensitive && (moved_folder == folder_store)) {
5079                         /* Do not allow to move to itself */
5080                         ok_sensitive = FALSE;
5081                 }
5082                 g_object_unref (moved_folder);
5083         } else {
5084                 TnyFolder *src_folder = NULL;
5085
5086                 /* Moving a message */
5087                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
5088
5089                         TnyHeader *header = NULL;
5090                         header = modest_msg_view_window_get_header
5091                                 (MODEST_MSG_VIEW_WINDOW (user_data));
5092                         if (!TNY_IS_HEADER(header))
5093                                 g_warning ("%s: could not get source header", __FUNCTION__);
5094                         else
5095                                 src_folder = tny_header_get_folder (header);
5096
5097                         if (header)
5098                                 g_object_unref (header);
5099                 } else {
5100                         src_folder =
5101                                 TNY_FOLDER (modest_folder_view_get_selected
5102                                             (MODEST_FOLDER_VIEW (folder_view)));
5103                 }
5104
5105                 if (TNY_IS_FOLDER(src_folder)) {
5106                         /* Do not allow to move the msg to the same folder */
5107                         /* Do not allow to move the msg to an account */
5108                         if ((gpointer) src_folder == (gpointer) folder_store ||
5109                             TNY_IS_ACCOUNT (folder_store))
5110                                 ok_sensitive = FALSE;
5111                         g_object_unref (src_folder);
5112                 } else
5113                         g_warning ("%s: could not get source folder", __FUNCTION__);
5114         }
5115
5116  end:
5117         /* Set sensitivity of the OK and NEW button */
5118         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5119         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5120 }
5121 #endif
5122
5123 static void
5124 on_move_to_dialog_response (GtkDialog *dialog,
5125                             gint       response,
5126                             gpointer   user_data)
5127 {
5128         GtkWidget *parent_win;
5129         MoveToInfo *helper = NULL;
5130         ModestFolderView *folder_view;
5131         gboolean unset_edit_mode = FALSE;
5132
5133         helper = (MoveToInfo *) user_data;
5134
5135         parent_win = (GtkWidget *) helper->win;
5136         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5137                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5138         switch (response) {
5139                 TnyFolderStore *dst_folder;
5140                 TnyFolderStore *selected;
5141
5142         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5143                 selected = modest_folder_view_get_selected (folder_view);
5144                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5145                 g_object_unref (selected);
5146                 return;
5147         case GTK_RESPONSE_NONE:
5148         case GTK_RESPONSE_CANCEL:
5149         case GTK_RESPONSE_DELETE_EVENT:
5150                 break;
5151         case GTK_RESPONSE_OK:
5152                 dst_folder = modest_folder_view_get_selected (folder_view);
5153
5154 #ifndef MODEST_TOOLKIT_HILDON2
5155                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5156                         /* Clean list to move used for filtering */
5157                         modest_folder_view_set_list_to_move (folder_view, NULL);
5158
5159                         modest_ui_actions_on_main_window_move_to (NULL,
5160                                                                   GTK_WIDGET (folder_view),
5161                                                                   dst_folder,
5162                                                                   MODEST_MAIN_WINDOW (parent_win));
5163 #else
5164                 if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5165                         /* Clean list to move used for filtering */
5166                         modest_folder_view_set_list_to_move (folder_view, NULL);
5167
5168                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5169                                                                     dst_folder,
5170                                                                     helper->list,
5171                                                                     GTK_WINDOW (parent_win));
5172 #endif
5173                 } else {
5174                         /* if the user selected a root folder
5175                            (account) then do not perform any action */
5176                         if (TNY_IS_ACCOUNT (dst_folder)) {
5177                                 g_signal_stop_emission_by_name (dialog, "response");
5178                                 return;
5179                         }
5180
5181                         /* Clean list to move used for filtering */
5182                         modest_folder_view_set_list_to_move (folder_view, NULL);
5183
5184                         /* Moving from headers window in edit mode */
5185                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5186                                                              dst_folder,
5187                                                              MODEST_WINDOW (parent_win));
5188                 }
5189
5190                 if (dst_folder)
5191                         g_object_unref (dst_folder);
5192
5193                 unset_edit_mode = TRUE;
5194                 break;
5195         default:
5196                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5197         }
5198
5199         /* Free the helper and exit */
5200         if (helper->list)
5201                 g_object_unref (helper->list);
5202         if (unset_edit_mode) {
5203 #ifdef MODEST_TOOLKIT_HILDON2
5204                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5205 #endif
5206         }
5207         g_slice_free (MoveToInfo, helper);
5208         gtk_widget_destroy (GTK_WIDGET (dialog));
5209 }
5210
5211 static GtkWidget*
5212 create_move_to_dialog (GtkWindow *win,
5213                        GtkWidget *folder_view,
5214                        TnyList *list_to_move)
5215 {
5216         GtkWidget *dialog, *tree_view = NULL;
5217
5218         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5219
5220 #ifndef MODEST_TOOLKIT_HILDON2
5221         /* Track changes in the selection to
5222          * disable the OK button whenever "Move to" is not possible
5223          * disbale NEW button whenever New is not possible */
5224         g_signal_connect (tree_view,
5225                           "folder_selection_changed",
5226                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5227                           win);
5228 #endif
5229
5230         /* It could happen that we're trying to move a message from a
5231            window (msg window for example) after the main window was
5232            closed, so we can not just get the model of the folder
5233            view */
5234         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5235                 const gchar *visible_id = NULL;
5236
5237                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5238                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5239                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5240                                                MODEST_FOLDER_VIEW(tree_view));
5241
5242                 visible_id =
5243                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5244
5245                 /* Show the same account than the one that is shown in the main window */
5246                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5247                                                                              visible_id);
5248         } else {
5249                 const gchar *active_account_name = NULL;
5250                 ModestAccountMgr *mgr = NULL;
5251                 ModestAccountSettings *settings = NULL;
5252                 ModestServerAccountSettings *store_settings = NULL;
5253
5254                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5255                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5256                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
5257                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
5258
5259                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5260                 mgr = modest_runtime_get_account_mgr ();
5261                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5262
5263                 if (settings) {
5264                         const gchar *store_account_name;
5265                         store_settings = modest_account_settings_get_store_settings (settings);
5266                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5267
5268                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5269                                                                                      store_account_name);
5270                         g_object_unref (store_settings);
5271                         g_object_unref (settings);
5272                 }
5273         }
5274
5275         /* we keep a pointer to the embedded folder view, so we can
5276          *   retrieve it with get_folder_view_from_move_to_dialog (see
5277          *   above) later (needed for focus handling)
5278          */
5279         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5280
5281         /* Hide special folders */
5282 #ifndef MODEST_TOOLKIT_HILDON2
5283         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5284 #endif
5285         if (list_to_move)
5286                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5287 #ifndef MODEST_TOOLKIT_HILDON2
5288         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5289 #endif
5290
5291         gtk_widget_show (GTK_WIDGET (tree_view));
5292
5293         return dialog;
5294 }
5295
5296 /*
5297  * Shows a confirmation dialog to the user when we're moving messages
5298  * from a remote server to the local storage. Returns the dialog
5299  * response. If it's other kind of movement then it always returns
5300  * GTK_RESPONSE_OK
5301  *
5302  * This one is used by the next functions:
5303  *      modest_ui_actions_on_paste                      - commented out
5304  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5305  */
5306 gint
5307 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5308                                              TnyFolder *dest_folder,
5309                                              gboolean delete,
5310                                              TnyList *headers)
5311 {
5312         gint response = GTK_RESPONSE_OK;
5313         TnyAccount *account = NULL;
5314         TnyFolder *src_folder = NULL;
5315         TnyIterator *iter = NULL;
5316         TnyHeader *header = NULL;
5317
5318         /* return with OK if the destination is a remote folder */
5319         if (modest_tny_folder_is_remote_folder (dest_folder))
5320                 return GTK_RESPONSE_OK;
5321
5322         /* Get source folder */
5323         iter = tny_list_create_iterator (headers);
5324         header = TNY_HEADER (tny_iterator_get_current (iter));
5325         if (header) {
5326                 src_folder = tny_header_get_folder (header);
5327                 g_object_unref (header);
5328         }
5329         g_object_unref (iter);
5330
5331         /* if no src_folder, message may be an attahcment */
5332         if (src_folder == NULL)
5333                 return GTK_RESPONSE_CANCEL;
5334
5335         /* If the source is a local or MMC folder */
5336         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5337                 g_object_unref (src_folder);
5338                 return GTK_RESPONSE_OK;
5339         }
5340
5341         /* Get the account */
5342         account = tny_folder_get_account (src_folder);
5343
5344         /* now if offline we ask the user */
5345         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5346                 response = GTK_RESPONSE_OK;
5347         else
5348                 response = GTK_RESPONSE_CANCEL;
5349
5350         /* Frees */
5351         g_object_unref (src_folder);
5352         g_object_unref (account);
5353
5354         return response;
5355 }
5356
5357 static void
5358 move_to_helper_destroyer (gpointer user_data)
5359 {
5360         MoveToHelper *helper = (MoveToHelper *) user_data;
5361
5362         /* Close the "Pasting" information banner */
5363         if (helper->banner) {
5364                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5365                 g_object_unref (helper->banner);
5366         }
5367         if (gtk_tree_row_reference_valid (helper->reference)) {
5368                 gtk_tree_row_reference_free (helper->reference);
5369                 helper->reference = NULL;
5370         }
5371         g_free (helper);
5372 }
5373
5374 static void
5375 move_to_cb (ModestMailOperation *mail_op,
5376             gpointer user_data)
5377 {
5378         MoveToHelper *helper = (MoveToHelper *) user_data;
5379         GObject *object = modest_mail_operation_get_source (mail_op);
5380
5381         /* Note that the operation could have failed, in that case do
5382            nothing */
5383         if (modest_mail_operation_get_status (mail_op) !=
5384             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5385                 goto frees;
5386
5387         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5388                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5389
5390                 if (!modest_msg_view_window_select_next_message (self) &&
5391                     !modest_msg_view_window_select_previous_message (self)) {
5392                         /* No more messages to view, so close this window */
5393                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5394                 }
5395 #ifndef MODEST_TOOLKIT_HILDON2
5396         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5397                    gtk_tree_row_reference_valid (helper->reference)) {
5398                 GtkWidget *header_view;
5399                 GtkTreePath *path;
5400                 GtkTreeSelection *sel;
5401
5402                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5403                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5404                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5405                 path = gtk_tree_row_reference_get_path (helper->reference);
5406                 /* We need to unselect the previous one
5407                    because we could be copying instead of
5408                    moving */
5409                 gtk_tree_selection_unselect_all (sel);
5410                 gtk_tree_selection_select_path (sel, path);
5411                 gtk_tree_path_free (path);
5412 #endif
5413         }
5414         g_object_unref (object);
5415
5416  frees:
5417         /* Destroy the helper */
5418         move_to_helper_destroyer (helper);
5419 }
5420
5421 static void
5422 folder_move_to_cb (ModestMailOperation *mail_op,
5423                    TnyFolder *new_folder,
5424                    gpointer user_data)
5425 {
5426         GObject *object;
5427
5428         object = modest_mail_operation_get_source (mail_op);
5429 #ifndef MODEST_TOOLKIT_HILDON2
5430         if (MODEST_IS_MAIN_WINDOW (object)) {
5431                 GtkWidget *folder_view;
5432                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5433                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5434                 g_object_ref (folder_view);
5435                 g_object_unref (object);
5436                 move_to_cb (mail_op, user_data);
5437                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5438                 g_object_unref (folder_view);
5439         } else {
5440 #else
5441                 {
5442 #endif
5443                 move_to_cb (mail_op, user_data);
5444         }
5445 }
5446
5447 static void
5448 msgs_move_to_cb (ModestMailOperation *mail_op,
5449                  gpointer user_data)
5450 {
5451         move_to_cb (mail_op, user_data);
5452 }
5453
5454 void
5455 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5456                                              gpointer user_data)
5457 {
5458         GObject *win = NULL;
5459         const GError *error;
5460         TnyAccount *account = NULL;
5461
5462 #ifndef MODEST_TOOLKIT_HILDON2
5463         ModestWindow *main_window = NULL;
5464
5465         /* Disable next automatic folder selection */
5466         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5467                                                          FALSE); /* don't create */
5468
5469         /* Show notification dialog only if the main window exists */
5470         if (main_window) {
5471                 GtkWidget *folder_view = NULL;
5472
5473                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5474                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5475                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5476
5477                 if (user_data && TNY_IS_FOLDER (user_data)) {
5478                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5479                                                           TNY_FOLDER (user_data), FALSE);
5480                 }
5481         }
5482 #endif
5483         win = modest_mail_operation_get_source (mail_op);
5484         error = modest_mail_operation_get_error (mail_op);
5485
5486         if (TNY_IS_FOLDER (user_data))
5487                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
5488         else if (TNY_IS_ACCOUNT (user_data))
5489                 account = g_object_ref (user_data);
5490
5491         /* If it's not a disk full error then show a generic error */
5492         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5493                                                              (GtkWidget *) win, (GError *) error,
5494                                                              account, NULL))
5495                 modest_platform_run_information_dialog ((GtkWindow *) win,
5496                                                         _("mail_in_ui_folder_move_target_error"),
5497                                                         FALSE);
5498         if (account)
5499                 g_object_unref (account);
5500         if (win)
5501                 g_object_unref (win);
5502 }
5503
5504 #ifndef MODEST_TOOLKIT_HILDON2
5505 static void
5506 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5507                        TnyHeader *header,
5508                        gboolean canceled,
5509                        TnyMsg *msg,
5510                        GError *err,
5511                        gpointer user_data)
5512 {
5513         TnyList *parts;
5514         TnyIterator *iter;
5515         gint pending_purges = 0;
5516         gboolean some_purged = FALSE;
5517         ModestWindow *win = MODEST_WINDOW (user_data);
5518         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5519
5520         /* If there was any error */
5521         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5522                 modest_window_mgr_unregister_header (mgr, header);
5523                 return;
5524         }
5525
5526         /* Once the message has been retrieved for purging, we check if
5527          * it's all ok for purging */
5528
5529         parts = tny_simple_list_new ();
5530         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5531         iter = tny_list_create_iterator (parts);
5532
5533         while (!tny_iterator_is_done (iter)) {
5534                 TnyMimePart *part;
5535                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5536                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5537                         if (tny_mime_part_is_purged (part))
5538                                 some_purged = TRUE;
5539                         else
5540                                 pending_purges++;
5541                 }
5542
5543                 if (part)
5544                         g_object_unref (part);
5545
5546                 tny_iterator_next (iter);
5547         }
5548         g_object_unref (iter);
5549
5550
5551         if (pending_purges>0) {
5552                 gint response;
5553                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5554
5555                 if (response == GTK_RESPONSE_OK) {
5556                         GtkWidget *info;
5557                         info =
5558                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5559                         iter = tny_list_create_iterator (parts);
5560                         while (!tny_iterator_is_done (iter)) {
5561                                 TnyMimePart *part;
5562
5563                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5564                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5565                                         tny_mime_part_set_purged (part);
5566
5567                                 if (part)
5568                                         g_object_unref (part);
5569
5570                                 tny_iterator_next (iter);
5571                         }
5572                         g_object_unref (iter);
5573
5574                         tny_msg_rewrite_cache (msg);
5575
5576                         gtk_widget_destroy (info);
5577                 }
5578         }
5579
5580         modest_window_mgr_unregister_header (mgr, header);
5581
5582         g_object_unref (parts);
5583 }
5584
5585 static void
5586 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5587                                                      ModestMainWindow *win)
5588 {
5589         GtkWidget *header_view;
5590         TnyList *header_list;
5591         TnyHeader *header;
5592         TnyHeaderFlags flags;
5593         ModestWindow *msg_view_window =  NULL;
5594         gboolean found;
5595
5596         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5597
5598         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5599                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5600
5601         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5602         if (!header_list) {
5603                 g_warning ("%s: no header selected", __FUNCTION__);
5604                 return;
5605         }
5606
5607         if (tny_list_get_length (header_list) == 1) {
5608                 TnyIterator *iter = tny_list_create_iterator (header_list);
5609                 header = TNY_HEADER (tny_iterator_get_current (iter));
5610                 g_object_unref (iter);
5611         } else
5612                 return;
5613
5614         if (!header || !TNY_IS_HEADER(header)) {
5615                 g_warning ("%s: header is not valid", __FUNCTION__);
5616                 return;
5617         }
5618
5619         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5620                                                           header, &msg_view_window);
5621         flags = tny_header_get_flags (header);
5622         if (!(flags & TNY_HEADER_FLAG_CACHED))
5623                 return;
5624         if (found) {
5625                 if (msg_view_window != NULL)
5626                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5627                 else {
5628                         /* do nothing; uid was registered before, so window is probably on it's way */
5629                         g_debug ("header %p has already been registered", header);
5630                 }
5631         } else {
5632                 ModestMailOperation *mail_op = NULL;
5633                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5634                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5635                                                                          modest_ui_actions_disk_operations_error_handler,
5636                                                                          NULL, NULL);
5637                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5638                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5639
5640                 g_object_unref (mail_op);
5641         }
5642         if (header)
5643                 g_object_unref (header);
5644         if (header_list)
5645                 g_object_unref (header_list);
5646 }
5647 #endif
5648
5649 /*
5650  * Checks if we need a connection to do the transfer and if the user
5651  * wants to connect to complete it
5652  */
5653 static void
5654 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5655                                        TnyFolderStore *src_folder,
5656                                        TnyList *headers,
5657                                        TnyFolder *dst_folder,
5658                                        gboolean delete_originals,
5659                                        gboolean *need_connection,
5660                                        gboolean *do_xfer)
5661 {
5662         TnyAccount *src_account;
5663         gint uncached_msgs = 0;
5664
5665         /* We don't need any further check if
5666          *
5667          * 1- the source folder is local OR
5668          * 2- the device is already online
5669          */
5670         if (!modest_tny_folder_store_is_remote (src_folder) ||
5671             tny_device_is_online (modest_runtime_get_device())) {
5672                 *need_connection = FALSE;
5673                 *do_xfer = TRUE;
5674                 return;
5675         }
5676
5677         /* We must ask for a connection when
5678          *
5679          *   - the message(s) is not already cached   OR
5680          *   - the message(s) is cached but the leave_on_server setting
5681          * is FALSE (because we need to sync the source folder to
5682          * delete the message from the server (for IMAP we could do it
5683          * offline, it'll take place the next time we get a
5684          * connection)
5685          */
5686         uncached_msgs = header_list_count_uncached_msgs (headers);
5687         src_account = get_account_from_folder_store (src_folder);
5688         if (uncached_msgs > 0) {
5689                 guint num_headers;
5690                 const gchar *msg;
5691
5692                 *need_connection = TRUE;
5693                 num_headers = tny_list_get_length (headers);
5694                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5695
5696                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5697                     GTK_RESPONSE_CANCEL) {
5698                         *do_xfer = FALSE;
5699                 } else {
5700                         *do_xfer = TRUE;
5701                 }
5702         } else {
5703                 /* The transfer is possible and the user wants to */
5704                 *do_xfer = TRUE;
5705
5706                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5707                         const gchar *account_name;
5708                         gboolean leave_on_server;
5709
5710                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5711                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5712                                                                                   account_name);
5713
5714                         if (leave_on_server == TRUE) {
5715                                 *need_connection = FALSE;
5716                         } else {
5717                                 *need_connection = TRUE;
5718                         }
5719                 } else {
5720                         *need_connection = FALSE;
5721                 }
5722         }
5723
5724         /* Frees */
5725         g_object_unref (src_account);
5726 }
5727
5728 static void
5729 xfer_messages_error_handler (ModestMailOperation *mail_op,
5730                              gpointer user_data)
5731 {
5732         GObject *win;
5733         const GError *error;
5734         TnyAccount *account;
5735
5736         win = modest_mail_operation_get_source (mail_op);
5737         error = modest_mail_operation_get_error (mail_op);
5738
5739         /* We cannot get the account from the mail op as that is the
5740            source account and for checking memory full conditions we
5741            need the destination one */
5742         account = TNY_ACCOUNT (user_data);
5743
5744         if (error &&
5745             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5746                                                              (GtkWidget *) win, (GError*) error,
5747                                                              account, _KR("cerm_memory_card_full"))) {
5748                 modest_platform_run_information_dialog ((GtkWindow *) win,
5749                                                         _("mail_in_ui_folder_move_target_error"),
5750                                                         FALSE);
5751         }
5752         if (win)
5753                 g_object_unref (win);
5754 }
5755
5756 typedef struct {
5757         TnyFolderStore *dst_folder;
5758         TnyList *headers;
5759 } XferMsgsHelper;
5760
5761 /**
5762  * Utility function that transfer messages from both the main window
5763  * and the msg view window when using the "Move to" dialog
5764  */
5765 static void
5766 xfer_messages_performer  (gboolean canceled,
5767                           GError *err,
5768                           GtkWindow *parent_window,
5769                           TnyAccount *account,
5770                           gpointer user_data)
5771 {
5772         ModestWindow *win = MODEST_WINDOW (parent_window);
5773         TnyAccount *dst_account = NULL;
5774         gboolean dst_forbids_message_add = FALSE;
5775         XferMsgsHelper *helper;
5776         MoveToHelper *movehelper;
5777         ModestMailOperation *mail_op;
5778
5779         helper = (XferMsgsHelper *) user_data;
5780
5781         if (canceled || err) {
5782                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5783                                                                      (GtkWidget *) parent_window, err,
5784                                                                      account, NULL)) {
5785                         /* Show the proper error message */
5786                         modest_ui_actions_on_account_connection_error (parent_window, account);
5787                 }
5788                 goto end;
5789         }
5790
5791         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5792
5793         /* tinymail will return NULL for local folders it seems */
5794         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5795                                                                                   modest_tny_account_get_protocol_type (dst_account),
5796                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
5797
5798         if (dst_forbids_message_add) {
5799                 modest_platform_information_banner (GTK_WIDGET (win),
5800                                                     NULL,
5801                                                     ngettext("mail_in_ui_folder_move_target_error",
5802                                                              "mail_in_ui_folder_move_targets_error",
5803                                                              tny_list_get_length (helper->headers)));
5804                 goto end;
5805         }
5806
5807         movehelper = g_new0 (MoveToHelper, 1);
5808
5809 #ifndef MODEST_TOOLKIT_HILDON2
5810         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5811                                                                _CS("ckct_nw_pasting"));
5812         if (movehelper->banner != NULL)  {
5813                 g_object_ref (movehelper->banner);
5814                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5815         }
5816
5817         if (MODEST_IS_MAIN_WINDOW (win)) {
5818                 GtkWidget *header_view =
5819                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5820                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5821                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5822         }
5823 #endif
5824
5825         /* Perform the mail operation */
5826         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5827                                                                  xfer_messages_error_handler,
5828                                                                  g_object_ref (dst_account),
5829                                                                  g_object_unref);
5830         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5831                                          mail_op);
5832
5833         modest_mail_operation_xfer_msgs (mail_op,
5834                                          helper->headers,
5835                                          TNY_FOLDER (helper->dst_folder),
5836                                          TRUE,
5837                                          msgs_move_to_cb,
5838                                          movehelper);
5839
5840         g_object_unref (G_OBJECT (mail_op));
5841  end:
5842         if (dst_account)
5843                 g_object_unref (dst_account);
5844         g_object_unref (helper->dst_folder);
5845         g_object_unref (helper->headers);
5846         g_slice_free (XferMsgsHelper, helper);
5847 }
5848
5849 typedef struct {
5850         TnyFolder *src_folder;
5851         TnyFolderStore *dst_folder;
5852         gboolean delete_original;
5853         GtkWidget *folder_view;
5854 } MoveFolderInfo;
5855
5856 static void
5857 on_move_folder_cb (gboolean canceled,
5858                    GError *err,
5859                    GtkWindow *parent_window,
5860                    TnyAccount *account,
5861                    gpointer user_data)
5862 {
5863         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5864         GtkTreeSelection *sel;
5865         ModestMailOperation *mail_op = NULL;
5866
5867         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5868                 /* Note that the connection process can fail due to
5869                    memory low conditions as it can not successfully
5870                    store the summary */
5871                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5872                                                                      (GtkWidget*) parent_window, err,
5873                                                                      account, NULL))
5874                         g_debug ("Error connecting when trying to move a folder");
5875
5876                 g_object_unref (G_OBJECT (info->src_folder));
5877                 g_object_unref (G_OBJECT (info->dst_folder));
5878                 g_free (info);
5879                 return;
5880         }
5881
5882         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5883 #ifndef MODEST_TOOLKIT_HILDON2
5884         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5885                         _CS("ckct_nw_pasting"));
5886         if (helper->banner != NULL)  {
5887                 g_object_ref (helper->banner);
5888                 gtk_widget_show (GTK_WIDGET(helper->banner));
5889         }
5890 #endif
5891         /* Clean folder on header view before moving it */
5892         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5893         gtk_tree_selection_unselect_all (sel);
5894
5895         /* Let gtk events run. We need that the folder
5896            view frees its reference to the source
5897            folder *before* issuing the mail operation
5898            so we need the signal handler of selection
5899            changed to happen before the mail
5900            operation
5901         while (gtk_events_pending ())
5902                 gtk_main_iteration ();   */
5903
5904         mail_op =
5905                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5906                                                                modest_ui_actions_move_folder_error_handler,
5907                                                                g_object_ref (info->dst_folder), g_object_unref);
5908         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5909                                          mail_op);
5910
5911 #ifndef MODEST_TOOLKIT_HILDON2
5912         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5913                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5914                                                   TNY_FOLDER (info->dst_folder), TRUE);
5915         }
5916 #endif
5917         modest_mail_operation_xfer_folder (mail_op,
5918                         TNY_FOLDER (info->src_folder),
5919                         info->dst_folder,
5920                         info->delete_original,
5921                         folder_move_to_cb,
5922                         helper);
5923         g_object_unref (G_OBJECT (info->src_folder));
5924
5925         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5926         /* } */
5927
5928         /* Unref mail operation */
5929         g_object_unref (G_OBJECT (mail_op));
5930         g_object_unref (G_OBJECT (info->dst_folder));
5931         g_free (user_data);
5932 }
5933
5934 static TnyAccount *
5935 get_account_from_folder_store (TnyFolderStore *folder_store)
5936 {
5937         if (TNY_IS_ACCOUNT (folder_store))
5938                 return g_object_ref (folder_store);
5939         else
5940                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5941 }
5942
5943 #ifndef MODEST_TOOLKIT_HILDON2
5944 /*
5945  * UI handler for the "Move to" action when invoked from the
5946  * ModestMainWindow
5947  */
5948 static void
5949 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5950                                           GtkWidget *folder_view,
5951                                           TnyFolderStore *dst_folder,
5952                                           ModestMainWindow *win)
5953 {
5954         ModestHeaderView *header_view = NULL;
5955         TnyFolderStore *src_folder = NULL;
5956
5957         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5958
5959         /* Get the source folder */
5960         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5961
5962         /* Get header view */
5963         header_view = (ModestHeaderView *)
5964                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5965
5966         /* Get folder or messages to transfer */
5967         if (gtk_widget_is_focus (folder_view)) {
5968                 gboolean do_xfer = TRUE;
5969
5970                 /* Allow only to transfer folders to the local root folder */
5971                 if (TNY_IS_ACCOUNT (dst_folder) &&
5972                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5973                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5974                         do_xfer = FALSE;
5975                 } else if (!TNY_IS_FOLDER (src_folder)) {
5976                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5977                         do_xfer = FALSE;
5978                 }
5979
5980                 if (do_xfer) {
5981                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5982                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5983
5984                         info->src_folder = g_object_ref (src_folder);
5985                         info->dst_folder = g_object_ref (dst_folder);
5986                         info->delete_original = TRUE;
5987                         info->folder_view = folder_view;
5988
5989                         connect_info->callback = on_move_folder_cb;
5990                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5991                         connect_info->data = info;
5992
5993                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5994                                                                    TNY_FOLDER_STORE (src_folder),
5995                                                                    connect_info);
5996                 }
5997         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5998                 TnyList *headers;
5999
6000                 headers = modest_header_view_get_selected_headers(header_view);
6001
6002                 /* Transfer the messages */
6003                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
6004                                                             headers, TNY_FOLDER (dst_folder));
6005
6006                 g_object_unref (headers);
6007         }
6008
6009         /* Frees */
6010         g_object_unref (src_folder);
6011 }
6012 #endif
6013
6014 #ifdef MODEST_TOOLKIT_HILDON2
6015 /*
6016  * UI handler for the "Move to" action when invoked from the
6017  * ModestFolderWindow
6018  */
6019 static void
6020 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
6021                                             TnyFolderStore *dst_folder,
6022                                             TnyList *selection,
6023                                             GtkWindow *win)
6024 {
6025         TnyFolderStore *src_folder = NULL;
6026         TnyIterator *iterator;
6027
6028         if (tny_list_get_length (selection) != 1)
6029                 return;
6030
6031         iterator = tny_list_create_iterator (selection);
6032         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
6033         g_object_unref (iterator);
6034
6035
6036         gboolean do_xfer = TRUE;
6037
6038         /* Allow only to transfer folders to the local root folder */
6039         if (TNY_IS_ACCOUNT (dst_folder) &&
6040             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
6041             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
6042                 do_xfer = FALSE;
6043                 /* Show an error */
6044                 modest_platform_run_information_dialog (win,
6045                                                         _("mail_in_ui_folder_move_target_error"),
6046                                                         FALSE);
6047         } else if (!TNY_IS_FOLDER (src_folder)) {
6048                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6049                 do_xfer = FALSE;
6050         }
6051
6052         if (do_xfer) {
6053                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6054                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6055
6056                 info->src_folder = g_object_ref (src_folder);
6057                 info->dst_folder = g_object_ref (dst_folder);
6058                 info->delete_original = TRUE;
6059                 info->folder_view = folder_view;
6060
6061                 connect_info->callback = on_move_folder_cb;
6062                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6063                 connect_info->data = info;
6064
6065                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6066                                                            TNY_FOLDER_STORE (src_folder),
6067                                                            connect_info);
6068         }
6069
6070         /* Frees */
6071         g_object_unref (src_folder);
6072 }
6073 #endif
6074
6075
6076 void
6077 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
6078                                             TnyFolder *src_folder,
6079                                             TnyList *headers,
6080                                             TnyFolder *dst_folder)
6081 {
6082         gboolean need_connection = TRUE;
6083         gboolean do_xfer = TRUE;
6084         XferMsgsHelper *helper;
6085
6086         g_return_if_fail (TNY_IS_FOLDER (src_folder));
6087         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6088         g_return_if_fail (TNY_IS_LIST (headers));
6089
6090         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
6091                                                headers, TNY_FOLDER (dst_folder),
6092                                                TRUE, &need_connection,
6093                                                &do_xfer);
6094
6095         /* If we don't want to transfer just return */
6096         if (!do_xfer)
6097                 return;
6098
6099         /* Create the helper */
6100         helper = g_slice_new (XferMsgsHelper);
6101         helper->dst_folder = g_object_ref (dst_folder);
6102         helper->headers = g_object_ref (headers);
6103
6104         if (need_connection) {
6105                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6106                 connect_info->callback = xfer_messages_performer;
6107                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
6108                 connect_info->data = helper;
6109
6110                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6111                                                            TNY_FOLDER_STORE (src_folder),
6112                                                            connect_info);
6113         } else {
6114                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
6115                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
6116                                          src_account, helper);
6117                 g_object_unref (src_account);
6118         }
6119 }
6120
6121 /*
6122  * UI handler for the "Move to" action when invoked from the
6123  * ModestMsgViewWindow
6124  */
6125 static void
6126 modest_ui_actions_on_window_move_to (GtkAction *action,
6127                                      TnyList *headers,
6128                                      TnyFolderStore *dst_folder,
6129                                      ModestWindow *win)
6130 {
6131         TnyFolder *src_folder = NULL;
6132
6133         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6134
6135         if (headers) {
6136                 TnyHeader *header = NULL;
6137                 TnyIterator *iter;
6138
6139                 iter = tny_list_create_iterator (headers);
6140                 header = (TnyHeader *) tny_iterator_get_current (iter);
6141                 src_folder = tny_header_get_folder (header);
6142
6143                 /* Transfer the messages */
6144                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6145                                                             headers,
6146                                                             TNY_FOLDER (dst_folder));
6147
6148                 /* Frees */
6149                 g_object_unref (header);
6150                 g_object_unref (iter);
6151                 g_object_unref (src_folder);
6152         }
6153 }
6154
6155 void
6156 modest_ui_actions_on_move_to (GtkAction *action,
6157                               ModestWindow *win)
6158 {
6159         modest_ui_actions_on_edit_mode_move_to (win);
6160 }
6161
6162 gboolean
6163 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6164 {
6165         GtkWidget *dialog = NULL;
6166         MoveToInfo *helper = NULL;
6167         TnyList *list_to_move;
6168
6169         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6170
6171 #ifndef MODEST_TOOLKIT_HILDON2
6172         /* Get the main window if exists */
6173         ModestMainWindow *main_window;
6174         if (MODEST_IS_MAIN_WINDOW (win))
6175                 main_window = MODEST_MAIN_WINDOW (win);
6176         else
6177                 main_window =
6178                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6179                                                                                FALSE)); /* don't create */
6180 #endif
6181
6182         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6183
6184         if (!list_to_move)
6185                 return FALSE;
6186
6187         if (tny_list_get_length (list_to_move) < 1) {
6188                 g_object_unref (list_to_move);
6189                 return FALSE;
6190         }
6191
6192         /* Create and run the dialog */
6193         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6194         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6195                                      GTK_WINDOW (dialog),
6196                                      (GtkWindow *) win);
6197
6198         /* Create helper */
6199         helper = g_slice_new0 (MoveToInfo);
6200         helper->list = list_to_move;
6201         helper->win = win;
6202
6203         /* Listen to response signal */
6204         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6205
6206         /* Show the dialog */
6207         gtk_widget_show (dialog);
6208
6209         return FALSE;
6210 }
6211
6212 /*
6213  * Calls #HeadersFunc for each header already selected in the main
6214  * window or the message currently being shown in the msg view window
6215  */
6216 static void
6217 do_headers_action (ModestWindow *win,
6218                    HeadersFunc func,
6219                    gpointer user_data)
6220 {
6221         TnyList *headers_list = NULL;
6222         TnyIterator *iter = NULL;
6223         TnyHeader *header = NULL;
6224         TnyFolder *folder = NULL;
6225
6226         /* Get headers */
6227         headers_list = get_selected_headers (win);
6228         if (!headers_list)
6229                 return;
6230
6231         /* Get the folder */
6232         iter = tny_list_create_iterator (headers_list);
6233         header = TNY_HEADER (tny_iterator_get_current (iter));
6234         if (header) {
6235                 folder = tny_header_get_folder (header);
6236                 g_object_unref (header);
6237         }
6238
6239         /* Call the function for each header */
6240         while (!tny_iterator_is_done (iter)) {
6241                 header = TNY_HEADER (tny_iterator_get_current (iter));
6242                 func (header, win, user_data);
6243                 g_object_unref (header);
6244                 tny_iterator_next (iter);
6245         }
6246
6247         /* Trick: do a poke status in order to speed up the signaling
6248            of observers */
6249         if (folder) {
6250                 tny_folder_poke_status (folder);
6251                 g_object_unref (folder);
6252         }
6253
6254         /* Frees */
6255         g_object_unref (iter);
6256         g_object_unref (headers_list);
6257 }
6258
6259 void
6260 modest_ui_actions_view_attachment (GtkAction *action,
6261                                    ModestWindow *window)
6262 {
6263         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6264                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6265         } else {
6266                 /* not supported window for this action */
6267                 g_return_if_reached ();
6268         }
6269 }
6270
6271 void
6272 modest_ui_actions_save_attachments (GtkAction *action,
6273                                     ModestWindow *window)
6274 {
6275         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6276
6277                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6278                         return;
6279
6280                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6281         } else {
6282                 /* not supported window for this action */
6283                 g_return_if_reached ();
6284         }
6285 }
6286
6287 void
6288 modest_ui_actions_remove_attachments (GtkAction *action,
6289                                       ModestWindow *window)
6290 {
6291 #ifndef MODEST_TOOLKIT_HILDON2
6292         if (MODEST_IS_MAIN_WINDOW (window)) {
6293                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6294         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6295 #else
6296         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6297 #endif
6298                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6299         } else {
6300                 /* not supported window for this action */
6301                 g_return_if_reached ();
6302         }
6303 }
6304
6305 void
6306 modest_ui_actions_on_settings (GtkAction *action,
6307                                ModestWindow *win)
6308 {
6309         GtkWidget *dialog;
6310
6311         dialog = modest_platform_get_global_settings_dialog ();
6312         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6313         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6314         gtk_widget_show_all (dialog);
6315
6316         gtk_dialog_run (GTK_DIALOG (dialog));
6317
6318         gtk_widget_destroy (dialog);
6319 }
6320
6321 void
6322 modest_ui_actions_on_help (GtkAction *action,
6323                            GtkWindow *win)
6324 {
6325         /* Help app is not available at all in fremantle */
6326 #ifndef MODEST_TOOLKIT_HILDON2
6327         const gchar *help_id;
6328
6329         g_return_if_fail (win && GTK_IS_WINDOW(win));
6330
6331         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6332
6333         if (help_id)
6334                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6335 #endif
6336 }
6337
6338 void
6339 modest_ui_actions_on_csm_help (GtkAction *action,
6340                                GtkWindow *win)
6341 {
6342         /* Help app is not available at all in fremantle */
6343 #ifndef MODEST_TOOLKIT_HILDON2
6344
6345         const gchar* help_id = NULL;
6346         GtkWidget *folder_view;
6347         TnyFolderStore *folder_store;
6348
6349         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6350
6351         /* Get selected folder */
6352         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6353                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6354         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6355
6356         /* Switch help_id */
6357         if (folder_store && TNY_IS_FOLDER (folder_store))
6358                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6359
6360         if (folder_store)
6361                 g_object_unref (folder_store);
6362
6363         if (help_id)
6364                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6365         else
6366                 modest_ui_actions_on_help (action, win);
6367 #endif
6368 }
6369
6370 static void
6371 retrieve_contents_cb (ModestMailOperation *mail_op,
6372                       TnyHeader *header,
6373                       gboolean canceled,
6374                       TnyMsg *msg,
6375                       GError *err,
6376                       gpointer user_data)
6377 {
6378         /* We only need this callback to show an error in case of
6379            memory low condition */
6380         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6381                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6382         }
6383 }
6384
6385 static void
6386 retrieve_msg_contents_performer (gboolean canceled,
6387                                  GError *err,
6388                                  GtkWindow *parent_window,
6389                                  TnyAccount *account,
6390                                  gpointer user_data)
6391 {
6392         ModestMailOperation *mail_op;
6393         TnyList *headers = TNY_LIST (user_data);
6394
6395         if (err || canceled) {
6396                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6397                                                                 (GtkWidget *) parent_window, err,
6398                                                                 account, NULL);
6399                 goto out;
6400         }
6401
6402         /* Create mail operation */
6403         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6404                                                                  modest_ui_actions_disk_operations_error_handler,
6405                                                                  NULL, NULL);
6406         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6407         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6408
6409         /* Frees */
6410         g_object_unref (mail_op);
6411  out:
6412         g_object_unref (headers);
6413         g_object_unref (account);
6414 }
6415
6416 void
6417 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6418                                             ModestWindow *window)
6419 {
6420         TnyList *headers = NULL;
6421         TnyAccount *account = NULL;
6422         TnyIterator *iter = NULL;
6423         TnyHeader *header = NULL;
6424         TnyFolder *folder = NULL;
6425
6426         /* Get headers */
6427         headers = get_selected_headers (window);
6428         if (!headers)
6429                 return;
6430
6431         /* Pick the account */
6432         iter = tny_list_create_iterator (headers);
6433         header = TNY_HEADER (tny_iterator_get_current (iter));
6434         folder = tny_header_get_folder (header);
6435         account = tny_folder_get_account (folder);
6436         g_object_unref (folder);
6437         g_object_unref (header);
6438         g_object_unref (iter);
6439
6440         /* Connect and perform the message retrieval */
6441         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6442                                              g_object_ref (account),
6443                                              retrieve_msg_contents_performer,
6444                                              g_object_ref (headers));
6445
6446         /* Frees */
6447         g_object_unref (account);
6448         g_object_unref (headers);
6449 }
6450
6451 void
6452 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6453 {
6454         g_return_if_fail (MODEST_IS_WINDOW (window));
6455
6456         /* Update dimmed */
6457         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6458 }
6459
6460 void
6461 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6462 {
6463         g_return_if_fail (MODEST_IS_WINDOW (window));
6464
6465         /* Update dimmed */
6466         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6467 }
6468
6469 void
6470 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6471                                           ModestWindow *window)
6472 {
6473         g_return_if_fail (MODEST_IS_WINDOW (window));
6474
6475         /* Update dimmed */
6476         modest_ui_actions_check_menu_dimming_rules (window);
6477 }
6478
6479 void
6480 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6481                                           ModestWindow *window)
6482 {
6483         g_return_if_fail (MODEST_IS_WINDOW (window));
6484
6485         /* Update dimmed */
6486         modest_ui_actions_check_menu_dimming_rules (window);
6487 }
6488
6489 void
6490 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6491                                           ModestWindow *window)
6492 {
6493         g_return_if_fail (MODEST_IS_WINDOW (window));
6494
6495         /* Update dimmed */
6496         modest_ui_actions_check_menu_dimming_rules (window);
6497 }
6498
6499 void
6500 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6501                                             ModestWindow *window)
6502 {
6503         g_return_if_fail (MODEST_IS_WINDOW (window));
6504
6505         /* Update dimmed */
6506         modest_ui_actions_check_menu_dimming_rules (window);
6507 }
6508
6509 void
6510 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6511                                           ModestWindow *window)
6512 {
6513         g_return_if_fail (MODEST_IS_WINDOW (window));
6514
6515         /* Update dimmed */
6516         modest_ui_actions_check_menu_dimming_rules (window);
6517 }
6518
6519 void
6520 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6521                                           ModestWindow *window)
6522 {
6523         g_return_if_fail (MODEST_IS_WINDOW (window));
6524
6525         /* Update dimmed */
6526         modest_ui_actions_check_menu_dimming_rules (window);
6527 }
6528
6529 void
6530 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6531                                                  ModestWindow *window)
6532 {
6533         g_return_if_fail (MODEST_IS_WINDOW (window));
6534
6535         /* Update dimmed */
6536         modest_ui_actions_check_menu_dimming_rules (window);
6537 }
6538
6539 void
6540 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6541                                                      ModestWindow *window)
6542 {
6543         g_return_if_fail (MODEST_IS_WINDOW (window));
6544
6545         /* Update dimmed */
6546         modest_ui_actions_check_menu_dimming_rules (window);
6547 }
6548
6549 void
6550 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6551                                                      ModestWindow *window)
6552 {
6553         g_return_if_fail (MODEST_IS_WINDOW (window));
6554
6555         /* Update dimmed */
6556         modest_ui_actions_check_menu_dimming_rules (window);
6557 }
6558
6559 void
6560 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6561 {
6562         g_return_if_fail (MODEST_IS_WINDOW (window));
6563
6564         /* we check for low-mem; in that case, show a warning, and don't allow
6565          * searching
6566          */
6567         if (modest_platform_check_memory_low (window, TRUE))
6568                 return;
6569
6570         modest_platform_show_search_messages (GTK_WINDOW (window));
6571 }
6572
6573 void
6574 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6575 {
6576         g_return_if_fail (MODEST_IS_WINDOW (win));
6577
6578
6579         /* we check for low-mem; in that case, show a warning, and don't allow
6580          * for the addressbook
6581          */
6582         if (modest_platform_check_memory_low (win, TRUE))
6583                 return;
6584
6585
6586         modest_platform_show_addressbook (GTK_WINDOW (win));
6587 }
6588
6589
6590 void
6591 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6592                                           ModestWindow *window)
6593 {
6594         gboolean active;
6595         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6596
6597         if (GTK_IS_TOGGLE_ACTION (action))
6598                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6599         else
6600                 active = TRUE;
6601
6602         modest_msg_edit_window_toggle_isearch_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6603                                                        active);
6604 }
6605
6606 #ifndef MODEST_TOOLKIT_HILDON2
6607 static void
6608 on_send_receive_finished (ModestMailOperation  *mail_op,
6609                            gpointer user_data)
6610 {
6611         GtkWidget *header_view, *folder_view;
6612         TnyFolderStore *folder_store;
6613         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6614
6615         /* Set send/receive operation finished */
6616         modest_main_window_notify_send_receive_completed (main_win);
6617
6618         /* Don't refresh the current folder if there were any errors */
6619         if (modest_mail_operation_get_status (mail_op) !=
6620             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6621                 return;
6622
6623         /* Refresh the current folder if we're viewing a window. We do
6624            this because the user won't be able to see the new mails in
6625            the selected folder after a Send&Receive because it only
6626            performs a poke_status, i.e, only the number of read/unread
6627            messages is updated, but the new headers are not
6628            downloaded */
6629         folder_view = modest_main_window_get_child_widget (main_win,
6630                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6631         if (!folder_view)
6632                 return;
6633
6634         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6635
6636         /* Do not need to refresh INBOX again because the
6637            update_account does it always automatically */
6638         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6639             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6640                 ModestMailOperation *refresh_op;
6641
6642                 header_view = modest_main_window_get_child_widget (main_win,
6643                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6644
6645                 /* We do not need to set the contents style
6646                    because it hasn't changed. We also do not
6647                    need to save the widget status. Just force
6648                    a refresh */
6649                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6650                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6651                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6652                                                       folder_refreshed_cb, main_win);
6653                 g_object_unref (refresh_op);
6654         }
6655
6656         if (folder_store)
6657                 g_object_unref (folder_store);
6658 }
6659 #endif
6660
6661 void
6662 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6663                                                 TnyHeader *header,
6664                                                 TnyMsg *msg,
6665                                                 GError *err,
6666                                                 gpointer user_data)
6667 {
6668         const gchar* server_name = NULL;
6669         TnyTransportAccount *transport;
6670         gchar *message = NULL;
6671         ModestProtocol *protocol;
6672
6673         /* Don't show anything if the user cancelled something or the
6674          * send receive request is not interactive. Authentication
6675          * errors are managed by the account store so no need to show
6676          * a dialog here again */
6677         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6678             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6679             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6680                 return;
6681
6682
6683         /* Get the server name. Note that we could be using a
6684            connection specific transport account */
6685         transport = (TnyTransportAccount *)
6686                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6687         if (transport) {
6688                 ModestTnyAccountStore *acc_store;
6689                 const gchar *acc_name;
6690                 TnyTransportAccount *conn_specific;
6691
6692                 acc_store = modest_runtime_get_account_store();
6693                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6694                 conn_specific = (TnyTransportAccount *)
6695                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6696                 if (conn_specific) {
6697                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6698                         g_object_unref (conn_specific);
6699                 } else {
6700                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6701                 }
6702                 g_object_unref (transport);
6703         }
6704
6705         /* Get protocol */
6706         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6707                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6708                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6709         if (!protocol) {
6710                 g_warning ("%s: Account with no proto", __FUNCTION__);
6711                 return;
6712         }
6713
6714         /* Show the appropriate message text for the GError: */
6715         switch (err->code) {
6716         case TNY_SERVICE_ERROR_CONNECT:
6717                 message = modest_protocol_get_translation (protocol,
6718                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6719                                                            server_name);
6720                 break;
6721         case TNY_SERVICE_ERROR_SEND:
6722                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6723                 break;
6724         case TNY_SERVICE_ERROR_UNAVAILABLE:
6725                 message = modest_protocol_get_translation (protocol,
6726                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6727                                                            server_name);
6728                 break;
6729         default:
6730                 g_warning ("%s: unexpected ERROR %d",
6731                            __FUNCTION__, err->code);
6732                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6733                 break;
6734         }
6735
6736         modest_platform_run_information_dialog (NULL, message, FALSE);
6737         g_free (message);
6738 }
6739
6740 void
6741 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6742                                                 gchar *msg_id,
6743                                                 guint status,
6744                                                 gpointer user_data)
6745 {
6746         ModestWindow *top_window = NULL;
6747         ModestWindowMgr *mgr = NULL;
6748         GtkWidget *header_view = NULL;
6749         TnyFolder *selected_folder = NULL;
6750         TnyFolderType folder_type;
6751
6752         mgr = modest_runtime_get_window_mgr ();
6753         top_window = modest_window_mgr_get_current_top (mgr);
6754
6755         if (!top_window)
6756                 return;
6757
6758 #ifndef MODEST_TOOLKIT_HILDON2
6759         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6760                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6761                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6762         }
6763 #else
6764         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6765                 header_view = (GtkWidget *)
6766                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6767         }
6768 #endif
6769
6770         /* Get selected folder */
6771         if (header_view)
6772                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6773         if (!selected_folder)
6774                 return;
6775
6776         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6777 #if GTK_CHECK_VERSION(2, 8, 0)
6778         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6779         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6780                 GtkTreeViewColumn *tree_column;
6781
6782                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6783                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6784                 if (tree_column)
6785                         gtk_tree_view_column_queue_resize (tree_column);
6786                 }
6787 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6788         gtk_widget_queue_draw (header_view);
6789 #endif
6790
6791 #ifndef MODEST_TOOLKIT_HILDON2
6792         /* Rerun dimming rules, because the message could become deletable for example */
6793         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6794                                                  MODEST_DIMMING_RULES_TOOLBAR);
6795         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6796                                                  MODEST_DIMMING_RULES_MENU);
6797 #endif
6798
6799         /* Free */
6800         g_object_unref (selected_folder);
6801 }
6802
6803 void
6804 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6805                                                TnyAccount *account)
6806 {
6807         ModestProtocolType protocol_type;
6808         ModestProtocol *protocol;
6809         gchar *error_note = NULL;
6810
6811         protocol_type = modest_tny_account_get_protocol_type (account);
6812         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6813                                                                   protocol_type);
6814
6815         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6816         if (error_note == NULL) {
6817                 g_warning ("%s: This should not be reached", __FUNCTION__);
6818         } else {
6819                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6820                 g_free (error_note);
6821         }
6822 }
6823
6824 gchar *
6825 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6826 {
6827         gchar *msg = NULL;
6828         gchar *subject;
6829         TnyFolderStore *folder = NULL;
6830         TnyAccount *account = NULL;
6831         ModestProtocolType proto;
6832         ModestProtocol *protocol;
6833         TnyHeader *header = NULL;
6834
6835 #ifndef MODEST_TOOLKIT_HILDON2
6836         if (MODEST_IS_MAIN_WINDOW (win)) {
6837                 GtkWidget *header_view;
6838                 TnyList* headers = NULL;
6839                 TnyIterator *iter;
6840                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6841                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6842                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6843                 if (!headers || tny_list_get_length (headers) == 0) {
6844                         if (headers)
6845                                 g_object_unref (headers);
6846                         return NULL;
6847                 }
6848                 iter = tny_list_create_iterator (headers);
6849                 header = TNY_HEADER (tny_iterator_get_current (iter));
6850                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6851                 g_object_unref (iter);
6852                 g_object_unref (headers);
6853 #else
6854         if (MODEST_IS_HEADER_WINDOW (win)) {
6855                 GtkWidget *header_view;
6856                 TnyList* headers = NULL;
6857                 TnyIterator *iter;
6858                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6859                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6860                 if (!headers || tny_list_get_length (headers) == 0) {
6861                         if (headers)
6862                                 g_object_unref (headers);
6863                         return NULL;
6864                 }
6865                 iter = tny_list_create_iterator (headers);
6866                 header = TNY_HEADER (tny_iterator_get_current (iter));
6867                 if (header) {
6868                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6869                 } else {
6870                         g_warning ("List should contain headers");
6871                 }
6872                 g_object_unref (iter);
6873                 g_object_unref (headers);
6874 #endif
6875         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6876                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6877                 if (header)
6878                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6879         }
6880
6881         if (!header || !folder)
6882                 goto frees;
6883
6884         /* Get the account type */
6885         account = tny_folder_get_account (TNY_FOLDER (folder));
6886         proto = modest_tny_account_get_protocol_type (account);
6887         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6888                                                                   proto);
6889
6890         subject = tny_header_dup_subject (header);
6891         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6892         if (subject)
6893                 g_free (subject);
6894         if (msg == NULL) {
6895                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6896         }
6897
6898  frees:
6899         /* Frees */
6900         if (account)
6901                 g_object_unref (account);
6902         if (folder)
6903                 g_object_unref (folder);
6904         if (header)
6905                 g_object_unref (header);
6906
6907         return msg;
6908 }
6909
6910 gboolean
6911 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6912                                      const gchar *account_name,
6913                                      const gchar *account_title)
6914 {
6915         ModestAccountMgr *account_mgr;
6916         gchar *txt = NULL;
6917         gint response;
6918         ModestProtocol *protocol;
6919         gboolean removed = FALSE;
6920
6921         g_return_val_if_fail (account_name, FALSE);
6922         g_return_val_if_fail (account_title, FALSE);
6923
6924         account_mgr = modest_runtime_get_account_mgr();
6925
6926         /* The warning text depends on the account type: */
6927         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6928                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6929                                                                                                          account_name));
6930         txt = modest_protocol_get_translation (protocol,
6931                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6932                                                account_title);
6933         if (txt == NULL)
6934                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6935
6936         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6937         g_free (txt);
6938         txt = NULL;
6939
6940         if (response == GTK_RESPONSE_OK) {
6941                 /* Remove account. If it succeeds then it also removes
6942                    the account from the ModestAccountView: */
6943                 gboolean is_default = FALSE;
6944                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6945                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6946                         is_default = TRUE;
6947                 g_free (default_account_name);
6948
6949                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6950                 if (removed) {
6951                         /* Close all email notifications, we cannot
6952                            distinguish if the notification belongs to
6953                            this account or not, so for safety reasons
6954                            we remove them all */
6955                         modest_platform_remove_new_mail_notifications (FALSE);
6956                 } else {
6957                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6958                 }
6959         }
6960         return removed;
6961 }
6962
6963 static void
6964 on_fetch_images_performer (gboolean canceled,
6965                            GError *err,
6966                            GtkWindow *parent_window,
6967                            TnyAccount *account,
6968                            gpointer user_data)
6969 {
6970         if (err || canceled) {
6971                 /* Show an unable to retrieve images ??? */
6972                 return;
6973         }
6974
6975         /* Note that the user could have closed the window while connecting */
6976         if (GTK_WIDGET_VISIBLE (parent_window))
6977                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
6978         g_object_unref ((GObject *) user_data);
6979 }
6980
6981 void
6982 modest_ui_actions_on_fetch_images (GtkAction *action,
6983                                    ModestWindow *window)
6984 {
6985         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6986
6987         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
6988                                              NULL,
6989                                              on_fetch_images_performer, 
6990                                              g_object_ref (window));
6991 }
6992
6993 void
6994 modest_ui_actions_on_reload_message (const gchar *msg_id)
6995 {
6996         ModestWindow *window = NULL;
6997
6998         g_return_if_fail (msg_id && msg_id[0] != '\0');
6999         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
7000                                                             msg_id,
7001                                                             &window))
7002                 return;
7003
7004
7005         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
7006                 return;
7007
7008         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
7009 }
7010
7011 /** Check whether any connections are active, and cancel them if 
7012  * the user wishes.
7013  * Returns TRUE is there was no problem, 
7014  * or if an operation was cancelled so we can continue.
7015  * Returns FALSE if the user chose to cancel his request instead.
7016  */
7017
7018 gboolean
7019 modest_ui_actions_check_for_active_account (ModestWindow *self,
7020                                             const gchar* account_name)
7021 {
7022         ModestTnySendQueue *send_queue;
7023         ModestTnyAccountStore *acc_store;
7024         ModestMailOperationQueue* queue;
7025         TnyConnectionStatus store_conn_status;
7026         TnyAccount *store_account = NULL, *transport_account = NULL;
7027         gboolean retval = TRUE, sending = FALSE;
7028
7029         acc_store = modest_runtime_get_account_store ();
7030         queue = modest_runtime_get_mail_operation_queue ();
7031
7032         store_account = 
7033                 modest_tny_account_store_get_server_account (acc_store,
7034                                                              account_name,
7035                                                              TNY_ACCOUNT_TYPE_STORE);
7036
7037         /* This could happen if the account was deleted before the
7038            call to this function */
7039         if (!store_account)
7040                 return FALSE;
7041
7042         transport_account = 
7043                 modest_tny_account_store_get_server_account (acc_store,
7044                                                              account_name,
7045                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
7046
7047         /* This could happen if the account was deleted before the
7048            call to this function */
7049         if (!transport_account) {
7050                 g_object_unref (store_account);
7051                 return FALSE;
7052         }
7053
7054         /* If the transport account was not used yet, then the send
7055            queue could not exist (it's created on demand) */
7056         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
7057         if (TNY_IS_SEND_QUEUE (send_queue))
7058                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
7059
7060         store_conn_status = tny_account_get_connection_status (store_account);
7061         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
7062                 gint response;
7063
7064                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
7065                                                                 _("emev_nc_disconnect_account"));
7066                 if (response == GTK_RESPONSE_OK) {
7067                         retval = TRUE;
7068                 } else {
7069                         retval = FALSE;
7070                 }
7071         }
7072
7073         if (retval) {
7074
7075                 /* FIXME: We should only cancel those of this account */
7076                 modest_mail_operation_queue_cancel_all (queue);
7077
7078                 /* Also disconnect the account */
7079                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
7080                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
7081                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
7082                                                       FALSE, NULL, NULL);
7083                 }
7084                 if (sending) {
7085                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
7086                                                       FALSE, NULL, NULL);
7087                 }
7088         }
7089                 
7090         /* Frees */
7091         g_object_unref (store_account);
7092         g_object_unref (transport_account);
7093         
7094         return retval;
7095 }