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