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