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