Sync the flags of messages read from notifications
[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 (TnyFolder *folder,
2173                 gboolean cancelled,
2174                 GError *err,
2175                 gpointer user_data)
2176 {
2177         ModestHeaderView *header_view = (ModestHeaderView *) user_data;
2178
2179         tny_folder_refresh_async (folder, NULL, NULL, NULL);
2180         /* ModestWindow *parent = (ModestWindow *) gtk_widget_get_ancestor ((GtkWidget *) user_data, GTK_TYPE_WINDOW); */
2181
2182         /* We must clear first, because otherwise set_folder will ignore
2183            the change as the folders are the same */
2184         /* modest_header_view_clear (header_view); */
2185         /* modest_header_view_set_folder (header_view, folder, TRUE, parent, NULL, NULL); */
2186
2187         g_object_unref (header_view);
2188 }
2189
2190 static gboolean
2191 idle_refresh_folder (gpointer source)
2192 {
2193         ModestHeaderView *header_view = NULL;
2194
2195         /* If the window still exists */
2196         if (!GTK_IS_WIDGET (source) ||
2197             !GTK_WIDGET_VISIBLE (source))
2198                 return FALSE;
2199
2200         /* Refresh the current view */
2201 #ifdef MODEST_TOOLKIT_HILDON2
2202         if (MODEST_IS_HEADER_WINDOW (source))
2203                 header_view = modest_header_window_get_header_view ((ModestHeaderWindow *) source);
2204 #else
2205         if (MODEST_IS_MAIN_WINDOW (source))
2206                 header_view = modest_main_window_get_child_widget ((ModestMainWindow *) source,
2207                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2208 #endif
2209         if (header_view) {
2210                 TnyFolder *folder = modest_header_view_get_folder (header_view);
2211                 if (folder) {
2212                         /* Sync the folder status */
2213                         tny_folder_sync_async (folder, TRUE, sync_folder_cb, NULL, g_object_ref (header_view));
2214                         g_object_unref (folder);
2215                 }
2216         }
2217
2218         return FALSE;
2219 }
2220
2221 static void
2222 update_account_cb (ModestMailOperation *self,
2223                    TnyList *new_headers,
2224                    gpointer user_data)
2225 {
2226         GObject *source;
2227         gboolean show_visual_notifications;
2228
2229         source = modest_mail_operation_get_source (self);
2230         show_visual_notifications = (source) ? FALSE : TRUE;
2231
2232         /* Notify new messages have been downloaded. If the
2233            send&receive was invoked by the user then do not show any
2234            visual notification, only play a sound and activate the LED
2235            (for the Maemo version) */
2236         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2237
2238                 /* We only notify about really new messages (not seen) we get */
2239                 TnyList *actually_new_list;
2240                 TnyIterator *iterator;
2241                 actually_new_list = TNY_LIST (tny_simple_list_new ());
2242                 for (iterator = tny_list_create_iterator (new_headers);
2243                      !tny_iterator_is_done (iterator);
2244                      tny_iterator_next (iterator)) {
2245                         TnyHeader *header;
2246                         TnyHeaderFlags flags;
2247                         header = TNY_HEADER (tny_iterator_get_current (iterator));
2248                         flags = tny_header_get_flags (header);
2249
2250                         if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2251                                 /* Messages are ordered from most
2252                                    recent to oldest. But we want to
2253                                    show notifications starting from
2254                                    the oldest message. That's why we
2255                                    reverse the list */
2256                                 tny_list_prepend (actually_new_list, G_OBJECT (header));
2257                         }
2258                         g_object_unref (header);
2259                 }
2260                 g_object_unref (iterator);
2261
2262                 if (tny_list_get_length (actually_new_list) > 0) {
2263                         GList *new_headers_list = NULL;
2264
2265                         new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2266
2267                         /* Send notifications */
2268                         if (new_headers_list) {
2269                                 modest_platform_on_new_headers_received (new_headers_list,
2270                                                                          show_visual_notifications);
2271                                 /* Free the list */
2272                                 modest_utils_free_notification_list (new_headers_list);
2273                         }
2274                 }
2275                 g_object_unref (actually_new_list);
2276         }
2277
2278         if (source) {
2279                 /* Refresh the current folder in an idle. We do this
2280                    in order to avoid refresh cancelations if the
2281                    currently viewed folder is the inbox */
2282                 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
2283                                  idle_refresh_folder,
2284                                  g_object_ref (source),
2285                                  g_object_unref);
2286                 g_object_unref (source);
2287         }
2288 }
2289
2290 typedef struct {
2291         TnyAccount *account;
2292         ModestWindow *win;
2293         gchar *account_name;
2294         gboolean poke_status;
2295         gboolean interactive;
2296         ModestMailOperation *mail_op;
2297 } SendReceiveInfo;
2298
2299 static void
2300 do_send_receive_performer (gboolean canceled,
2301                            GError *err,
2302                            GtkWindow *parent_window,
2303                            TnyAccount *account,
2304                            gpointer user_data)
2305 {
2306         SendReceiveInfo *info;
2307
2308         info = (SendReceiveInfo *) user_data;
2309
2310         if (err || canceled) {
2311                 /* In disk full conditions we could get this error here */
2312                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2313                                                                 (GtkWidget *) parent_window, err,
2314                                                                 account, NULL);
2315
2316                 if (info->mail_op) {
2317                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2318                                                             info->mail_op);
2319                 }
2320                 goto clean;
2321         }
2322
2323 #ifndef MODEST_TOOLKIT_HILDON2
2324         /* Set send/receive operation in progress */
2325         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2326                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2327         }
2328
2329         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2330                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2331                                   G_CALLBACK (on_send_receive_finished),
2332                                   info->win);
2333 #endif
2334
2335         /* Send & receive. */
2336         modest_mail_operation_update_account (info->mail_op, info->account_name,
2337                                               info->poke_status, info->interactive,
2338                                               update_account_cb, info->win);
2339
2340  clean:
2341         /* Frees */
2342         if (info->mail_op)
2343                 g_object_unref (G_OBJECT (info->mail_op));
2344         if (info->account_name)
2345                 g_free (info->account_name);
2346         if (info->win)
2347                 g_object_unref (info->win);
2348         if (info->account)
2349                 g_object_unref (info->account);
2350         g_slice_free (SendReceiveInfo, info);
2351 }
2352
2353 /*
2354  * This function performs the send & receive required actions. The
2355  * window is used to create the mail operation. Typically it should
2356  * always be the main window, but we pass it as argument in order to
2357  * be more flexible.
2358  */
2359 void
2360 modest_ui_actions_do_send_receive (const gchar *account_name,
2361                                    gboolean force_connection,
2362                                    gboolean poke_status,
2363                                    gboolean interactive,
2364                                    ModestWindow *win)
2365 {
2366         gchar *acc_name = NULL;
2367         SendReceiveInfo *info;
2368         ModestTnyAccountStore *acc_store;
2369         TnyAccount *account;
2370
2371         /* If no account name was provided then get the current account, and if
2372            there is no current account then pick the default one: */
2373         if (!account_name) {
2374                 if (win)
2375                         acc_name = g_strdup (modest_window_get_active_account (win));
2376                 if (!acc_name)
2377                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2378                 if (!acc_name) {
2379                         modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2380                         return;
2381                 }
2382         } else {
2383                 acc_name = g_strdup (account_name);
2384         }
2385
2386         acc_store = modest_runtime_get_account_store ();
2387         account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2388
2389         if (!account) {
2390                 g_free (acc_name);
2391                 modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2392                 return;
2393         }
2394
2395         /* Do not automatically refresh accounts that are flagged as
2396            NO_AUTO_UPDATE. This could be useful for accounts that
2397            handle their own update times */
2398         if (!interactive) {
2399                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2400                 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2401                         const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2402                         ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2403
2404                         if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2405                                 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2406                                 g_object_unref (account);
2407                                 g_free (acc_name);
2408                                 return;
2409                         }
2410                 }
2411         }
2412
2413         /* Create the info for the connect and perform */
2414         info = g_slice_new (SendReceiveInfo);
2415         info->account_name = acc_name;
2416         info->win = (win) ? g_object_ref (win) : NULL;
2417         info->poke_status = poke_status;
2418         info->interactive = interactive;
2419         info->account = account;
2420         /* We need to create the operation here, because otherwise it
2421            could happen that the queue emits the queue-empty signal
2422            while we're trying to connect the account */
2423         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2424                                                                        modest_ui_actions_disk_operations_error_handler,
2425                                                                        NULL, NULL);
2426         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2427
2428         /* Invoke the connect and perform */
2429         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2430                                              force_connection, info->account,
2431                                              do_send_receive_performer, info);
2432 }
2433
2434
2435 static void
2436 modest_ui_actions_do_cancel_send (const gchar *account_name,
2437                                   ModestWindow *win)
2438 {
2439         TnyTransportAccount *transport_account;
2440         TnySendQueue *send_queue = NULL;
2441         GError *error = NULL;
2442
2443         /* Get transport account */
2444         transport_account =
2445                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2446                                       (modest_runtime_get_account_store(),
2447                                        account_name,
2448                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2449         if (!transport_account) {
2450                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2451                 goto frees;
2452         }
2453
2454         /* Get send queue*/
2455         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2456         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2457                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2458                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2459                              "modest: could not find send queue for account\n");
2460         } else {
2461                 /* Cancel the current send */
2462                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2463
2464                 /* Suspend all pending messages */
2465                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2466         }
2467
2468  frees:
2469         if (transport_account != NULL)
2470                 g_object_unref (G_OBJECT (transport_account));
2471 }
2472
2473 static void
2474 modest_ui_actions_cancel_send_all (ModestWindow *win)
2475 {
2476         GSList *account_names, *iter;
2477
2478         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2479                                                           TRUE);
2480
2481         iter = account_names;
2482         while (iter) {
2483                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2484                 iter = g_slist_next (iter);
2485         }
2486
2487         modest_account_mgr_free_account_names (account_names);
2488         account_names = NULL;
2489 }
2490
2491 void
2492 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2493
2494 {
2495         /* Check if accounts exist */
2496         gboolean accounts_exist =
2497                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2498
2499         /* If not, allow the user to create an account before trying to send/receive. */
2500         if (!accounts_exist)
2501                 modest_ui_actions_on_accounts (NULL, win);
2502
2503         /* Cancel all sending operaitons */
2504         modest_ui_actions_cancel_send_all (win);
2505 }
2506
2507 /*
2508  * Refreshes all accounts. This function will be used by automatic
2509  * updates
2510  */
2511 void
2512 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2513                                        gboolean force_connection,
2514                                        gboolean poke_status,
2515                                        gboolean interactive)
2516 {
2517         GSList *account_names, *iter;
2518
2519         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2520                                                           TRUE);
2521
2522         iter = account_names;
2523         while (iter) {
2524                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2525                                                    force_connection,
2526                                                    poke_status, interactive, win);
2527                 iter = g_slist_next (iter);
2528         }
2529
2530         modest_account_mgr_free_account_names (account_names);
2531         account_names = NULL;
2532 }
2533
2534 /*
2535  * Handler of the click on Send&Receive button in the main toolbar
2536  */
2537 void
2538 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2539 {
2540         /* Check if accounts exist */
2541         gboolean accounts_exist;
2542
2543         accounts_exist =
2544                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2545
2546         /* If not, allow the user to create an account before trying to send/receive. */
2547         if (!accounts_exist)
2548                 modest_ui_actions_on_accounts (NULL, win);
2549
2550         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2551 #ifndef MODEST_TOOLKIT_HILDON2
2552         if (MODEST_IS_MAIN_WINDOW (win)) {
2553                 GtkWidget *folder_view;
2554                 TnyFolderStore *folder_store;
2555
2556                 folder_view =
2557                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2558                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2559                 if (!folder_view)
2560                         return;
2561
2562                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2563
2564                 if (folder_store)
2565                         g_object_unref (folder_store);
2566                 /* Refresh the active account. Force the connection if needed
2567                    and poke the status of all folders */
2568                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2569 #else
2570         if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2571                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2572 #endif
2573         } else {
2574                 const gchar *active_account;
2575                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2576
2577                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2578         }
2579
2580 }
2581
2582 #ifndef MODEST_TOOLKIT_HILDON2
2583 void
2584 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2585 {
2586         ModestConf *conf;
2587         GtkWidget *header_view;
2588
2589         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2590
2591         header_view = modest_main_window_get_child_widget (main_window,
2592                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2593         if (!header_view)
2594                 return;
2595
2596         conf = modest_runtime_get_conf ();
2597
2598         /* what is saved/restored is depending on the style; thus; we save with
2599          * old style, then update the style, and restore for this new style
2600          */
2601         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2602
2603         if (modest_header_view_get_style
2604             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2605                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2606                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2607         else
2608                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2609                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2610
2611         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2612                                       MODEST_CONF_HEADER_VIEW_KEY);
2613 }
2614
2615 void
2616 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2617                                       TnyHeader *header,
2618                                       ModestMainWindow *main_window)
2619 {
2620         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2621         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2622
2623         /* in the case the folder is empty, show the empty folder message and focus
2624          * folder view */
2625         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2626                 if (modest_header_view_is_empty (header_view)) {
2627                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2628                         GtkWidget *folder_view =
2629                                 modest_main_window_get_child_widget (main_window,
2630                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2631                         if (folder != NULL) {
2632                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2633                                 g_object_unref (folder);
2634                         }
2635                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2636                         return;
2637                 }
2638         }
2639         /* If no header has been selected then exit */
2640         if (!header)
2641                 return;
2642
2643         /* Update focus */
2644         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2645             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2646
2647         /* Update toolbar dimming state */
2648         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2649         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2650 }
2651 #endif
2652
2653 void
2654 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2655                                        TnyHeader *header,
2656                                        GtkTreePath *path,
2657                                        ModestWindow *window)
2658 {
2659         GtkTreeRowReference *rowref;
2660
2661         g_return_if_fail (MODEST_IS_WINDOW(window));
2662         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2663         g_return_if_fail (TNY_IS_HEADER (header));
2664
2665         if (modest_header_view_count_selected_headers (header_view) > 1) {
2666                 /* Don't allow activation if there are more than one message selected */
2667                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2668                 return;
2669         }
2670
2671         /* we check for low-mem; in that case, show a warning, and don't allow
2672          * activating headers
2673          */
2674         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2675                 return;
2676
2677 #ifndef MODEST_TOOLKIT_HILDON2
2678         GtkWidget *open_widget;
2679         if (MODEST_IS_MAIN_WINDOW (window)) {
2680                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2681                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2682                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2683                         return;
2684         }
2685 #endif
2686
2687         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2688         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2689         gtk_tree_row_reference_free (rowref);
2690 }
2691
2692 #ifndef MODEST_TOOLKIT_HILDON2
2693 static void
2694 set_active_account_from_tny_account (TnyAccount *account,
2695                                      ModestWindow *window)
2696 {
2697         const gchar *server_acc_name = tny_account_get_id (account);
2698
2699         /* We need the TnyAccount provided by the
2700            account store because that is the one that
2701            knows the name of the Modest account */
2702         TnyAccount *modest_server_account =
2703                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2704                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2705                                                              server_acc_name);
2706         if (!modest_server_account) {
2707                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2708                 return;
2709         }
2710
2711         /* Update active account, but only if it's not a pseudo-account */
2712         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2713             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2714                 const gchar *modest_acc_name =
2715                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2716                 if (modest_acc_name)
2717                         modest_window_set_active_account (window, modest_acc_name);
2718         }
2719
2720         g_object_unref (modest_server_account);
2721 }
2722
2723 static void
2724 folder_refreshed_cb (ModestMailOperation *mail_op,
2725                      TnyFolder *folder,
2726                      gpointer user_data)
2727 {
2728         ModestMainWindow *win = NULL;
2729         GtkWidget *folder_view, *header_view;
2730         const GError *error;
2731
2732         g_return_if_fail (TNY_IS_FOLDER (folder));
2733
2734         win = MODEST_MAIN_WINDOW (user_data);
2735
2736         /* Check if the operation failed due to memory low conditions */
2737         error = modest_mail_operation_get_error (mail_op);
2738         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2739             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2740                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2741                                                         _KR("memr_ib_operation_disabled"),
2742                                                         TRUE);
2743                 return;
2744         }
2745
2746         folder_view =
2747                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2748         header_view =
2749                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2750
2751         if (folder_view) {
2752                 TnyFolderStore *current_folder;
2753
2754                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2755                 if (current_folder) {
2756                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2757                         g_object_unref (current_folder);
2758                         if (different)
2759                                 return;
2760                 }
2761         }
2762
2763         /* Check if folder is empty and set headers view contents style */
2764         if ((tny_folder_get_all_count (folder) == 0) ||
2765             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2766                 modest_main_window_set_contents_style (win,
2767                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2768 }
2769
2770 void
2771 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2772                                                TnyFolderStore *folder_store,
2773                                                gboolean selected,
2774                                                ModestMainWindow *main_window)
2775 {
2776         GtkWidget *header_view;
2777
2778         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2779
2780         header_view = modest_main_window_get_child_widget(main_window,
2781                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2782         if (!header_view)
2783                 return;
2784
2785
2786         if (TNY_IS_ACCOUNT (folder_store)) {
2787                 if (selected) {
2788                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2789
2790                         /* Show account details */
2791                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2792                 }
2793         } else {
2794                 if (TNY_IS_FOLDER (folder_store) && selected) {
2795                         TnyAccount *account;
2796
2797                         /* Update the active account */
2798                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2799                         if (account) {
2800                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2801                                 g_object_unref (account);
2802                                 account = NULL;
2803                         }
2804
2805                         /* Set the header style by default, it could
2806                            be changed later by the refresh callback to
2807                            empty */
2808                         modest_main_window_set_contents_style (main_window,
2809                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2810
2811                         /* Set folder on header view. This function
2812                            will call tny_folder_refresh_async so we
2813                            pass a callback that will be called when
2814                            finished. We use that callback to set the
2815                            empty view if there are no messages */
2816                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2817                                                        TNY_FOLDER (folder_store),
2818                                                        TRUE,
2819                                                        MODEST_WINDOW (main_window),
2820                                                        folder_refreshed_cb,
2821                                                        main_window);
2822
2823                         /* Restore configuration. We need to do this
2824                            *after* the set_folder because the widget
2825                            memory asks the header view about its
2826                            folder  */
2827                         modest_widget_memory_restore (modest_runtime_get_conf (),
2828                                                       G_OBJECT(header_view),
2829                                                       MODEST_CONF_HEADER_VIEW_KEY);
2830                 } else {
2831                         /* No need to save the header view
2832                            configuration for Maemo because it only
2833                            saves the sorting stuff and that it's
2834                            already being done by the sort
2835                            dialog. Remove it when the GNOME version
2836                            has the same behaviour */
2837 #ifdef MODEST_TOOLKIT_GTK
2838                         if (modest_main_window_get_contents_style (main_window) ==
2839                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2840                                 modest_widget_memory_save (modest_runtime_get_conf (), 
2841                                                            G_OBJECT (header_view),
2842                                                            MODEST_CONF_HEADER_VIEW_KEY);
2843 #endif
2844                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2845                 }
2846         }
2847
2848         /* Update dimming state */
2849         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2850         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2851 }
2852 #endif
2853
2854 void
2855 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2856                                      ModestWindow *win)
2857 {
2858         GtkWidget *dialog;
2859         gchar *txt, *item;
2860         gboolean online;
2861
2862         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2863
2864         online = tny_device_is_online (modest_runtime_get_device());
2865
2866         if (online) {
2867                 /* already online -- the item is simply not there... */
2868                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2869                                                  GTK_DIALOG_MODAL,
2870                                                  GTK_MESSAGE_WARNING,
2871                                                  GTK_BUTTONS_NONE,
2872                                                  _("The %s you selected cannot be found"),
2873                                                  item);
2874                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2875                 gtk_dialog_run (GTK_DIALOG(dialog));
2876         } else {
2877                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2878                                                       GTK_WINDOW (win),
2879                                                       GTK_DIALOG_MODAL,
2880                                                       _("mcen_bd_dialog_cancel"),
2881                                                       GTK_RESPONSE_REJECT,
2882                                                       _("mcen_bd_dialog_ok"),
2883                                                       GTK_RESPONSE_ACCEPT,
2884                                                       NULL);
2885                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2886                                          "Do you want to get online?"), item);
2887                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2888                                     gtk_label_new (txt), FALSE, FALSE, 0);
2889                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2890                 g_free (txt);
2891
2892                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2893                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2894                         /* TODO: Comment about why is this commented out: */
2895                         /* modest_platform_connect_and_wait (); */
2896                 }
2897         }
2898         gtk_widget_destroy (dialog);
2899 }
2900
2901 void
2902 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2903                                      ModestWindow *win)
2904 {
2905         /* g_debug ("%s %s", __FUNCTION__, link); */
2906 }
2907
2908
2909 void
2910 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2911                                         ModestWindow *win)
2912 {
2913         modest_platform_activate_uri (link);
2914 }
2915
2916 void
2917 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2918                                           ModestWindow *win)
2919 {
2920         modest_platform_show_uri_popup (link);
2921 }
2922
2923 void
2924 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2925                                              ModestWindow *win)
2926 {
2927         /* we check for low-mem; in that case, show a warning, and don't allow
2928          * viewing attachments
2929          */
2930         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2931                 return;
2932
2933         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2934 }
2935
2936 void
2937 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2938                                           const gchar *address,
2939                                           ModestWindow *win)
2940 {
2941         /* g_debug ("%s %s", __FUNCTION__, address); */
2942 }
2943
2944 static void
2945 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2946                       TnyMsg *saved_draft,
2947                       gpointer user_data)
2948 {
2949         ModestMsgEditWindow *edit_window;
2950
2951         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2952 #ifndef MODEST_TOOLKIT_HILDON2
2953         ModestMainWindow *win;
2954
2955         /* FIXME. Make the header view sensitive again. This is a
2956          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2957          * for details */
2958         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2959                                          modest_runtime_get_window_mgr(), FALSE));
2960         if (win != NULL) {
2961                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2962                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2963                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2964         }
2965 #endif
2966
2967         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2968
2969         /* Set draft is there was no error */
2970         if (!modest_mail_operation_get_error (mail_op))
2971                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2972
2973         g_object_unref(edit_window);
2974 }
2975
2976 static gboolean
2977 enough_space_for_message (ModestMsgEditWindow *edit_window,
2978                           MsgData *data)
2979 {
2980         guint64 available_disk, expected_size;
2981         gint parts_count;
2982         guint64 parts_size;
2983
2984         /* Check size */
2985         available_disk = modest_utils_get_available_space (NULL);
2986         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2987         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2988                                                       data->html_body,
2989                                                       parts_count,
2990                                                       parts_size);
2991
2992         /* Double check: disk full condition or message too big */
2993         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
2994             expected_size > available_disk) {
2995                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2996                 modest_platform_information_banner (NULL, NULL, msg);
2997                 g_free (msg);
2998
2999                 return FALSE;
3000         }
3001
3002         /*
3003          * djcb: if we're in low-memory state, we only allow for
3004          * saving messages smaller than
3005          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
3006          * should still allow for sending anything critical...
3007          */
3008         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
3009             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
3010                 return FALSE;
3011
3012         /*
3013          * djcb: we also make sure that the attachments are smaller than the max size
3014          * this is for the case where we'd try to forward a message with attachments
3015          * bigger than our max allowed size, or sending an message from drafts which
3016          * somehow got past our checks when attaching.
3017          */
3018         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
3019                 modest_platform_run_information_dialog (
3020                         GTK_WINDOW(edit_window),
3021                         _("mail_ib_error_attachment_size"),
3022                         TRUE);
3023                 return FALSE;
3024         }
3025
3026         return TRUE;
3027 }
3028
3029 gboolean
3030 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3031 {
3032         TnyTransportAccount *transport_account;
3033         ModestMailOperation *mail_operation;
3034         MsgData *data;
3035         gchar *account_name;
3036         ModestAccountMgr *account_mgr;
3037         gboolean had_error = FALSE;
3038
3039         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
3040
3041         data = modest_msg_edit_window_get_msg_data (edit_window);
3042
3043         /* Check size */
3044         if (!enough_space_for_message (edit_window, data)) {
3045                 modest_msg_edit_window_free_msg_data (edit_window, data);
3046                 return FALSE;
3047         }
3048
3049         account_name = g_strdup (data->account_name);
3050         account_mgr = modest_runtime_get_account_mgr();
3051         if (!account_name)
3052                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3053         if (!account_name)
3054                 account_name = modest_account_mgr_get_default_account (account_mgr);
3055         if (!account_name) {
3056                 g_printerr ("modest: no account found\n");
3057                 modest_msg_edit_window_free_msg_data (edit_window, data);
3058                 return FALSE;
3059         }
3060
3061         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
3062                 account_name = g_strdup (data->account_name);
3063         }
3064
3065         transport_account =
3066                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3067                                       (modest_runtime_get_account_store (),
3068                                        account_name,
3069                                        TNY_ACCOUNT_TYPE_TRANSPORT));
3070         if (!transport_account) {
3071                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
3072                 g_free (account_name);
3073                 modest_msg_edit_window_free_msg_data (edit_window, data);
3074                 return FALSE;
3075         }
3076
3077         /* Create the mail operation */
3078         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
3079                                                                         NULL, NULL);
3080         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3081
3082         modest_mail_operation_save_to_drafts (mail_operation,
3083                                               transport_account,
3084                                               data->draft_msg,
3085                                               data->from,
3086                                               data->to, 
3087                                               data->cc, 
3088                                               data->bcc,
3089                                               data->subject,
3090                                               data->plain_body,
3091                                               data->html_body,
3092                                               data->attachments,
3093                                               data->images,
3094                                               data->priority_flags,
3095                                               data->references,
3096                                               data->in_reply_to,
3097                                               on_save_to_drafts_cb,
3098                                               g_object_ref(edit_window));
3099
3100 #ifdef MODEST_TOOLKIT_HILDON2
3101         /* In hildon2 we always show the information banner on saving to drafts.
3102          * It will be a system information banner in this case.
3103          */
3104         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3105         modest_platform_information_banner (NULL, NULL, text);
3106         g_free (text);
3107 #else
3108         ModestMainWindow *win = NULL;
3109
3110         /* Use the main window as the parent of the banner, if the
3111            main window does not exist it won't be shown, if the parent
3112            window exists then it's properly shown. We don't use the
3113            editor window because it could be closed (save to drafts
3114            could happen after closing the window */
3115         win = (ModestMainWindow *)
3116                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3117         if (win) {
3118                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3119                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3120                 g_free (text);
3121         }
3122 #endif
3123         modest_msg_edit_window_set_modified (edit_window, FALSE);
3124
3125         /* Frees */
3126         g_free (account_name);
3127         g_object_unref (G_OBJECT (transport_account));
3128         g_object_unref (G_OBJECT (mail_operation));
3129
3130         modest_msg_edit_window_free_msg_data (edit_window, data);
3131
3132 #ifndef MODEST_TOOLKIT_HILDON2
3133         /* ** FIXME **
3134          * If the drafts folder is selected then make the header view
3135          * insensitive while the message is being saved to drafts
3136          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3137          * is not very clean but it avoids letting the drafts folder
3138          * in an inconsistent state: the user could edit the message
3139          * being saved and undesirable things would happen.
3140          * In the average case the user won't notice anything at
3141          * all. In the worst case (the user is editing a really big
3142          * file from Drafts) the header view will be insensitive
3143          * during the saving process (10 or 20 seconds, depending on
3144          * the message). Anyway this is just a quick workaround: once
3145          * we find a better solution it should be removed
3146          * See NB#65125 (commend #18) for details.
3147          */
3148         if (!had_error && win != NULL) {
3149                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3150                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3151                 if (view != NULL) {
3152                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3153                         if (folder) {
3154                                 if (modest_tny_folder_is_local_folder(folder)) {
3155                                         TnyFolderType folder_type;
3156                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3157                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3158                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3159                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3160                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3161                                         }
3162                                 }
3163                         }
3164                         if (folder != NULL) g_object_unref(folder);
3165                 }
3166         }
3167 #endif
3168
3169         return !had_error;
3170 }
3171
3172 /* For instance, when clicking the Send toolbar button when editing a message: */
3173 gboolean
3174 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3175 {
3176         TnyTransportAccount *transport_account = NULL;
3177         gboolean had_error = FALSE;
3178         MsgData *data;
3179         ModestAccountMgr *account_mgr;
3180         gchar *account_name;
3181         ModestMailOperation *mail_operation;
3182         gchar *recipients;
3183
3184         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3185
3186         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
3187                 return TRUE;
3188
3189         data = modest_msg_edit_window_get_msg_data (edit_window);
3190
3191         recipients = g_strconcat (data->to?data->to:"", 
3192                                   data->cc?data->cc:"",
3193                                   data->bcc?data->bcc:"",
3194                                   NULL);
3195         if (recipients == NULL || recipients[0] == '\0') {
3196                 /* Empty subject -> no send */
3197                 g_free (recipients);
3198                 modest_msg_edit_window_free_msg_data (edit_window, data);
3199                 return FALSE;
3200         }
3201         g_free (recipients);
3202
3203         /* Check size */
3204         if (!enough_space_for_message (edit_window, data)) {
3205                 modest_msg_edit_window_free_msg_data (edit_window, data);
3206                 return FALSE;
3207         }
3208
3209         account_mgr = modest_runtime_get_account_mgr();
3210         account_name = g_strdup (data->account_name);
3211         if (!account_name)
3212                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3213
3214         if (!account_name)
3215                 account_name = modest_account_mgr_get_default_account (account_mgr);
3216
3217         if (!account_name) {
3218                 modest_msg_edit_window_free_msg_data (edit_window, data);
3219                 /* Run account setup wizard */
3220                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3221                         return TRUE;
3222                 }
3223         }
3224
3225         /* Get the currently-active transport account for this modest account: */
3226         if (account_name && strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3227                 transport_account =
3228                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3229                                               (modest_runtime_get_account_store (),
3230                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3231         }
3232
3233         if (!transport_account) {
3234                 modest_msg_edit_window_free_msg_data (edit_window, data);
3235                 /* Run account setup wizard */
3236                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3237                         return TRUE;
3238         }
3239
3240
3241         /* Create the mail operation */
3242         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3243         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3244
3245         modest_mail_operation_send_new_mail (mail_operation,
3246                                              transport_account,
3247                                              data->draft_msg,
3248                                              data->from,
3249                                              data->to,
3250                                              data->cc,
3251                                              data->bcc,
3252                                              data->subject,
3253                                              data->plain_body,
3254                                              data->html_body,
3255                                              data->attachments,
3256                                              data->images,
3257                                              data->references,
3258                                              data->in_reply_to,
3259                                              data->priority_flags);
3260
3261         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3262                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3263
3264         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3265                 const GError *error = modest_mail_operation_get_error (mail_operation);
3266                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3267                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3268                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3269                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3270                         had_error = TRUE;
3271                 }
3272         }
3273
3274         /* Free data: */
3275         g_free (account_name);
3276         g_object_unref (G_OBJECT (transport_account));
3277         g_object_unref (G_OBJECT (mail_operation));
3278
3279         modest_msg_edit_window_free_msg_data (edit_window, data);
3280
3281         if (!had_error) {
3282                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3283
3284                 /* Save settings and close the window: */
3285                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3286         }
3287
3288         return !had_error;
3289 }
3290
3291 void
3292 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3293                                   ModestMsgEditWindow *window)
3294 {
3295         ModestMsgEditFormatState *format_state = NULL;
3296
3297         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3298         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3299
3300         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3301                 return;
3302
3303         format_state = modest_msg_edit_window_get_format_state (window);
3304         g_return_if_fail (format_state != NULL);
3305
3306         format_state->bold = gtk_toggle_action_get_active (action);
3307         modest_msg_edit_window_set_format_state (window, format_state);
3308         g_free (format_state);
3309
3310 }
3311
3312 void
3313 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3314                                      ModestMsgEditWindow *window)
3315 {
3316         ModestMsgEditFormatState *format_state = NULL;
3317
3318         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3319         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3320
3321         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3322                 return;
3323
3324         format_state = modest_msg_edit_window_get_format_state (window);
3325         g_return_if_fail (format_state != NULL);
3326
3327         format_state->italics = gtk_toggle_action_get_active (action);
3328         modest_msg_edit_window_set_format_state (window, format_state);
3329         g_free (format_state);
3330
3331 }
3332
3333 void
3334 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3335                                      ModestMsgEditWindow *window)
3336 {
3337         ModestMsgEditFormatState *format_state = NULL;
3338
3339         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3340         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3341
3342         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3343                 return;
3344
3345         format_state = modest_msg_edit_window_get_format_state (window);
3346         g_return_if_fail (format_state != NULL);
3347
3348         format_state->bullet = gtk_toggle_action_get_active (action);
3349         modest_msg_edit_window_set_format_state (window, format_state);
3350         g_free (format_state);
3351
3352 }
3353
3354 void
3355 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3356                                      GtkRadioAction *selected,
3357                                      ModestMsgEditWindow *window)
3358 {
3359         ModestMsgEditFormatState *format_state = NULL;
3360         GtkJustification value;
3361
3362         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3363
3364         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3365                 return;
3366
3367         value = gtk_radio_action_get_current_value (selected);
3368
3369         format_state = modest_msg_edit_window_get_format_state (window);
3370         g_return_if_fail (format_state != NULL);
3371
3372         format_state->justification = value;
3373         modest_msg_edit_window_set_format_state (window, format_state);
3374         g_free (format_state);
3375 }
3376
3377 void
3378 modest_ui_actions_on_select_editor_color (GtkAction *action,
3379                                           ModestMsgEditWindow *window)
3380 {
3381         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3382         g_return_if_fail (GTK_IS_ACTION (action));
3383
3384         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3385                 return;
3386
3387         modest_msg_edit_window_select_color (window);
3388 }
3389
3390 void
3391 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3392                                                      ModestMsgEditWindow *window)
3393 {
3394         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3395         g_return_if_fail (GTK_IS_ACTION (action));
3396
3397         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3398                 return;
3399
3400         modest_msg_edit_window_select_background_color (window);
3401 }
3402
3403 void
3404 modest_ui_actions_on_insert_image (GObject *object,
3405                                    ModestMsgEditWindow *window)
3406 {
3407         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3408
3409
3410         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3411                 return;
3412
3413         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3414                 return;
3415
3416         modest_msg_edit_window_insert_image (window);
3417 }
3418
3419 void
3420 modest_ui_actions_on_attach_file (GtkAction *action,
3421                                   ModestMsgEditWindow *window)
3422 {
3423         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3424         g_return_if_fail (GTK_IS_ACTION (action));
3425
3426         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3427                 return;
3428
3429         modest_msg_edit_window_offer_attach_file (window);
3430 }
3431
3432 void
3433 modest_ui_actions_on_remove_attachments (GtkAction *action,
3434                                          ModestMsgEditWindow *window)
3435 {
3436         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3437
3438         modest_msg_edit_window_remove_attachments (window, NULL);
3439 }
3440
3441 static void
3442 do_create_folder_cb (ModestMailOperation *mail_op,
3443                      TnyFolderStore *parent_folder,
3444                      TnyFolder *new_folder,
3445                      gpointer user_data)
3446 {
3447         gchar *suggested_name = (gchar *) user_data;
3448         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3449         const GError *error;
3450
3451         error = modest_mail_operation_get_error (mail_op);
3452         if (error) {
3453                 gboolean disk_full = FALSE;
3454                 TnyAccount *account;
3455                 /* Show an error. If there was some problem writing to
3456                    disk, show it, otherwise show the generic folder
3457                    create error. We do it here and not in an error
3458                    handler because the call to do_create_folder will
3459                    stop the main loop in a gtk_dialog_run and then,
3460                    the message won't be shown until that dialog is
3461                    closed */
3462                 account = modest_mail_operation_get_account (mail_op);
3463                 if (account) {
3464                         disk_full =
3465                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3466                                                                                 (GtkWidget *) source_win,
3467                                                                                 (GError *) error,
3468                                                                                 account,
3469                                                                                 _("mail_in_ui_folder_create_error_memory"));
3470                         g_object_unref (account);
3471                 }
3472                 if (!disk_full) {
3473                         /* Show an error and try again if there is no
3474                            full memory condition */
3475                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3476                                                             _("mail_in_ui_folder_create_error"));
3477                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3478                 }
3479
3480         } else {
3481                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3482                  * FIXME: any other? */
3483                 GtkWidget *folder_view;
3484
3485 #ifndef MODEST_TOOLKIT_HILDON2
3486                 if (MODEST_IS_MAIN_WINDOW(source_win))
3487                         folder_view =
3488                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3489                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3490                 else
3491 #endif
3492                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3493                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3494
3495                 /* Select the newly created folder. It could happen
3496                    that the widget is no longer there (i.e. the window
3497                    has been destroyed, so we need to check this */
3498                 if (folder_view)
3499                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3500                                                           new_folder, FALSE);
3501                 g_object_unref (new_folder);
3502         }
3503         /* Free. Note that the first time it'll be NULL so noop */
3504         g_free (suggested_name);
3505         g_object_unref (source_win);
3506 }
3507
3508 typedef struct {
3509         gchar *folder_name;
3510         TnyFolderStore *parent;
3511 } CreateFolderConnect;
3512
3513 static void
3514 do_create_folder_performer (gboolean canceled,
3515                          GError *err,
3516                          GtkWindow *parent_window,
3517                          TnyAccount *account,
3518                          gpointer user_data)
3519 {
3520         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3521         ModestMailOperation *mail_op;
3522
3523         if (canceled || err) {
3524                 /* In disk full conditions we could get this error here */
3525                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3526                                                                 (GtkWidget *) parent_window, err,
3527                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
3528
3529                 /* This happens if we have selected the outbox folder
3530                    as the parent */
3531                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3532                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3533                         /* Show an error and retry */
3534                         modest_platform_information_banner ((GtkWidget *) parent_window,
3535                                                             NULL,
3536                                                             _("mail_in_ui_folder_create_error"));
3537
3538                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3539                 }
3540
3541                 goto frees;
3542         }
3543
3544         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3545         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3546                                          mail_op);
3547         modest_mail_operation_create_folder (mail_op,
3548                                              helper->parent,
3549                                              (const gchar *) helper->folder_name,
3550                                              do_create_folder_cb,
3551                                              g_strdup (helper->folder_name));
3552         g_object_unref (mail_op);
3553
3554  frees:
3555         if (helper->parent)
3556                 g_object_unref (helper->parent);
3557         if (helper->folder_name)
3558                 g_free (helper->folder_name);
3559         g_slice_free (CreateFolderConnect, helper);
3560 }
3561
3562
3563 static void
3564 do_create_folder (GtkWindow *parent_window,
3565                   TnyFolderStore *suggested_parent,
3566                   const gchar *suggested_name)
3567 {
3568         gint result;
3569         gchar *folder_name = NULL;
3570         TnyFolderStore *parent_folder = NULL;
3571
3572         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3573                                                         suggested_parent,
3574                                                         (gchar *) suggested_name,
3575                                                         &folder_name,
3576                                                         &parent_folder);
3577
3578         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3579                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3580                 helper->folder_name = g_strdup (folder_name);
3581                 helper->parent = g_object_ref (parent_folder);
3582
3583                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3584                                                                TRUE,
3585                                                                parent_folder,
3586                                                                do_create_folder_performer,
3587                                                                helper);
3588         }
3589
3590         if (folder_name)
3591                 g_free (folder_name);
3592         if (parent_folder)
3593                 g_object_unref (parent_folder);
3594 }
3595
3596 static void
3597 modest_ui_actions_create_folder(GtkWidget *parent_window,
3598                                 GtkWidget *folder_view,
3599                                 TnyFolderStore *parent_folder)
3600 {
3601         if (!parent_folder) {
3602 #ifdef MODEST_TOOLKIT_HILDON2
3603                 ModestTnyAccountStore *acc_store;
3604
3605                 acc_store = modest_runtime_get_account_store ();
3606
3607                 parent_folder = (TnyFolderStore *)
3608                         modest_tny_account_store_get_local_folders_account (acc_store);
3609 #else
3610                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3611 #endif
3612         }
3613
3614         if (parent_folder) {
3615                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3616                 g_object_unref (parent_folder);
3617         }
3618 }
3619
3620 void
3621 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3622 {
3623
3624         g_return_if_fail (MODEST_IS_WINDOW(window));
3625
3626 #ifndef MODEST_TOOLKIT_HILDON2
3627         if (MODEST_IS_MAIN_WINDOW (window)) {
3628                 GtkWidget *folder_view;
3629
3630                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3631                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3632                 if (!folder_view)
3633                         return;
3634
3635                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3636 #else
3637         if (MODEST_IS_FOLDER_WINDOW (window)) {
3638                 GtkWidget *folder_view;
3639
3640                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3641                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3642 #endif
3643         } else {
3644                 g_assert_not_reached ();
3645         }
3646 }
3647
3648 static void
3649 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3650                                                gpointer user_data)
3651 {
3652         const GError *error = NULL;
3653         gchar *message = NULL;
3654         gboolean mem_full;
3655         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3656
3657         /* Get error message */
3658         error = modest_mail_operation_get_error (mail_op);
3659         if (!error)
3660                 g_return_if_reached ();
3661
3662         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3663                                                                 (GError *) error, account);
3664         if (mem_full) {
3665                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3666         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3667                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3668                 message = _CS("ckdg_ib_folder_already_exists");
3669         } else if (error->domain == TNY_ERROR_DOMAIN &&
3670                    error->code == TNY_SERVICE_ERROR_STATE) {
3671                 /* This means that the folder is already in use (a
3672                    message is opened for example */
3673                 message = _("emev_ni_internal_error");
3674         } else {
3675                 message = _CS("ckdg_ib_unable_to_rename");
3676         }
3677
3678         /* We don't set a parent for the dialog because the dialog
3679            will be destroyed so the banner won't appear */
3680         modest_platform_information_banner (NULL, NULL, message);
3681
3682         if (account)
3683                 g_object_unref (account);
3684         if (mem_full)
3685                 g_free (message);
3686 }
3687
3688 typedef struct {
3689         TnyFolderStore *folder;
3690         gchar *new_name;
3691 } RenameFolderInfo;
3692
3693 static void
3694 on_rename_folder_cb (ModestMailOperation *mail_op,
3695                      TnyFolder *new_folder,
3696                      gpointer user_data)
3697 {
3698         ModestFolderView *folder_view;
3699
3700         /* If the window was closed when renaming a folder, or if
3701          * it's not a main window this will happen */
3702         if (!MODEST_IS_FOLDER_VIEW (user_data))
3703                 return;
3704
3705         folder_view = MODEST_FOLDER_VIEW (user_data);
3706         /* Note that if the rename fails new_folder will be NULL */
3707         if (new_folder) {
3708                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3709 #ifndef MODEST_TOOLKIT_HILDON2
3710         } else {
3711                 modest_folder_view_select_first_inbox_or_local (folder_view);
3712 #endif
3713         }
3714         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3715 }
3716
3717 static void
3718 on_rename_folder_performer (gboolean canceled,
3719                             GError *err,
3720                             GtkWindow *parent_window,
3721                             TnyAccount *account,
3722                             gpointer user_data)
3723 {
3724         ModestMailOperation *mail_op = NULL;
3725         GtkTreeSelection *sel = NULL;
3726         GtkWidget *folder_view = NULL;
3727         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3728
3729         if (canceled || err) {
3730                 /* In disk full conditions we could get this error here */
3731                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3732                                                                 (GtkWidget *) parent_window, err,
3733                                                                 account, NULL);
3734         } else {
3735
3736                 mail_op =
3737                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3738                                         modest_ui_actions_rename_folder_error_handler,
3739                                         parent_window, NULL);
3740
3741                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3742                                 mail_op);
3743 #ifndef MODEST_TOOLKIT_HILDON2
3744                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3745
3746                         folder_view = modest_main_window_get_child_widget (
3747                                 MODEST_MAIN_WINDOW (parent_window),
3748                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3749                 }
3750 #else
3751                 if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3752                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3753                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3754                 }
3755 #endif
3756
3757                 /* Clear the folders view */
3758                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3759                 gtk_tree_selection_unselect_all (sel);
3760
3761                 /* Actually rename the folder */
3762                 modest_mail_operation_rename_folder (mail_op,
3763                                                      TNY_FOLDER (data->folder),
3764                                                      (const gchar *) (data->new_name),
3765                                                      on_rename_folder_cb,
3766                                                      folder_view);
3767                 g_object_unref (mail_op);
3768         }
3769
3770         g_object_unref (data->folder);
3771         g_free (data->new_name);
3772         g_free (data);
3773 }
3774
3775 void
3776 modest_ui_actions_on_rename_folder (GtkAction *action,
3777                                      ModestWindow *window)
3778 {
3779         modest_ui_actions_on_edit_mode_rename_folder (window);
3780 }
3781
3782 gboolean
3783 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3784 {
3785         TnyFolderStore *folder;
3786         GtkWidget *folder_view;
3787         gboolean do_rename = TRUE;
3788
3789         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3790
3791 #ifndef MODEST_TOOLKIT_HILDON2
3792         if (MODEST_IS_MAIN_WINDOW (window)) {
3793                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3794                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3795                 if (!folder_view)
3796                         return FALSE;
3797 #else
3798         if (MODEST_IS_FOLDER_WINDOW (window)) {
3799                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3800 #endif
3801         } else {
3802                 return FALSE;
3803         }
3804
3805         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3806
3807         if (!folder)
3808                 return FALSE;
3809
3810         if (TNY_IS_FOLDER (folder)) {
3811                 gchar *folder_name = NULL;
3812                 gint response;
3813                 const gchar *current_name;
3814                 TnyFolderStore *parent;
3815
3816                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3817                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3818                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3819                                                                      parent, current_name,
3820                                                                      &folder_name);
3821                 g_object_unref (parent);
3822
3823                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3824                         do_rename = FALSE;
3825                 } else {
3826                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3827                         rename_folder_data->folder = g_object_ref (folder);
3828                         rename_folder_data->new_name = folder_name;
3829                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3830                                         folder, on_rename_folder_performer, rename_folder_data);
3831                 }
3832         }
3833         g_object_unref (folder);
3834         return do_rename;
3835 }
3836
3837 static void
3838 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3839                                                gpointer user_data)
3840 {
3841         GObject *win = modest_mail_operation_get_source (mail_op);
3842
3843         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3844                                                 _("mail_in_ui_folder_delete_error"),
3845                                                 FALSE);
3846         g_object_unref (win);
3847 }
3848
3849 typedef struct {
3850         TnyFolderStore *folder;
3851         gboolean move_to_trash;
3852 } DeleteFolderInfo;
3853
3854 static void
3855 on_delete_folder_cb (gboolean canceled,
3856                   GError *err,
3857                   GtkWindow *parent_window,
3858                   TnyAccount *account,
3859                   gpointer user_data)
3860 {
3861         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3862         GtkWidget *folder_view;
3863         ModestMailOperation *mail_op;
3864         GtkTreeSelection *sel;
3865
3866         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3867                 /* Note that the connection process can fail due to
3868                    memory low conditions as it can not successfully
3869                    store the summary */
3870                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3871                                                                      (GtkWidget*) parent_window, err,
3872                                                                      account, NULL))
3873                         g_debug ("Error connecting when trying to delete a folder");
3874                 g_object_unref (G_OBJECT (info->folder));
3875                 g_free (info);
3876                 return;
3877         }
3878
3879 #ifndef MODEST_TOOLKIT_HILDON2
3880         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3881                 folder_view = modest_main_window_get_child_widget (
3882                         MODEST_MAIN_WINDOW (parent_window),
3883                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3884 #else
3885         if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3886                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3887 #endif
3888         } else {
3889                 g_object_unref (G_OBJECT (info->folder));
3890                 g_free (info);
3891                 return;
3892         }
3893
3894         /* Unselect the folder before deleting it to free the headers */
3895         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3896         gtk_tree_selection_unselect_all (sel);
3897
3898         /* Create the mail operation */
3899         mail_op =
3900                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3901                                 modest_ui_actions_delete_folder_error_handler,
3902                                 NULL, NULL);
3903
3904         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3905                         mail_op);
3906         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3907
3908 #ifndef MODEST_TOOLKIT_HILDON2
3909         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3910 #endif
3911
3912         g_object_unref (mail_op);
3913         g_object_unref (info->folder);
3914         g_free (info);
3915 }
3916
3917 static gboolean
3918 delete_folder (ModestWindow *window, gboolean move_to_trash)
3919 {
3920         TnyFolderStore *folder;
3921         GtkWidget *folder_view;
3922         gint response;
3923         gchar *message;
3924
3925         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3926
3927 #ifndef MODEST_TOOLKIT_HILDON2
3928         if (MODEST_IS_MAIN_WINDOW (window)) {
3929
3930                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3931                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3932 #else
3933         if (MODEST_IS_FOLDER_WINDOW (window)) {
3934                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3935 #endif
3936         } else {
3937                 return FALSE;
3938         }
3939         if (!folder_view)
3940                 return FALSE;
3941
3942         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3943
3944         if (!folder)
3945                 return FALSE;
3946
3947         /* Show an error if it's an account */
3948         if (!TNY_IS_FOLDER (folder)) {
3949                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3950                                                         _("mail_in_ui_folder_delete_error"),
3951                                                         FALSE);
3952                 g_object_unref (G_OBJECT (folder));
3953                 return FALSE;
3954         }
3955
3956         /* Ask the user */
3957         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3958                                     tny_folder_get_name (TNY_FOLDER (folder)));
3959         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3960                                                             (const gchar *) message);
3961         g_free (message);
3962
3963         if (response == GTK_RESPONSE_OK) {
3964                 TnyAccount *account = NULL;
3965                 DeleteFolderInfo *info = NULL;
3966                 info = g_new0(DeleteFolderInfo, 1);
3967                 info->folder = g_object_ref (folder);
3968                 info->move_to_trash = move_to_trash;
3969
3970                 account = tny_folder_get_account (TNY_FOLDER (folder));
3971                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3972                                                                TRUE,
3973                                                                TNY_FOLDER_STORE (account),
3974                                                                on_delete_folder_cb, info);
3975                 g_object_unref (account);
3976                 g_object_unref (folder);
3977                 return TRUE;
3978         } else {
3979                 return FALSE;
3980         }
3981 }
3982
3983 void
3984 modest_ui_actions_on_delete_folder (GtkAction *action,
3985                                     ModestWindow *window)
3986 {
3987         modest_ui_actions_on_edit_mode_delete_folder (window);
3988 }
3989
3990 gboolean
3991 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3992 {
3993         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3994
3995         return delete_folder (window, FALSE);
3996 }
3997
3998 #ifndef MODEST_TOOLKIT_HILDON2
3999 void
4000 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
4001 {
4002         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4003
4004         delete_folder (MODEST_WINDOW (main_window), TRUE);
4005 }
4006 #endif
4007
4008 typedef struct _PasswordDialogFields {
4009         GtkWidget *username;
4010         GtkWidget *password;
4011         GtkWidget *dialog;
4012 } PasswordDialogFields;
4013
4014 static void
4015 password_dialog_check_field (GtkEditable *editable,
4016                              PasswordDialogFields *fields)
4017 {
4018         const gchar *value;
4019         gboolean any_value_empty = FALSE;
4020
4021 #ifdef MODEST_TOOLKIT_HILDON2
4022         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
4023 #else
4024         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
4025 #endif
4026         if ((value == NULL) || value[0] == '\0') {
4027                 any_value_empty = TRUE;
4028         }
4029 #ifdef MODEST_TOOLKIT_HILDON2
4030         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
4031 #else
4032         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
4033 #endif
4034         if ((value == NULL) || value[0] == '\0') {
4035                 any_value_empty = TRUE;
4036         }
4037         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
4038 }
4039
4040 void
4041 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
4042                                          const gchar* server_account_name,
4043                                          gchar **username,
4044                                          gchar **password,
4045                                          gboolean *cancel,
4046                                          gboolean *remember,
4047                                          ModestMainWindow *main_window)
4048 {
4049         g_return_if_fail(server_account_name);
4050         gboolean completed = FALSE;
4051         PasswordDialogFields *fields = NULL;
4052
4053         /* Initalize output parameters: */
4054         if (cancel)
4055                 *cancel = FALSE;
4056
4057         if (remember)
4058                 *remember = TRUE;
4059
4060 #ifndef MODEST_TOOLKIT_GTK
4061         /* Maemo uses a different (awkward) button order,
4062          * It should probably just use gtk_alternative_dialog_button_order ().
4063          */
4064 #ifdef MODEST_TOOLKIT_HILDON2
4065         GtkWidget *dialog =
4066                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4067                                              NULL,
4068                                              GTK_DIALOG_MODAL,
4069                                              _HL("wdgt_bd_done"),
4070                                              GTK_RESPONSE_ACCEPT,
4071                                              NULL);
4072         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
4073                                         HILDON_MARGIN_DOUBLE);
4074 #else
4075         GtkWidget *dialog =
4076                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4077                                              NULL,
4078                                              GTK_DIALOG_MODAL,
4079                                              _("mcen_bd_dialog_ok"),
4080                                              GTK_RESPONSE_ACCEPT,
4081                                              _("mcen_bd_dialog_cancel"),
4082                                              GTK_RESPONSE_REJECT,
4083                                              NULL);
4084 #endif /* MODEST_TOOLKIT_HILDON2 */
4085 #else
4086         GtkWidget *dialog =
4087                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4088                                              NULL,
4089                                              GTK_DIALOG_MODAL,
4090                                              GTK_STOCK_CANCEL,
4091                                              GTK_RESPONSE_REJECT,
4092                                              GTK_STOCK_OK,
4093                                              GTK_RESPONSE_ACCEPT,
4094                                              NULL);
4095 #endif /* MODEST_TOOLKIT_GTK */
4096
4097         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
4098
4099         gchar *server_name = modest_account_mgr_get_server_account_hostname (
4100                 modest_runtime_get_account_mgr(), server_account_name);
4101         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
4102                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
4103                 if (cancel)
4104                         *cancel = TRUE;
4105                 gtk_widget_destroy (dialog);
4106                 return;
4107         }
4108
4109         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4110         GtkWidget *label = gtk_label_new (txt);
4111         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4112         g_free (txt);
4113         g_free (server_name);
4114         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4115                             FALSE, FALSE, 0);
4116         server_name = NULL;
4117
4118         /* username: */
4119         gchar *initial_username = modest_account_mgr_get_server_account_username (
4120                 modest_runtime_get_account_mgr(), server_account_name);
4121
4122 #ifdef MODEST_TOOLKIT_HILDON2
4123         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4124         if (initial_username)
4125                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
4126 #else
4127         GtkWidget *entry_username = gtk_entry_new ();
4128         if (initial_username)
4129                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
4130 #endif
4131         /* Dim this if a connection has ever succeeded with this username,
4132          * as per the UI spec: */
4133         /* const gboolean username_known =  */
4134         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4135         /*              modest_runtime_get_account_mgr(), server_account_name); */
4136         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4137
4138         /* We drop the username sensitive code and disallow changing it here
4139          * as tinymail does not support really changing the username in the callback
4140          */
4141         gtk_widget_set_sensitive (entry_username, FALSE);
4142
4143 #ifndef MODEST_TOOLKIT_GTK
4144         /* Auto-capitalization is the default, so let's turn it off: */
4145         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4146
4147         /* Create a size group to be used by all captions.
4148          * Note that HildonCaption does not create a default size group if we do not specify one.
4149          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4150         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4151
4152 #ifdef MODEST_TOOLKIT_HILDON2
4153         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4154                                                                   _("mail_fi_username"), FALSE,
4155                                                                   entry_username);
4156 #else
4157         GtkWidget *caption = hildon_caption_new (sizegroup,
4158                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
4159 #endif
4160         gtk_widget_show (entry_username);
4161         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4162                 FALSE, FALSE, MODEST_MARGIN_HALF);
4163         gtk_widget_show (caption);
4164 #else
4165         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
4166                             TRUE, FALSE, 0);
4167 #endif /* !MODEST_TOOLKIT_GTK */
4168
4169         /* password: */
4170 #ifdef MODEST_TOOLKIT_HILDON2
4171         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4172 #else
4173         GtkWidget *entry_password = gtk_entry_new ();
4174 #endif
4175         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4176         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4177
4178 #ifndef MODEST_TOOLKIT_GTK
4179         /* Auto-capitalization is the default, so let's turn it off: */
4180         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4181                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4182
4183 #ifdef MODEST_TOOLKIT_HILDON2
4184         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4185                                                        _("mail_fi_password"), FALSE,
4186                                                        entry_password);
4187 #else
4188         caption = hildon_caption_new (sizegroup,
4189                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
4190 #endif
4191         gtk_widget_show (entry_password);
4192         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4193                 FALSE, FALSE, MODEST_MARGIN_HALF);
4194         gtk_widget_show (caption);
4195         g_object_unref (sizegroup);
4196 #else
4197         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4198                             TRUE, FALSE, 0);
4199 #endif /* !MODEST_TOOLKIT_GTK */
4200
4201         if (initial_username != NULL)
4202                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4203
4204 /* This is not in the Maemo UI spec:
4205         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4206         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4207                             TRUE, FALSE, 0);
4208 */
4209
4210         fields = g_slice_new0 (PasswordDialogFields);
4211         fields->username = entry_username;
4212         fields->password = entry_password;
4213         fields->dialog = dialog;
4214
4215         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4216         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4217         password_dialog_check_field (NULL, fields);
4218
4219         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4220
4221         while (!completed) {
4222
4223                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4224                         if (username) {
4225 #ifdef MODEST_TOOLKIT_HILDON2
4226                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4227 #else
4228                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4229 #endif
4230
4231                                 /* Note that an empty field becomes the "" string */
4232                                 if (*username && strlen (*username) > 0) {
4233                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4234                                                                                         server_account_name,
4235                                                                                         *username);
4236                                         completed = TRUE;
4237
4238                                         const gboolean username_was_changed =
4239                                                 (strcmp (*username, initial_username) != 0);
4240                                         if (username_was_changed) {
4241                                                 g_warning ("%s: tinymail does not yet support changing the "
4242                                                            "username in the get_password() callback.\n", __FUNCTION__);
4243                                         }
4244                                 } else {
4245                                         g_free (*username);
4246                                         *username = NULL;
4247                                         /* Show error */
4248                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4249                                                                             _("mcen_ib_username_pw_incorrect"));
4250                                         completed = FALSE;
4251                                 }
4252                         }
4253
4254                         if (password) {
4255 #ifdef MODEST_TOOLKIT_HILDON2
4256                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4257 #else
4258                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4259 #endif
4260
4261                                 /* We do not save the password in the configuration,
4262                                  * because this function is only called for passwords that should
4263                                  * not be remembered:
4264                                  modest_server_account_set_password (
4265                                  modest_runtime_get_account_mgr(), server_account_name,
4266                                  *password);
4267                                  */
4268                         }
4269                         if (cancel)
4270                                 *cancel   = FALSE;
4271                 } else {
4272 #ifndef MODEST_TOOLKIT_HILDON2
4273                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4274                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4275 #endif
4276                         completed = TRUE;
4277                         if (username)
4278                                 *username = NULL;
4279                         if (password)
4280                                 *password = NULL;
4281                         if (cancel)
4282                                 *cancel   = TRUE;
4283                 }
4284         }
4285
4286 /* This is not in the Maemo UI spec:
4287         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4288                 *remember = TRUE;
4289         else
4290                 *remember = FALSE;
4291 */
4292
4293         g_free (initial_username);
4294         gtk_widget_destroy (dialog);
4295         g_slice_free (PasswordDialogFields, fields);
4296
4297         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4298 }
4299
4300 void
4301 modest_ui_actions_on_cut (GtkAction *action,
4302                           ModestWindow *window)
4303 {
4304         GtkWidget *focused_widget;
4305         GtkClipboard *clipboard;
4306
4307         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4308         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4309         if (GTK_IS_EDITABLE (focused_widget)) {
4310                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4311                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4312                 gtk_clipboard_store (clipboard);
4313         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4314                 GtkTextBuffer *buffer;
4315
4316                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4317                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4318                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4319                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4320                         gtk_clipboard_store (clipboard);
4321                 }
4322         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4323                 TnyList *header_list = modest_header_view_get_selected_headers (
4324                                 MODEST_HEADER_VIEW (focused_widget));
4325                 gboolean continue_download = FALSE;
4326                 gint num_of_unc_msgs;
4327
4328                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4329
4330                 if (num_of_unc_msgs) {
4331                         TnyAccount *account = get_account_from_header_list (header_list);
4332                         if (account) {
4333                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4334                                 g_object_unref (account);
4335                         }
4336                 }
4337
4338                 if (num_of_unc_msgs == 0 || continue_download) {
4339 /*                      modest_platform_information_banner (
4340                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4341                         modest_header_view_cut_selection (
4342                                         MODEST_HEADER_VIEW (focused_widget));
4343                 }
4344
4345                 g_object_unref (header_list);
4346         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4347                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4348         }
4349 }
4350
4351 void
4352 modest_ui_actions_on_copy (GtkAction *action,
4353                            ModestWindow *window)
4354 {
4355         GtkClipboard *clipboard;
4356         GtkWidget *focused_widget;
4357         gboolean copied = TRUE;
4358
4359         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4360         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4361
4362         if (GTK_IS_LABEL (focused_widget)) {
4363                 gchar *selection;
4364                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4365                 gtk_clipboard_set_text (clipboard, selection, -1);
4366                 g_free (selection);
4367                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4368                 gtk_clipboard_store (clipboard);
4369         } else if (GTK_IS_EDITABLE (focused_widget)) {
4370                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4371                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4372                 gtk_clipboard_store (clipboard);
4373         } else if (GTK_IS_HTML (focused_widget)) {
4374                 const gchar *sel;
4375                 int len = -1;
4376                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4377                 if ((sel == NULL) || (sel[0] == '\0')) {
4378                         copied = FALSE;
4379                 } else {
4380                         gtk_html_copy (GTK_HTML (focused_widget));
4381                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4382                         gtk_clipboard_store (clipboard);
4383                 }
4384         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4385                 GtkTextBuffer *buffer;
4386                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4387                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4388                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4389                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4390                         gtk_clipboard_store (clipboard);
4391                 }
4392         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4393                 TnyList *header_list = modest_header_view_get_selected_headers (
4394                                 MODEST_HEADER_VIEW (focused_widget));
4395                 gboolean continue_download = FALSE;
4396                 gint num_of_unc_msgs;
4397
4398                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4399
4400                 if (num_of_unc_msgs) {
4401                         TnyAccount *account = get_account_from_header_list (header_list);
4402                         if (account) {
4403                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4404                                 g_object_unref (account);
4405                         }
4406                 }
4407
4408                 if (num_of_unc_msgs == 0 || continue_download) {
4409                         modest_platform_information_banner (
4410                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4411                         modest_header_view_copy_selection (
4412                                         MODEST_HEADER_VIEW (focused_widget));
4413                 } else
4414                         copied = FALSE;
4415
4416                 g_object_unref (header_list);
4417
4418         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4419                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4420         }
4421
4422         /* Show information banner if there was a copy to clipboard */
4423         if(copied)
4424                 modest_platform_information_banner (
4425                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4426 }
4427
4428 void
4429 modest_ui_actions_on_undo (GtkAction *action,
4430                            ModestWindow *window)
4431 {
4432         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4433                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4434 #ifndef MODEST_TOOLKIT_HILDON2
4435         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4436                 ModestEmailClipboard *clipboard = NULL;
4437                 /* Clear clipboard source */
4438                 clipboard = modest_runtime_get_email_clipboard ();
4439                 modest_email_clipboard_clear (clipboard);
4440 #endif
4441         } else {
4442                 g_return_if_reached ();
4443         }
4444 }
4445
4446 void
4447 modest_ui_actions_on_redo (GtkAction *action,
4448                            ModestWindow *window)
4449 {
4450         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4451                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4452         }
4453         else {
4454                 g_return_if_reached ();
4455         }
4456 }
4457
4458
4459 static void
4460 destroy_information_note (ModestMailOperation *mail_op,
4461                           gpointer user_data)
4462 {
4463         /* destroy information note */
4464         gtk_widget_destroy (GTK_WIDGET(user_data));
4465 }
4466
4467 static void
4468 destroy_folder_information_note (ModestMailOperation *mail_op,
4469                                  TnyFolder *new_folder,
4470                                  gpointer user_data)
4471 {
4472         /* destroy information note */
4473         gtk_widget_destroy (GTK_WIDGET(user_data));
4474 }
4475
4476
4477 static void
4478 paste_as_attachment_free (gpointer data)
4479 {
4480         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4481
4482         if (helper->banner) {
4483                 gtk_widget_destroy (helper->banner);
4484                 g_object_unref (helper->banner);
4485         }
4486         g_free (helper);
4487 }
4488
4489 static void
4490 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4491                             TnyHeader *header,
4492                             TnyMsg *msg,
4493                             gpointer userdata)
4494 {
4495         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4496         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4497
4498         if (msg == NULL)
4499                 return;
4500
4501         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4502
4503 }
4504
4505 void
4506 modest_ui_actions_on_paste (GtkAction *action,
4507                             ModestWindow *window)
4508 {
4509         GtkWidget *focused_widget = NULL;
4510         GtkWidget *inf_note = NULL;
4511         ModestMailOperation *mail_op = NULL;
4512
4513         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4514         if (GTK_IS_EDITABLE (focused_widget)) {
4515                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4516         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4517                 ModestEmailClipboard *e_clipboard = NULL;
4518                 e_clipboard = modest_runtime_get_email_clipboard ();
4519                 if (modest_email_clipboard_cleared (e_clipboard)) {
4520                         GtkTextBuffer *buffer;
4521                         GtkClipboard *clipboard;
4522
4523                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4524                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4525                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4526                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4527                         ModestMailOperation *mail_op;
4528                         TnyFolder *src_folder = NULL;
4529                         TnyList *data = NULL;
4530                         gboolean delete;
4531                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4532                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4533                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4534                                                                            _CS("ckct_nw_pasting"));
4535                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4536                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4537                         if (helper->banner != NULL) {
4538                                 g_object_ref (G_OBJECT (helper->banner));
4539                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4540                         }
4541
4542                         if (data != NULL) {
4543                                 modest_mail_operation_get_msgs_full (mail_op,
4544                                                                      data,
4545                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4546                                                                      helper,
4547                                                                      paste_as_attachment_free);
4548                         }
4549                         /* Free */
4550                         if (data)
4551                                 g_object_unref (data);
4552                         if (src_folder)
4553                                 g_object_unref (src_folder);
4554
4555                 }
4556         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4557                 ModestEmailClipboard *clipboard = NULL;
4558                 TnyFolder *src_folder = NULL;
4559                 TnyFolderStore *folder_store = NULL;
4560                 TnyList *data = NULL;
4561                 gboolean delete = FALSE;
4562
4563                 /* Check clipboard source */
4564                 clipboard = modest_runtime_get_email_clipboard ();
4565                 if (modest_email_clipboard_cleared (clipboard))
4566                         return;
4567
4568                 /* Get elements to paste */
4569                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4570
4571                 /* Create a new mail operation */
4572                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4573
4574                 /* Get destination folder */
4575                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4576
4577                 /* transfer messages  */
4578                 if (data != NULL) {
4579                         gint response = 0;
4580
4581                         /* Ask for user confirmation */
4582                         response =
4583                                 modest_ui_actions_msgs_move_to_confirmation (window,
4584                                                                              TNY_FOLDER (folder_store),
4585                                                                              delete,
4586                                                                              data);
4587
4588                         if (response == GTK_RESPONSE_OK) {
4589                                 /* Launch notification */
4590                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4591                                                                              _CS("ckct_nw_pasting"));
4592                                 if (inf_note != NULL)  {
4593                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4594                                         gtk_widget_show (GTK_WIDGET(inf_note));
4595                                 }
4596
4597                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4598                                 modest_mail_operation_xfer_msgs (mail_op,
4599                                                                  data,
4600                                                                  TNY_FOLDER (folder_store),
4601                                                                  delete,
4602                                                                  destroy_information_note,
4603                                                                  inf_note);
4604                         } else {
4605                                 g_object_unref (mail_op);
4606                         }
4607
4608                 } else if (src_folder != NULL) {
4609                         /* Launch notification */
4610                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4611                                                                      _CS("ckct_nw_pasting"));
4612                         if (inf_note != NULL)  {
4613                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4614                                 gtk_widget_show (GTK_WIDGET(inf_note));
4615                         }
4616
4617                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4618                         modest_mail_operation_xfer_folder (mail_op,
4619                                                            src_folder,
4620                                                            folder_store,
4621                                                            delete,
4622                                                            destroy_folder_information_note,
4623                                                            inf_note);
4624                 }
4625
4626                 /* Free */
4627                 if (data != NULL)
4628                         g_object_unref (data);
4629                 if (src_folder != NULL)
4630                         g_object_unref (src_folder);
4631                 if (folder_store != NULL)
4632                         g_object_unref (folder_store);
4633         }
4634 }
4635
4636
4637 void
4638 modest_ui_actions_on_select_all (GtkAction *action,
4639                                  ModestWindow *window)
4640 {
4641         GtkWidget *focused_widget;
4642
4643         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4644         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4645                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4646         } else if (GTK_IS_LABEL (focused_widget)) {
4647                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4648         } else if (GTK_IS_EDITABLE (focused_widget)) {
4649                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4650         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4651                 GtkTextBuffer *buffer;
4652                 GtkTextIter start, end;
4653
4654                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4655                 gtk_text_buffer_get_start_iter (buffer, &start);
4656                 gtk_text_buffer_get_end_iter (buffer, &end);
4657                 gtk_text_buffer_select_range (buffer, &start, &end);
4658         } else if (GTK_IS_HTML (focused_widget)) {
4659                 gtk_html_select_all (GTK_HTML (focused_widget));
4660 #ifndef MODEST_TOOLKIT_HILDON2
4661         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4662                 GtkWidget *header_view = focused_widget;
4663                 GtkTreeSelection *selection = NULL;
4664
4665                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4666                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4667                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4668                 }
4669
4670                 /* Disable window dimming management */
4671                 modest_window_disable_dimming (MODEST_WINDOW(window));
4672
4673                 /* Select all messages */
4674                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4675                 gtk_tree_selection_select_all (selection);
4676
4677                 /* Set focuse on header view */
4678                 gtk_widget_grab_focus (header_view);
4679
4680                 /* Enable window dimming management */
4681                 modest_window_enable_dimming (MODEST_WINDOW(window));
4682                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4683                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4684 #endif
4685         }
4686
4687 }
4688
4689 void
4690 modest_ui_actions_on_mark_as_read (GtkAction *action,
4691                                    ModestWindow *window)
4692 {
4693         g_return_if_fail (MODEST_IS_WINDOW(window));
4694
4695         /* Mark each header as read */
4696         do_headers_action (window, headers_action_mark_as_read, NULL);
4697 }
4698
4699 void
4700 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4701                                      ModestWindow *window)
4702 {
4703         g_return_if_fail (MODEST_IS_WINDOW(window));
4704
4705         /* Mark each header as read */
4706         do_headers_action (window, headers_action_mark_as_unread, NULL);
4707 }
4708
4709 void
4710 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4711                                   GtkRadioAction *selected,
4712                                   ModestWindow *window)
4713 {
4714         gint value;
4715
4716         value = gtk_radio_action_get_current_value (selected);
4717         if (MODEST_IS_WINDOW (window)) {
4718                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4719         }
4720 }
4721
4722 void
4723 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4724                                                GtkRadioAction *selected,
4725                                                ModestWindow *window)
4726 {
4727         TnyHeaderFlags flags;
4728         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4729
4730         flags = gtk_radio_action_get_current_value (selected);
4731         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4732 }
4733
4734 void
4735 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4736                                                   GtkRadioAction *selected,
4737                                                   ModestWindow *window)
4738 {
4739         gint file_format;
4740
4741         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4742
4743         file_format = gtk_radio_action_get_current_value (selected);
4744         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4745 }
4746
4747
4748 void
4749 modest_ui_actions_on_zoom_plus (GtkAction *action,
4750                                 ModestWindow *window)
4751 {
4752         g_return_if_fail (MODEST_IS_WINDOW (window));
4753
4754         modest_window_zoom_plus (MODEST_WINDOW (window));
4755 }
4756
4757 void
4758 modest_ui_actions_on_zoom_minus (GtkAction *action,
4759                                  ModestWindow *window)
4760 {
4761         g_return_if_fail (MODEST_IS_WINDOW (window));
4762
4763         modest_window_zoom_minus (MODEST_WINDOW (window));
4764 }
4765
4766 void
4767 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4768                                            ModestWindow *window)
4769 {
4770         ModestWindowMgr *mgr;
4771         gboolean fullscreen, active;
4772         g_return_if_fail (MODEST_IS_WINDOW (window));
4773
4774         mgr = modest_runtime_get_window_mgr ();
4775
4776         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4777         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4778
4779         if (active != fullscreen) {
4780                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4781 #ifndef MODEST_TOOLKIT_HILDON2
4782                 gtk_window_present (GTK_WINDOW (window));
4783 #endif
4784         }
4785 }
4786
4787 void
4788 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4789                                         ModestWindow *window)
4790 {
4791         ModestWindowMgr *mgr;
4792         gboolean fullscreen;
4793
4794         g_return_if_fail (MODEST_IS_WINDOW (window));
4795
4796         mgr = modest_runtime_get_window_mgr ();
4797         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4798         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4799
4800 #ifndef MODEST_TOOLKIT_HILDON2
4801         gtk_window_present (GTK_WINDOW (window));
4802 #endif
4803 }
4804
4805 /*
4806  * Used by modest_ui_actions_on_details to call do_headers_action
4807  */
4808 static void
4809 headers_action_show_details (TnyHeader *header,
4810                              ModestWindow *window,
4811                              gpointer user_data)
4812
4813 {
4814         gboolean async_retrieval;
4815         TnyMsg *msg = NULL;
4816
4817         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4818                 async_retrieval = TRUE;
4819                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4820         } else {
4821                 async_retrieval = FALSE;
4822         }
4823         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4824         if (msg)
4825                 g_object_unref (msg);
4826 }
4827
4828 /*
4829  * Show the header details in a ModestDetailsDialog widget
4830  */
4831 void
4832 modest_ui_actions_on_details (GtkAction *action,
4833                               ModestWindow *win)
4834 {
4835         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4836                 TnyMsg *msg;
4837                 TnyHeader *header;
4838
4839                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4840                 if (!msg)
4841                         return;
4842
4843                 header = tny_msg_get_header (msg);
4844                 if (header) {
4845                         headers_action_show_details (header, win, NULL);
4846                         g_object_unref (header);
4847                 }
4848                 g_object_unref (msg);
4849 #ifndef MODEST_TOOLKIT_HILDON2
4850         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4851                 GtkWidget *folder_view, *header_view;
4852
4853                 /* Check which widget has the focus */
4854                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4855                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4856                 if (gtk_widget_is_focus (folder_view)) {
4857                         TnyFolderStore *folder_store
4858                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4859                         if (!folder_store) {
4860                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4861                                 return;
4862                         }
4863                         /* Show only when it's a folder */
4864                         /* This function should not be called for account items,
4865                          * because we dim the menu item for them. */
4866                         if (TNY_IS_FOLDER (folder_store)) {
4867                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4868                                                                            TNY_FOLDER (folder_store));
4869                         }
4870
4871                         g_object_unref (folder_store);
4872
4873                 } else {
4874                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4875                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4876                         /* Show details of each header */
4877                         do_headers_action (win, headers_action_show_details, header_view);
4878                 }
4879 #else
4880         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4881                 TnyFolder *folder;
4882                 GtkWidget *header_view;
4883
4884                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4885                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4886                 if (folder) {
4887                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4888                                                                    folder);
4889                         g_object_unref (folder);
4890                 }
4891 #endif
4892         }
4893 }
4894
4895 void
4896 modest_ui_actions_on_limit_error (GtkAction *action,
4897                                   ModestWindow *win)
4898 {
4899         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
4900
4901         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
4902
4903 }
4904
4905 void
4906 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4907                                      ModestMsgEditWindow *window)
4908 {
4909         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4910
4911         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4912 }
4913
4914 void
4915 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4916                                       ModestMsgEditWindow *window)
4917 {
4918         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4919
4920         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4921 }
4922
4923 #ifndef MODEST_TOOLKIT_HILDON2
4924 void
4925 modest_ui_actions_toggle_folders_view (GtkAction *action,
4926                                        ModestMainWindow *main_window)
4927 {
4928         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4929
4930         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4931                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4932         else
4933                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4934 }
4935 #endif
4936
4937 void
4938 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4939                                      ModestWindow *window)
4940 {
4941         gboolean active, fullscreen = FALSE;
4942         ModestWindowMgr *mgr;
4943
4944         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4945
4946         /* Check if we want to toggle the toolbar view in fullscreen
4947            or normal mode */
4948         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4949                      "ViewShowToolbarFullScreen")) {
4950                 fullscreen = TRUE;
4951         }
4952
4953         /* Toggle toolbar */
4954         mgr = modest_runtime_get_window_mgr ();
4955         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4956 }
4957
4958 void
4959 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4960                                            ModestMsgEditWindow *window)
4961 {
4962         modest_msg_edit_window_select_font (window);
4963 }
4964
4965
4966 void
4967 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4968                                                   const gchar *display_name,
4969                                                   GtkWindow *window)
4970 {
4971         /* don't update the display name if it was already set;
4972          * updating the display name apparently is expensive */
4973         const gchar* old_name = gtk_window_get_title (window);
4974
4975         if (display_name == NULL)
4976                 display_name = " ";
4977
4978         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4979                 return; /* don't do anything */
4980
4981         /* This is usually used to change the title of the main window, which
4982          * is the one that holds the folder view. Note that this change can
4983          * happen even when the widget doesn't have the focus. */
4984         gtk_window_set_title (window, display_name);
4985
4986 }
4987
4988 void
4989 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4990 {
4991         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4992         modest_msg_edit_window_select_contacts (window);
4993 }
4994
4995 void
4996 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4997 {
4998         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4999         modest_msg_edit_window_check_names (window, FALSE);
5000 }
5001
5002 #ifndef MODEST_TOOLKIT_HILDON2
5003 /*
5004  * This function is used to track changes in the selection of the
5005  * folder view that is inside the "move to" dialog to enable/disable
5006  * the OK button because we do not want the user to select a disallowed
5007  * destination for a folder.
5008  * The user also not desired to be able to use NEW button on items where
5009  * folder creation is not possibel.
5010  */
5011 static void
5012 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
5013                                             TnyFolderStore *folder_store,
5014                                             gboolean selected,
5015                                             gpointer user_data)
5016 {
5017         GtkWidget *dialog = NULL;
5018         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
5019         gboolean moving_folder = FALSE;
5020         gboolean is_local_account = TRUE;
5021         GtkWidget *folder_view = NULL;
5022         ModestTnyFolderRules rules;
5023
5024         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
5025
5026         if (!selected)
5027                 return;
5028
5029         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
5030         if (!dialog)
5031                 return;
5032
5033         /* check if folder_store is an remote account */
5034         if (TNY_IS_ACCOUNT (folder_store)) {
5035                 TnyAccount *local_account = NULL;
5036                 TnyAccount *mmc_account = NULL;
5037                 ModestTnyAccountStore *account_store = NULL;
5038
5039                 account_store = modest_runtime_get_account_store ();
5040                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
5041                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
5042
5043                 if ((gpointer) local_account != (gpointer) folder_store &&
5044                     (gpointer) mmc_account != (gpointer) folder_store) {
5045                         ModestProtocolType proto;
5046                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
5047                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
5048                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
5049                         }
5050                         is_local_account = FALSE;
5051                         /* New button should be dimmed on remote
5052                            POP account root */
5053                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5054                                                                                          proto,
5055                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
5056                 }
5057                 g_object_unref (local_account);
5058
5059                 /* It could not exist */
5060                 if (mmc_account)
5061                         g_object_unref (mmc_account);
5062         }
5063
5064         /* Check the target folder rules */
5065         if (TNY_IS_FOLDER (folder_store)) {
5066                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
5067                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
5068                         ok_sensitive = FALSE;
5069                         new_sensitive = FALSE;
5070                         goto end;
5071                 }
5072         }
5073
5074         /* Check if we're moving a folder */
5075         if (MODEST_IS_MAIN_WINDOW (user_data)) {
5076                 /* Get the widgets */
5077                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
5078                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5079                 if (gtk_widget_is_focus (folder_view))
5080                         moving_folder = TRUE;
5081         }
5082
5083         if (moving_folder) {
5084                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
5085
5086                 /* Get the folder to move */
5087                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5088
5089                 /* Check that we're not moving to the same folder */
5090                 if (TNY_IS_FOLDER (moved_folder)) {
5091                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
5092                         if (parent == folder_store)
5093                                 ok_sensitive = FALSE;
5094                         g_object_unref (parent);
5095                 }
5096
5097                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
5098                         /* Do not allow to move to an account unless it's the
5099                            local folders account */
5100                         if (!is_local_account)
5101                                 ok_sensitive = FALSE;
5102                 }
5103
5104                 if (ok_sensitive && (moved_folder == folder_store)) {
5105                         /* Do not allow to move to itself */
5106                         ok_sensitive = FALSE;
5107                 }
5108                 g_object_unref (moved_folder);
5109         } else {
5110                 TnyFolder *src_folder = NULL;
5111
5112                 /* Moving a message */
5113                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
5114
5115                         TnyHeader *header = NULL;
5116                         header = modest_msg_view_window_get_header
5117                                 (MODEST_MSG_VIEW_WINDOW (user_data));
5118                         if (!TNY_IS_HEADER(header))
5119                                 g_warning ("%s: could not get source header", __FUNCTION__);
5120                         else
5121                                 src_folder = tny_header_get_folder (header);
5122
5123                         if (header)
5124                                 g_object_unref (header);
5125                 } else {
5126                         src_folder =
5127                                 TNY_FOLDER (modest_folder_view_get_selected
5128                                             (MODEST_FOLDER_VIEW (folder_view)));
5129                 }
5130
5131                 if (TNY_IS_FOLDER(src_folder)) {
5132                         /* Do not allow to move the msg to the same folder */
5133                         /* Do not allow to move the msg to an account */
5134                         if ((gpointer) src_folder == (gpointer) folder_store ||
5135                             TNY_IS_ACCOUNT (folder_store))
5136                                 ok_sensitive = FALSE;
5137                         g_object_unref (src_folder);
5138                 } else
5139                         g_warning ("%s: could not get source folder", __FUNCTION__);
5140         }
5141
5142  end:
5143         /* Set sensitivity of the OK and NEW button */
5144         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5145         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5146 }
5147 #endif
5148
5149 static void
5150 on_move_to_dialog_response (GtkDialog *dialog,
5151                             gint       response,
5152                             gpointer   user_data)
5153 {
5154         GtkWidget *parent_win;
5155         MoveToInfo *helper = NULL;
5156         ModestFolderView *folder_view;
5157         gboolean unset_edit_mode = FALSE;
5158
5159         helper = (MoveToInfo *) user_data;
5160
5161         parent_win = (GtkWidget *) helper->win;
5162         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5163                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5164         switch (response) {
5165                 TnyFolderStore *dst_folder;
5166                 TnyFolderStore *selected;
5167
5168         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5169                 selected = modest_folder_view_get_selected (folder_view);
5170                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5171                 g_object_unref (selected);
5172                 return;
5173         case GTK_RESPONSE_NONE:
5174         case GTK_RESPONSE_CANCEL:
5175         case GTK_RESPONSE_DELETE_EVENT:
5176                 break;
5177         case GTK_RESPONSE_OK:
5178                 dst_folder = modest_folder_view_get_selected (folder_view);
5179
5180 #ifndef MODEST_TOOLKIT_HILDON2
5181                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5182                         /* Clean list to move used for filtering */
5183                         modest_folder_view_set_list_to_move (folder_view, NULL);
5184
5185                         modest_ui_actions_on_main_window_move_to (NULL,
5186                                                                   GTK_WIDGET (folder_view),
5187                                                                   dst_folder,
5188                                                                   MODEST_MAIN_WINDOW (parent_win));
5189 #else
5190                 if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5191                         /* Clean list to move used for filtering */
5192                         modest_folder_view_set_list_to_move (folder_view, NULL);
5193
5194                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5195                                                                     dst_folder,
5196                                                                     helper->list,
5197                                                                     GTK_WINDOW (parent_win));
5198 #endif
5199                 } else {
5200                         /* if the user selected a root folder
5201                            (account) then do not perform any action */
5202                         if (TNY_IS_ACCOUNT (dst_folder)) {
5203                                 g_signal_stop_emission_by_name (dialog, "response");
5204                                 return;
5205                         }
5206
5207                         /* Clean list to move used for filtering */
5208                         modest_folder_view_set_list_to_move (folder_view, NULL);
5209
5210                         /* Moving from headers window in edit mode */
5211                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5212                                                              dst_folder,
5213                                                              MODEST_WINDOW (parent_win));
5214                 }
5215
5216                 if (dst_folder)
5217                         g_object_unref (dst_folder);
5218
5219                 unset_edit_mode = TRUE;
5220                 break;
5221         default:
5222                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5223         }
5224
5225         /* Free the helper and exit */
5226         if (helper->list)
5227                 g_object_unref (helper->list);
5228         if (unset_edit_mode) {
5229 #ifdef MODEST_TOOLKIT_HILDON2
5230                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5231 #endif
5232         }
5233         g_slice_free (MoveToInfo, helper);
5234         gtk_widget_destroy (GTK_WIDGET (dialog));
5235 }
5236
5237 static GtkWidget*
5238 create_move_to_dialog (GtkWindow *win,
5239                        GtkWidget *folder_view,
5240                        TnyList *list_to_move)
5241 {
5242         GtkWidget *dialog, *tree_view = NULL;
5243
5244         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5245
5246 #ifndef MODEST_TOOLKIT_HILDON2
5247         /* Track changes in the selection to
5248          * disable the OK button whenever "Move to" is not possible
5249          * disbale NEW button whenever New is not possible */
5250         g_signal_connect (tree_view,
5251                           "folder_selection_changed",
5252                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5253                           win);
5254 #endif
5255
5256         /* It could happen that we're trying to move a message from a
5257            window (msg window for example) after the main window was
5258            closed, so we can not just get the model of the folder
5259            view */
5260         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5261                 const gchar *visible_id = NULL;
5262
5263                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5264                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5265                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5266                                                MODEST_FOLDER_VIEW(tree_view));
5267
5268                 visible_id =
5269                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5270
5271                 /* Show the same account than the one that is shown in the main window */
5272                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5273                                                                              visible_id);
5274         } else {
5275                 const gchar *active_account_name = NULL;
5276                 ModestAccountMgr *mgr = NULL;
5277                 ModestAccountSettings *settings = NULL;
5278                 ModestServerAccountSettings *store_settings = NULL;
5279
5280                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5281                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5282                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
5283                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
5284
5285                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5286                 mgr = modest_runtime_get_account_mgr ();
5287                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5288
5289                 if (settings) {
5290                         const gchar *store_account_name;
5291                         store_settings = modest_account_settings_get_store_settings (settings);
5292                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5293
5294                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5295                                                                                      store_account_name);
5296                         g_object_unref (store_settings);
5297                         g_object_unref (settings);
5298                 }
5299         }
5300
5301         /* we keep a pointer to the embedded folder view, so we can
5302          *   retrieve it with get_folder_view_from_move_to_dialog (see
5303          *   above) later (needed for focus handling)
5304          */
5305         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5306
5307         /* Hide special folders */
5308 #ifndef MODEST_TOOLKIT_HILDON2
5309         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5310 #endif
5311         if (list_to_move)
5312                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5313 #ifndef MODEST_TOOLKIT_HILDON2
5314         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5315 #endif
5316
5317         gtk_widget_show (GTK_WIDGET (tree_view));
5318
5319         return dialog;
5320 }
5321
5322 /*
5323  * Shows a confirmation dialog to the user when we're moving messages
5324  * from a remote server to the local storage. Returns the dialog
5325  * response. If it's other kind of movement then it always returns
5326  * GTK_RESPONSE_OK
5327  *
5328  * This one is used by the next functions:
5329  *      modest_ui_actions_on_paste                      - commented out
5330  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5331  */
5332 gint
5333 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5334                                              TnyFolder *dest_folder,
5335                                              gboolean delete,
5336                                              TnyList *headers)
5337 {
5338         gint response = GTK_RESPONSE_OK;
5339         TnyAccount *account = NULL;
5340         TnyFolder *src_folder = NULL;
5341         TnyIterator *iter = NULL;
5342         TnyHeader *header = NULL;
5343
5344         /* return with OK if the destination is a remote folder */
5345         if (modest_tny_folder_is_remote_folder (dest_folder))
5346                 return GTK_RESPONSE_OK;
5347
5348         /* Get source folder */
5349         iter = tny_list_create_iterator (headers);
5350         header = TNY_HEADER (tny_iterator_get_current (iter));
5351         if (header) {
5352                 src_folder = tny_header_get_folder (header);
5353                 g_object_unref (header);
5354         }
5355         g_object_unref (iter);
5356
5357         /* if no src_folder, message may be an attahcment */
5358         if (src_folder == NULL)
5359                 return GTK_RESPONSE_CANCEL;
5360
5361         /* If the source is a local or MMC folder */
5362         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5363                 g_object_unref (src_folder);
5364                 return GTK_RESPONSE_OK;
5365         }
5366
5367         /* Get the account */
5368         account = tny_folder_get_account (src_folder);
5369
5370         /* now if offline we ask the user */
5371         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5372                 response = GTK_RESPONSE_OK;
5373         else
5374                 response = GTK_RESPONSE_CANCEL;
5375
5376         /* Frees */
5377         g_object_unref (src_folder);
5378         g_object_unref (account);
5379
5380         return response;
5381 }
5382
5383 static void
5384 move_to_helper_destroyer (gpointer user_data)
5385 {
5386         MoveToHelper *helper = (MoveToHelper *) user_data;
5387
5388         /* Close the "Pasting" information banner */
5389         if (helper->banner) {
5390                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5391                 g_object_unref (helper->banner);
5392         }
5393         if (gtk_tree_row_reference_valid (helper->reference)) {
5394                 gtk_tree_row_reference_free (helper->reference);
5395                 helper->reference = NULL;
5396         }
5397         g_free (helper);
5398 }
5399
5400 static void
5401 move_to_cb (ModestMailOperation *mail_op,
5402             gpointer user_data)
5403 {
5404         MoveToHelper *helper = (MoveToHelper *) user_data;
5405         GObject *object = modest_mail_operation_get_source (mail_op);
5406
5407         /* Note that the operation could have failed, in that case do
5408            nothing */
5409         if (modest_mail_operation_get_status (mail_op) !=
5410             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5411                 goto frees;
5412
5413         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5414                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5415
5416                 if (!modest_msg_view_window_select_next_message (self) &&
5417                     !modest_msg_view_window_select_previous_message (self)) {
5418                         /* No more messages to view, so close this window */
5419                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5420                 }
5421 #ifndef MODEST_TOOLKIT_HILDON2
5422         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5423                    gtk_tree_row_reference_valid (helper->reference)) {
5424                 GtkWidget *header_view;
5425                 GtkTreePath *path;
5426                 GtkTreeSelection *sel;
5427
5428                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5429                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5430                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5431                 path = gtk_tree_row_reference_get_path (helper->reference);
5432                 /* We need to unselect the previous one
5433                    because we could be copying instead of
5434                    moving */
5435                 gtk_tree_selection_unselect_all (sel);
5436                 gtk_tree_selection_select_path (sel, path);
5437                 gtk_tree_path_free (path);
5438 #endif
5439         }
5440         g_object_unref (object);
5441
5442  frees:
5443         /* Destroy the helper */
5444         move_to_helper_destroyer (helper);
5445 }
5446
5447 static void
5448 folder_move_to_cb (ModestMailOperation *mail_op,
5449                    TnyFolder *new_folder,
5450                    gpointer user_data)
5451 {
5452         GObject *object;
5453
5454         object = modest_mail_operation_get_source (mail_op);
5455 #ifndef MODEST_TOOLKIT_HILDON2
5456         if (MODEST_IS_MAIN_WINDOW (object)) {
5457                 GtkWidget *folder_view;
5458                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5459                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5460                 g_object_ref (folder_view);
5461                 g_object_unref (object);
5462                 move_to_cb (mail_op, user_data);
5463                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5464                 g_object_unref (folder_view);
5465         } else {
5466 #else
5467                 {
5468 #endif
5469                 move_to_cb (mail_op, user_data);
5470         }
5471 }
5472
5473 static void
5474 msgs_move_to_cb (ModestMailOperation *mail_op,
5475                  gpointer user_data)
5476 {
5477         move_to_cb (mail_op, user_data);
5478 }
5479
5480 void
5481 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5482                                              gpointer user_data)
5483 {
5484         GObject *win = NULL;
5485         const GError *error;
5486         TnyAccount *account = NULL;
5487
5488 #ifndef MODEST_TOOLKIT_HILDON2
5489         ModestWindow *main_window = NULL;
5490
5491         /* Disable next automatic folder selection */
5492         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5493                                                          FALSE); /* don't create */
5494
5495         /* Show notification dialog only if the main window exists */
5496         if (main_window) {
5497                 GtkWidget *folder_view = NULL;
5498
5499                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5500                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5501                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5502
5503                 if (user_data && TNY_IS_FOLDER (user_data)) {
5504                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5505                                                           TNY_FOLDER (user_data), FALSE);
5506                 }
5507         }
5508 #endif
5509         win = modest_mail_operation_get_source (mail_op);
5510         error = modest_mail_operation_get_error (mail_op);
5511
5512         if (TNY_IS_FOLDER (user_data))
5513                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
5514         else if (TNY_IS_ACCOUNT (user_data))
5515                 account = g_object_ref (user_data);
5516
5517         /* If it's not a disk full error then show a generic error */
5518         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5519                                                              (GtkWidget *) win, (GError *) error,
5520                                                              account, NULL))
5521                 modest_platform_run_information_dialog ((GtkWindow *) win,
5522                                                         _("mail_in_ui_folder_move_target_error"),
5523                                                         FALSE);
5524         if (account)
5525                 g_object_unref (account);
5526         if (win)
5527                 g_object_unref (win);
5528 }
5529
5530 #ifndef MODEST_TOOLKIT_HILDON2
5531 static void
5532 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5533                        TnyHeader *header,
5534                        gboolean canceled,
5535                        TnyMsg *msg,
5536                        GError *err,
5537                        gpointer user_data)
5538 {
5539         TnyList *parts;
5540         TnyIterator *iter;
5541         gint pending_purges = 0;
5542         gboolean some_purged = FALSE;
5543         ModestWindow *win = MODEST_WINDOW (user_data);
5544         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5545
5546         /* If there was any error */
5547         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5548                 modest_window_mgr_unregister_header (mgr, header);
5549                 return;
5550         }
5551
5552         /* Once the message has been retrieved for purging, we check if
5553          * it's all ok for purging */
5554
5555         parts = tny_simple_list_new ();
5556         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5557         iter = tny_list_create_iterator (parts);
5558
5559         while (!tny_iterator_is_done (iter)) {
5560                 TnyMimePart *part;
5561                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5562                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5563                         if (tny_mime_part_is_purged (part))
5564                                 some_purged = TRUE;
5565                         else
5566                                 pending_purges++;
5567                 }
5568
5569                 if (part)
5570                         g_object_unref (part);
5571
5572                 tny_iterator_next (iter);
5573         }
5574         g_object_unref (iter);
5575
5576
5577         if (pending_purges>0) {
5578                 gint response;
5579                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5580
5581                 if (response == GTK_RESPONSE_OK) {
5582                         GtkWidget *info;
5583                         info =
5584                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5585                         iter = tny_list_create_iterator (parts);
5586                         while (!tny_iterator_is_done (iter)) {
5587                                 TnyMimePart *part;
5588
5589                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5590                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5591                                         tny_mime_part_set_purged (part);
5592
5593                                 if (part)
5594                                         g_object_unref (part);
5595
5596                                 tny_iterator_next (iter);
5597                         }
5598                         g_object_unref (iter);
5599
5600                         tny_msg_rewrite_cache (msg);
5601
5602                         gtk_widget_destroy (info);
5603                 }
5604         }
5605
5606         modest_window_mgr_unregister_header (mgr, header);
5607
5608         g_object_unref (parts);
5609 }
5610
5611 static void
5612 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5613                                                      ModestMainWindow *win)
5614 {
5615         GtkWidget *header_view;
5616         TnyList *header_list;
5617         TnyHeader *header;
5618         TnyHeaderFlags flags;
5619         ModestWindow *msg_view_window =  NULL;
5620         gboolean found;
5621
5622         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5623
5624         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5625                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5626
5627         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5628         if (!header_list) {
5629                 g_warning ("%s: no header selected", __FUNCTION__);
5630                 return;
5631         }
5632
5633         if (tny_list_get_length (header_list) == 1) {
5634                 TnyIterator *iter = tny_list_create_iterator (header_list);
5635                 header = TNY_HEADER (tny_iterator_get_current (iter));
5636                 g_object_unref (iter);
5637         } else
5638                 return;
5639
5640         if (!header || !TNY_IS_HEADER(header)) {
5641                 g_warning ("%s: header is not valid", __FUNCTION__);
5642                 return;
5643         }
5644
5645         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5646                                                           header, &msg_view_window);
5647         flags = tny_header_get_flags (header);
5648         if (!(flags & TNY_HEADER_FLAG_CACHED))
5649                 return;
5650         if (found) {
5651                 if (msg_view_window != NULL)
5652                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5653                 else {
5654                         /* do nothing; uid was registered before, so window is probably on it's way */
5655                         g_debug ("header %p has already been registered", header);
5656                 }
5657         } else {
5658                 ModestMailOperation *mail_op = NULL;
5659                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5660                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5661                                                                          modest_ui_actions_disk_operations_error_handler,
5662                                                                          NULL, NULL);
5663                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5664                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5665
5666                 g_object_unref (mail_op);
5667         }
5668         if (header)
5669                 g_object_unref (header);
5670         if (header_list)
5671                 g_object_unref (header_list);
5672 }
5673 #endif
5674
5675 /*
5676  * Checks if we need a connection to do the transfer and if the user
5677  * wants to connect to complete it
5678  */
5679 static void
5680 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5681                                        TnyFolderStore *src_folder,
5682                                        TnyList *headers,
5683                                        TnyFolder *dst_folder,
5684                                        gboolean delete_originals,
5685                                        gboolean *need_connection,
5686                                        gboolean *do_xfer)
5687 {
5688         TnyAccount *src_account;
5689         gint uncached_msgs = 0;
5690
5691         /* We don't need any further check if
5692          *
5693          * 1- the source folder is local OR
5694          * 2- the device is already online
5695          */
5696         if (!modest_tny_folder_store_is_remote (src_folder) ||
5697             tny_device_is_online (modest_runtime_get_device())) {
5698                 *need_connection = FALSE;
5699                 *do_xfer = TRUE;
5700                 return;
5701         }
5702
5703         /* We must ask for a connection when
5704          *
5705          *   - the message(s) is not already cached   OR
5706          *   - the message(s) is cached but the leave_on_server setting
5707          * is FALSE (because we need to sync the source folder to
5708          * delete the message from the server (for IMAP we could do it
5709          * offline, it'll take place the next time we get a
5710          * connection)
5711          */
5712         uncached_msgs = header_list_count_uncached_msgs (headers);
5713         src_account = get_account_from_folder_store (src_folder);
5714         if (uncached_msgs > 0) {
5715                 guint num_headers;
5716                 const gchar *msg;
5717
5718                 *need_connection = TRUE;
5719                 num_headers = tny_list_get_length (headers);
5720                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5721
5722                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5723                     GTK_RESPONSE_CANCEL) {
5724                         *do_xfer = FALSE;
5725                 } else {
5726                         *do_xfer = TRUE;
5727                 }
5728         } else {
5729                 /* The transfer is possible and the user wants to */
5730                 *do_xfer = TRUE;
5731
5732                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5733                         const gchar *account_name;
5734                         gboolean leave_on_server;
5735
5736                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5737                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5738                                                                                   account_name);
5739
5740                         if (leave_on_server == TRUE) {
5741                                 *need_connection = FALSE;
5742                         } else {
5743                                 *need_connection = TRUE;
5744                         }
5745                 } else {
5746                         *need_connection = FALSE;
5747                 }
5748         }
5749
5750         /* Frees */
5751         g_object_unref (src_account);
5752 }
5753
5754 static void
5755 xfer_messages_error_handler (ModestMailOperation *mail_op,
5756                              gpointer user_data)
5757 {
5758         GObject *win;
5759         const GError *error;
5760         TnyAccount *account;
5761
5762         win = modest_mail_operation_get_source (mail_op);
5763         error = modest_mail_operation_get_error (mail_op);
5764
5765         /* We cannot get the account from the mail op as that is the
5766            source account and for checking memory full conditions we
5767            need the destination one */
5768         account = TNY_ACCOUNT (user_data);
5769
5770         if (error &&
5771             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5772                                                              (GtkWidget *) win, (GError*) error,
5773                                                              account, _KR("cerm_memory_card_full"))) {
5774                 modest_platform_run_information_dialog ((GtkWindow *) win,
5775                                                         _("mail_in_ui_folder_move_target_error"),
5776                                                         FALSE);
5777         }
5778         if (win)
5779                 g_object_unref (win);
5780 }
5781
5782 typedef struct {
5783         TnyFolderStore *dst_folder;
5784         TnyList *headers;
5785 } XferMsgsHelper;
5786
5787 /**
5788  * Utility function that transfer messages from both the main window
5789  * and the msg view window when using the "Move to" dialog
5790  */
5791 static void
5792 xfer_messages_performer  (gboolean canceled,
5793                           GError *err,
5794                           GtkWindow *parent_window,
5795                           TnyAccount *account,
5796                           gpointer user_data)
5797 {
5798         ModestWindow *win = MODEST_WINDOW (parent_window);
5799         TnyAccount *dst_account = NULL;
5800         gboolean dst_forbids_message_add = FALSE;
5801         XferMsgsHelper *helper;
5802         MoveToHelper *movehelper;
5803         ModestMailOperation *mail_op;
5804
5805         helper = (XferMsgsHelper *) user_data;
5806
5807         if (canceled || err) {
5808                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5809                                                                      (GtkWidget *) parent_window, err,
5810                                                                      account, NULL)) {
5811                         /* Show the proper error message */
5812                         modest_ui_actions_on_account_connection_error (parent_window, account);
5813                 }
5814                 goto end;
5815         }
5816
5817         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5818
5819         /* tinymail will return NULL for local folders it seems */
5820         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5821                                                                                   modest_tny_account_get_protocol_type (dst_account),
5822                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
5823
5824         if (dst_forbids_message_add) {
5825                 modest_platform_information_banner (GTK_WIDGET (win),
5826                                                     NULL,
5827                                                     ngettext("mail_in_ui_folder_move_target_error",
5828                                                              "mail_in_ui_folder_move_targets_error",
5829                                                              tny_list_get_length (helper->headers)));
5830                 goto end;
5831         }
5832
5833         movehelper = g_new0 (MoveToHelper, 1);
5834
5835 #ifndef MODEST_TOOLKIT_HILDON2
5836         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5837                                                                _CS("ckct_nw_pasting"));
5838         if (movehelper->banner != NULL)  {
5839                 g_object_ref (movehelper->banner);
5840                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5841         }
5842
5843         if (MODEST_IS_MAIN_WINDOW (win)) {
5844                 GtkWidget *header_view =
5845                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5846                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5847                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5848         }
5849 #endif
5850
5851         /* Perform the mail operation */
5852         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5853                                                                  xfer_messages_error_handler,
5854                                                                  g_object_ref (dst_account),
5855                                                                  g_object_unref);
5856         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5857                                          mail_op);
5858
5859         modest_mail_operation_xfer_msgs (mail_op,
5860                                          helper->headers,
5861                                          TNY_FOLDER (helper->dst_folder),
5862                                          TRUE,
5863                                          msgs_move_to_cb,
5864                                          movehelper);
5865
5866         g_object_unref (G_OBJECT (mail_op));
5867  end:
5868         if (dst_account)
5869                 g_object_unref (dst_account);
5870         g_object_unref (helper->dst_folder);
5871         g_object_unref (helper->headers);
5872         g_slice_free (XferMsgsHelper, helper);
5873 }
5874
5875 typedef struct {
5876         TnyFolder *src_folder;
5877         TnyFolderStore *dst_folder;
5878         gboolean delete_original;
5879         GtkWidget *folder_view;
5880 } MoveFolderInfo;
5881
5882 static void
5883 on_move_folder_cb (gboolean canceled,
5884                    GError *err,
5885                    GtkWindow *parent_window,
5886                    TnyAccount *account,
5887                    gpointer user_data)
5888 {
5889         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5890         GtkTreeSelection *sel;
5891         ModestMailOperation *mail_op = NULL;
5892
5893         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5894                 /* Note that the connection process can fail due to
5895                    memory low conditions as it can not successfully
5896                    store the summary */
5897                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5898                                                                      (GtkWidget*) parent_window, err,
5899                                                                      account, NULL))
5900                         g_debug ("Error connecting when trying to move a folder");
5901
5902                 g_object_unref (G_OBJECT (info->src_folder));
5903                 g_object_unref (G_OBJECT (info->dst_folder));
5904                 g_free (info);
5905                 return;
5906         }
5907
5908         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5909 #ifndef MODEST_TOOLKIT_HILDON2
5910         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5911                         _CS("ckct_nw_pasting"));
5912         if (helper->banner != NULL)  {
5913                 g_object_ref (helper->banner);
5914                 gtk_widget_show (GTK_WIDGET(helper->banner));
5915         }
5916 #endif
5917         /* Clean folder on header view before moving it */
5918         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5919         gtk_tree_selection_unselect_all (sel);
5920
5921         /* Let gtk events run. We need that the folder
5922            view frees its reference to the source
5923            folder *before* issuing the mail operation
5924            so we need the signal handler of selection
5925            changed to happen before the mail
5926            operation
5927         while (gtk_events_pending ())
5928                 gtk_main_iteration ();   */
5929
5930         mail_op =
5931                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5932                                                                modest_ui_actions_move_folder_error_handler,
5933                                                                g_object_ref (info->dst_folder), g_object_unref);
5934         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5935                                          mail_op);
5936
5937 #ifndef MODEST_TOOLKIT_HILDON2
5938         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5939                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5940                                                   TNY_FOLDER (info->dst_folder), TRUE);
5941         }
5942 #endif
5943         modest_mail_operation_xfer_folder (mail_op,
5944                         TNY_FOLDER (info->src_folder),
5945                         info->dst_folder,
5946                         info->delete_original,
5947                         folder_move_to_cb,
5948                         helper);
5949         g_object_unref (G_OBJECT (info->src_folder));
5950
5951         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5952         /* } */
5953
5954         /* Unref mail operation */
5955         g_object_unref (G_OBJECT (mail_op));
5956         g_object_unref (G_OBJECT (info->dst_folder));
5957         g_free (user_data);
5958 }
5959
5960 static TnyAccount *
5961 get_account_from_folder_store (TnyFolderStore *folder_store)
5962 {
5963         if (TNY_IS_ACCOUNT (folder_store))
5964                 return g_object_ref (folder_store);
5965         else
5966                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5967 }
5968
5969 #ifndef MODEST_TOOLKIT_HILDON2
5970 /*
5971  * UI handler for the "Move to" action when invoked from the
5972  * ModestMainWindow
5973  */
5974 static void
5975 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5976                                           GtkWidget *folder_view,
5977                                           TnyFolderStore *dst_folder,
5978                                           ModestMainWindow *win)
5979 {
5980         ModestHeaderView *header_view = NULL;
5981         TnyFolderStore *src_folder = NULL;
5982
5983         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5984
5985         /* Get the source folder */
5986         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5987
5988         /* Get header view */
5989         header_view = (ModestHeaderView *)
5990                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5991
5992         /* Get folder or messages to transfer */
5993         if (gtk_widget_is_focus (folder_view)) {
5994                 gboolean do_xfer = TRUE;
5995
5996                 /* Allow only to transfer folders to the local root folder */
5997                 if (TNY_IS_ACCOUNT (dst_folder) &&
5998                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5999                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
6000                         do_xfer = FALSE;
6001                 } else if (!TNY_IS_FOLDER (src_folder)) {
6002                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6003                         do_xfer = FALSE;
6004                 }
6005
6006                 if (do_xfer) {
6007                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6008                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6009
6010                         info->src_folder = g_object_ref (src_folder);
6011                         info->dst_folder = g_object_ref (dst_folder);
6012                         info->delete_original = TRUE;
6013                         info->folder_view = folder_view;
6014
6015                         connect_info->callback = on_move_folder_cb;
6016                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6017                         connect_info->data = info;
6018
6019                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6020                                                                    TNY_FOLDER_STORE (src_folder),
6021                                                                    connect_info);
6022                 }
6023         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
6024                 TnyList *headers;
6025
6026                 headers = modest_header_view_get_selected_headers(header_view);
6027
6028                 /* Transfer the messages */
6029                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
6030                                                             headers, TNY_FOLDER (dst_folder));
6031
6032                 g_object_unref (headers);
6033         }
6034
6035         /* Frees */
6036         g_object_unref (src_folder);
6037 }
6038 #endif
6039
6040 #ifdef MODEST_TOOLKIT_HILDON2
6041 /*
6042  * UI handler for the "Move to" action when invoked from the
6043  * ModestFolderWindow
6044  */
6045 static void
6046 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
6047                                             TnyFolderStore *dst_folder,
6048                                             TnyList *selection,
6049                                             GtkWindow *win)
6050 {
6051         TnyFolderStore *src_folder = NULL;
6052         TnyIterator *iterator;
6053
6054         if (tny_list_get_length (selection) != 1)
6055                 return;
6056
6057         iterator = tny_list_create_iterator (selection);
6058         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
6059         g_object_unref (iterator);
6060
6061
6062         gboolean do_xfer = TRUE;
6063
6064         /* Allow only to transfer folders to the local root folder */
6065         if (TNY_IS_ACCOUNT (dst_folder) &&
6066             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
6067             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
6068                 do_xfer = FALSE;
6069                 /* Show an error */
6070                 modest_platform_run_information_dialog (win,
6071                                                         _("mail_in_ui_folder_move_target_error"),
6072                                                         FALSE);
6073         } else if (!TNY_IS_FOLDER (src_folder)) {
6074                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6075                 do_xfer = FALSE;
6076         }
6077
6078         if (do_xfer) {
6079                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6080                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6081
6082                 info->src_folder = g_object_ref (src_folder);
6083                 info->dst_folder = g_object_ref (dst_folder);
6084                 info->delete_original = TRUE;
6085                 info->folder_view = folder_view;
6086
6087                 connect_info->callback = on_move_folder_cb;
6088                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6089                 connect_info->data = info;
6090
6091                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6092                                                            TNY_FOLDER_STORE (src_folder),
6093                                                            connect_info);
6094         }
6095
6096         /* Frees */
6097         g_object_unref (src_folder);
6098 }
6099 #endif
6100
6101
6102 void
6103 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
6104                                             TnyFolder *src_folder,
6105                                             TnyList *headers,
6106                                             TnyFolder *dst_folder)
6107 {
6108         gboolean need_connection = TRUE;
6109         gboolean do_xfer = TRUE;
6110         XferMsgsHelper *helper;
6111
6112         g_return_if_fail (TNY_IS_FOLDER (src_folder));
6113         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6114         g_return_if_fail (TNY_IS_LIST (headers));
6115
6116         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
6117                                                headers, TNY_FOLDER (dst_folder),
6118                                                TRUE, &need_connection,
6119                                                &do_xfer);
6120
6121         /* If we don't want to transfer just return */
6122         if (!do_xfer)
6123                 return;
6124
6125         /* Create the helper */
6126         helper = g_slice_new (XferMsgsHelper);
6127         helper->dst_folder = g_object_ref (dst_folder);
6128         helper->headers = g_object_ref (headers);
6129
6130         if (need_connection) {
6131                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6132                 connect_info->callback = xfer_messages_performer;
6133                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
6134                 connect_info->data = helper;
6135
6136                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6137                                                            TNY_FOLDER_STORE (src_folder),
6138                                                            connect_info);
6139         } else {
6140                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
6141                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
6142                                          src_account, helper);
6143                 g_object_unref (src_account);
6144         }
6145 }
6146
6147 /*
6148  * UI handler for the "Move to" action when invoked from the
6149  * ModestMsgViewWindow
6150  */
6151 static void
6152 modest_ui_actions_on_window_move_to (GtkAction *action,
6153                                      TnyList *headers,
6154                                      TnyFolderStore *dst_folder,
6155                                      ModestWindow *win)
6156 {
6157         TnyFolder *src_folder = NULL;
6158
6159         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6160
6161         if (headers) {
6162                 TnyHeader *header = NULL;
6163                 TnyIterator *iter;
6164
6165                 iter = tny_list_create_iterator (headers);
6166                 header = (TnyHeader *) tny_iterator_get_current (iter);
6167                 src_folder = tny_header_get_folder (header);
6168
6169                 /* Transfer the messages */
6170                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6171                                                             headers,
6172                                                             TNY_FOLDER (dst_folder));
6173
6174                 /* Frees */
6175                 g_object_unref (header);
6176                 g_object_unref (iter);
6177                 g_object_unref (src_folder);
6178         }
6179 }
6180
6181 void
6182 modest_ui_actions_on_move_to (GtkAction *action,
6183                               ModestWindow *win)
6184 {
6185         modest_ui_actions_on_edit_mode_move_to (win);
6186 }
6187
6188 gboolean
6189 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6190 {
6191         GtkWidget *dialog = NULL;
6192         MoveToInfo *helper = NULL;
6193         TnyList *list_to_move;
6194
6195         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6196
6197 #ifndef MODEST_TOOLKIT_HILDON2
6198         /* Get the main window if exists */
6199         ModestMainWindow *main_window;
6200         if (MODEST_IS_MAIN_WINDOW (win))
6201                 main_window = MODEST_MAIN_WINDOW (win);
6202         else
6203                 main_window =
6204                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6205                                                                                FALSE)); /* don't create */
6206 #endif
6207
6208         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6209
6210         if (!list_to_move)
6211                 return FALSE;
6212
6213         if (tny_list_get_length (list_to_move) < 1) {
6214                 g_object_unref (list_to_move);
6215                 return FALSE;
6216         }
6217
6218         /* Create and run the dialog */
6219         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6220         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6221                                      GTK_WINDOW (dialog),
6222                                      (GtkWindow *) win);
6223
6224         /* Create helper */
6225         helper = g_slice_new0 (MoveToInfo);
6226         helper->list = list_to_move;
6227         helper->win = win;
6228
6229         /* Listen to response signal */
6230         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6231
6232         /* Show the dialog */
6233         gtk_widget_show (dialog);
6234
6235         return FALSE;
6236 }
6237
6238 /*
6239  * Calls #HeadersFunc for each header already selected in the main
6240  * window or the message currently being shown in the msg view window
6241  */
6242 static void
6243 do_headers_action (ModestWindow *win,
6244                    HeadersFunc func,
6245                    gpointer user_data)
6246 {
6247         TnyList *headers_list = NULL;
6248         TnyIterator *iter = NULL;
6249         TnyHeader *header = NULL;
6250         TnyFolder *folder = NULL;
6251
6252         /* Get headers */
6253         headers_list = get_selected_headers (win);
6254         if (!headers_list)
6255                 return;
6256
6257         /* Get the folder */
6258         iter = tny_list_create_iterator (headers_list);
6259         header = TNY_HEADER (tny_iterator_get_current (iter));
6260         if (header) {
6261                 folder = tny_header_get_folder (header);
6262                 g_object_unref (header);
6263         }
6264
6265         /* Call the function for each header */
6266         while (!tny_iterator_is_done (iter)) {
6267                 header = TNY_HEADER (tny_iterator_get_current (iter));
6268                 func (header, win, user_data);
6269                 g_object_unref (header);
6270                 tny_iterator_next (iter);
6271         }
6272
6273         /* Trick: do a poke status in order to speed up the signaling
6274            of observers */
6275         if (folder) {
6276                 tny_folder_poke_status (folder);
6277                 g_object_unref (folder);
6278         }
6279
6280         /* Frees */
6281         g_object_unref (iter);
6282         g_object_unref (headers_list);
6283 }
6284
6285 void
6286 modest_ui_actions_view_attachment (GtkAction *action,
6287                                    ModestWindow *window)
6288 {
6289         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6290                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6291         } else {
6292                 /* not supported window for this action */
6293                 g_return_if_reached ();
6294         }
6295 }
6296
6297 void
6298 modest_ui_actions_save_attachments (GtkAction *action,
6299                                     ModestWindow *window)
6300 {
6301         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6302
6303                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6304                         return;
6305
6306                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6307         } else {
6308                 /* not supported window for this action */
6309                 g_return_if_reached ();
6310         }
6311 }
6312
6313 void
6314 modest_ui_actions_remove_attachments (GtkAction *action,
6315                                       ModestWindow *window)
6316 {
6317 #ifndef MODEST_TOOLKIT_HILDON2
6318         if (MODEST_IS_MAIN_WINDOW (window)) {
6319                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6320         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6321 #else
6322         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6323 #endif
6324                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6325         } else {
6326                 /* not supported window for this action */
6327                 g_return_if_reached ();
6328         }
6329 }
6330
6331 void
6332 modest_ui_actions_on_settings (GtkAction *action,
6333                                ModestWindow *win)
6334 {
6335         GtkWidget *dialog;
6336
6337         dialog = modest_platform_get_global_settings_dialog ();
6338         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6339         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6340         gtk_widget_show_all (dialog);
6341
6342         gtk_dialog_run (GTK_DIALOG (dialog));
6343
6344         gtk_widget_destroy (dialog);
6345 }
6346
6347 void
6348 modest_ui_actions_on_help (GtkAction *action,
6349                            GtkWindow *win)
6350 {
6351         /* Help app is not available at all in fremantle */
6352 #ifndef MODEST_TOOLKIT_HILDON2
6353         const gchar *help_id;
6354
6355         g_return_if_fail (win && GTK_IS_WINDOW(win));
6356
6357         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6358
6359         if (help_id)
6360                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6361 #endif
6362 }
6363
6364 void
6365 modest_ui_actions_on_csm_help (GtkAction *action,
6366                                GtkWindow *win)
6367 {
6368         /* Help app is not available at all in fremantle */
6369 #ifndef MODEST_TOOLKIT_HILDON2
6370
6371         const gchar* help_id = NULL;
6372         GtkWidget *folder_view;
6373         TnyFolderStore *folder_store;
6374
6375         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6376
6377         /* Get selected folder */
6378         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6379                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6380         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6381
6382         /* Switch help_id */
6383         if (folder_store && TNY_IS_FOLDER (folder_store))
6384                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6385
6386         if (folder_store)
6387                 g_object_unref (folder_store);
6388
6389         if (help_id)
6390                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6391         else
6392                 modest_ui_actions_on_help (action, win);
6393 #endif
6394 }
6395
6396 static void
6397 retrieve_contents_cb (ModestMailOperation *mail_op,
6398                       TnyHeader *header,
6399                       gboolean canceled,
6400                       TnyMsg *msg,
6401                       GError *err,
6402                       gpointer user_data)
6403 {
6404         /* We only need this callback to show an error in case of
6405            memory low condition */
6406         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6407                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6408         }
6409 }
6410
6411 static void
6412 retrieve_msg_contents_performer (gboolean canceled,
6413                                  GError *err,
6414                                  GtkWindow *parent_window,
6415                                  TnyAccount *account,
6416                                  gpointer user_data)
6417 {
6418         ModestMailOperation *mail_op;
6419         TnyList *headers = TNY_LIST (user_data);
6420
6421         if (err || canceled) {
6422                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6423                                                                 (GtkWidget *) parent_window, err,
6424                                                                 account, NULL);
6425                 goto out;
6426         }
6427
6428         /* Create mail operation */
6429         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6430                                                                  modest_ui_actions_disk_operations_error_handler,
6431                                                                  NULL, NULL);
6432         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6433         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6434
6435         /* Frees */
6436         g_object_unref (mail_op);
6437  out:
6438         g_object_unref (headers);
6439         g_object_unref (account);
6440 }
6441
6442 void
6443 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6444                                             ModestWindow *window)
6445 {
6446         TnyList *headers = NULL;
6447         TnyAccount *account = NULL;
6448         TnyIterator *iter = NULL;
6449         TnyHeader *header = NULL;
6450         TnyFolder *folder = NULL;
6451
6452         /* Get headers */
6453         headers = get_selected_headers (window);
6454         if (!headers)
6455                 return;
6456
6457         /* Pick the account */
6458         iter = tny_list_create_iterator (headers);
6459         header = TNY_HEADER (tny_iterator_get_current (iter));
6460         folder = tny_header_get_folder (header);
6461         account = tny_folder_get_account (folder);
6462         g_object_unref (folder);
6463         g_object_unref (header);
6464         g_object_unref (iter);
6465
6466         /* Connect and perform the message retrieval */
6467         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6468                                              g_object_ref (account),
6469                                              retrieve_msg_contents_performer,
6470                                              g_object_ref (headers));
6471
6472         /* Frees */
6473         g_object_unref (account);
6474         g_object_unref (headers);
6475 }
6476
6477 void
6478 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6479 {
6480         g_return_if_fail (MODEST_IS_WINDOW (window));
6481
6482         /* Update dimmed */
6483         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6484 }
6485
6486 void
6487 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6488 {
6489         g_return_if_fail (MODEST_IS_WINDOW (window));
6490
6491         /* Update dimmed */
6492         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6493 }
6494
6495 void
6496 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6497                                           ModestWindow *window)
6498 {
6499         g_return_if_fail (MODEST_IS_WINDOW (window));
6500
6501         /* Update dimmed */
6502         modest_ui_actions_check_menu_dimming_rules (window);
6503 }
6504
6505 void
6506 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6507                                           ModestWindow *window)
6508 {
6509         g_return_if_fail (MODEST_IS_WINDOW (window));
6510
6511         /* Update dimmed */
6512         modest_ui_actions_check_menu_dimming_rules (window);
6513 }
6514
6515 void
6516 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6517                                           ModestWindow *window)
6518 {
6519         g_return_if_fail (MODEST_IS_WINDOW (window));
6520
6521         /* Update dimmed */
6522         modest_ui_actions_check_menu_dimming_rules (window);
6523 }
6524
6525 void
6526 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6527                                             ModestWindow *window)
6528 {
6529         g_return_if_fail (MODEST_IS_WINDOW (window));
6530
6531         /* Update dimmed */
6532         modest_ui_actions_check_menu_dimming_rules (window);
6533 }
6534
6535 void
6536 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6537                                           ModestWindow *window)
6538 {
6539         g_return_if_fail (MODEST_IS_WINDOW (window));
6540
6541         /* Update dimmed */
6542         modest_ui_actions_check_menu_dimming_rules (window);
6543 }
6544
6545 void
6546 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6547                                           ModestWindow *window)
6548 {
6549         g_return_if_fail (MODEST_IS_WINDOW (window));
6550
6551         /* Update dimmed */
6552         modest_ui_actions_check_menu_dimming_rules (window);
6553 }
6554
6555 void
6556 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6557                                                  ModestWindow *window)
6558 {
6559         g_return_if_fail (MODEST_IS_WINDOW (window));
6560
6561         /* Update dimmed */
6562         modest_ui_actions_check_menu_dimming_rules (window);
6563 }
6564
6565 void
6566 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6567                                                      ModestWindow *window)
6568 {
6569         g_return_if_fail (MODEST_IS_WINDOW (window));
6570
6571         /* Update dimmed */
6572         modest_ui_actions_check_menu_dimming_rules (window);
6573 }
6574
6575 void
6576 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6577                                                      ModestWindow *window)
6578 {
6579         g_return_if_fail (MODEST_IS_WINDOW (window));
6580
6581         /* Update dimmed */
6582         modest_ui_actions_check_menu_dimming_rules (window);
6583 }
6584
6585 void
6586 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6587 {
6588         g_return_if_fail (MODEST_IS_WINDOW (window));
6589
6590         /* we check for low-mem; in that case, show a warning, and don't allow
6591          * searching
6592          */
6593         if (modest_platform_check_memory_low (window, TRUE))
6594                 return;
6595
6596         modest_platform_show_search_messages (GTK_WINDOW (window));
6597 }
6598
6599 void
6600 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6601 {
6602         g_return_if_fail (MODEST_IS_WINDOW (win));
6603
6604
6605         /* we check for low-mem; in that case, show a warning, and don't allow
6606          * for the addressbook
6607          */
6608         if (modest_platform_check_memory_low (win, TRUE))
6609                 return;
6610
6611
6612         modest_platform_show_addressbook (GTK_WINDOW (win));
6613 }
6614
6615
6616 void
6617 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6618                                           ModestWindow *window)
6619 {
6620         gboolean active;
6621         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6622
6623         if (GTK_IS_TOGGLE_ACTION (action))
6624                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6625         else
6626                 active = TRUE;
6627
6628         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6629                                                     active);
6630 }
6631
6632 #ifndef MODEST_TOOLKIT_HILDON2
6633 static void
6634 on_send_receive_finished (ModestMailOperation  *mail_op,
6635                            gpointer user_data)
6636 {
6637         GtkWidget *header_view, *folder_view;
6638         TnyFolderStore *folder_store;
6639         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6640
6641         /* Set send/receive operation finished */
6642         modest_main_window_notify_send_receive_completed (main_win);
6643
6644         /* Don't refresh the current folder if there were any errors */
6645         if (modest_mail_operation_get_status (mail_op) !=
6646             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6647                 return;
6648
6649         /* Refresh the current folder if we're viewing a window. We do
6650            this because the user won't be able to see the new mails in
6651            the selected folder after a Send&Receive because it only
6652            performs a poke_status, i.e, only the number of read/unread
6653            messages is updated, but the new headers are not
6654            downloaded */
6655         folder_view = modest_main_window_get_child_widget (main_win,
6656                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6657         if (!folder_view)
6658                 return;
6659
6660         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6661
6662         /* Do not need to refresh INBOX again because the
6663            update_account does it always automatically */
6664         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6665             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6666                 ModestMailOperation *refresh_op;
6667
6668                 header_view = modest_main_window_get_child_widget (main_win,
6669                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6670
6671                 /* We do not need to set the contents style
6672                    because it hasn't changed. We also do not
6673                    need to save the widget status. Just force
6674                    a refresh */
6675                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6676                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6677                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6678                                                       folder_refreshed_cb, main_win);
6679                 g_object_unref (refresh_op);
6680         }
6681
6682         if (folder_store)
6683                 g_object_unref (folder_store);
6684 }
6685 #endif
6686
6687 void
6688 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6689                                                 TnyHeader *header,
6690                                                 TnyMsg *msg,
6691                                                 GError *err,
6692                                                 gpointer user_data)
6693 {
6694         const gchar* server_name = NULL;
6695         TnyTransportAccount *transport;
6696         gchar *message = NULL;
6697         ModestProtocol *protocol;
6698
6699         /* Don't show anything if the user cancelled something or the
6700          * send receive request is not interactive. Authentication
6701          * errors are managed by the account store so no need to show
6702          * a dialog here again */
6703         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6704             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6705             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6706                 return;
6707
6708
6709         /* Get the server name. Note that we could be using a
6710            connection specific transport account */
6711         transport = (TnyTransportAccount *)
6712                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6713         if (transport) {
6714                 ModestTnyAccountStore *acc_store;
6715                 const gchar *acc_name;
6716                 TnyTransportAccount *conn_specific;
6717
6718                 acc_store = modest_runtime_get_account_store();
6719                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6720                 conn_specific = (TnyTransportAccount *)
6721                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6722                 if (conn_specific) {
6723                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6724                         g_object_unref (conn_specific);
6725                 } else {
6726                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6727                 }
6728                 g_object_unref (transport);
6729         }
6730
6731         /* Get protocol */
6732         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6733                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6734                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6735         if (!protocol) {
6736                 g_warning ("%s: Account with no proto", __FUNCTION__);
6737                 return;
6738         }
6739
6740         /* Show the appropriate message text for the GError: */
6741         switch (err->code) {
6742         case TNY_SERVICE_ERROR_CONNECT:
6743                 message = modest_protocol_get_translation (protocol,
6744                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6745                                                            server_name);
6746                 break;
6747         case TNY_SERVICE_ERROR_SEND:
6748                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6749                 break;
6750         case TNY_SERVICE_ERROR_UNAVAILABLE:
6751                 message = modest_protocol_get_translation (protocol,
6752                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6753                                                            server_name);
6754                 break;
6755         default:
6756                 g_warning ("%s: unexpected ERROR %d",
6757                            __FUNCTION__, err->code);
6758                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6759                 break;
6760         }
6761
6762         modest_platform_run_information_dialog (NULL, message, FALSE);
6763         g_free (message);
6764 }
6765
6766 void
6767 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6768                                                 gchar *msg_id,
6769                                                 guint status,
6770                                                 gpointer user_data)
6771 {
6772         ModestWindow *top_window = NULL;
6773         ModestWindowMgr *mgr = NULL;
6774         GtkWidget *header_view = NULL;
6775         TnyFolder *selected_folder = NULL;
6776         TnyFolderType folder_type;
6777
6778         mgr = modest_runtime_get_window_mgr ();
6779         top_window = modest_window_mgr_get_current_top (mgr);
6780
6781         if (!top_window)
6782                 return;
6783
6784 #ifndef MODEST_TOOLKIT_HILDON2
6785         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6786                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6787                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6788         }
6789 #else
6790         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6791                 header_view = (GtkWidget *)
6792                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6793         }
6794 #endif
6795
6796         /* Get selected folder */
6797         if (header_view)
6798                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6799         if (!selected_folder)
6800                 return;
6801
6802         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6803 #if GTK_CHECK_VERSION(2, 8, 0)
6804         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6805         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6806                 GtkTreeViewColumn *tree_column;
6807
6808                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6809                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6810                 if (tree_column)
6811                         gtk_tree_view_column_queue_resize (tree_column);
6812                 }
6813 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6814         gtk_widget_queue_draw (header_view);
6815 #endif
6816
6817 #ifndef MODEST_TOOLKIT_HILDON2
6818         /* Rerun dimming rules, because the message could become deletable for example */
6819         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6820                                                  MODEST_DIMMING_RULES_TOOLBAR);
6821         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6822                                                  MODEST_DIMMING_RULES_MENU);
6823 #endif
6824
6825         /* Free */
6826         g_object_unref (selected_folder);
6827 }
6828
6829 void
6830 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6831                                                TnyAccount *account)
6832 {
6833         ModestProtocolType protocol_type;
6834         ModestProtocol *protocol;
6835         gchar *error_note = NULL;
6836
6837         protocol_type = modest_tny_account_get_protocol_type (account);
6838         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6839                                                                   protocol_type);
6840
6841         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6842         if (error_note == NULL) {
6843                 g_warning ("%s: This should not be reached", __FUNCTION__);
6844         } else {
6845                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6846                 g_free (error_note);
6847         }
6848 }
6849
6850 gchar *
6851 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6852 {
6853         gchar *msg = NULL;
6854         gchar *subject;
6855         TnyFolderStore *folder = NULL;
6856         TnyAccount *account = NULL;
6857         ModestProtocolType proto;
6858         ModestProtocol *protocol;
6859         TnyHeader *header = NULL;
6860
6861 #ifndef MODEST_TOOLKIT_HILDON2
6862         if (MODEST_IS_MAIN_WINDOW (win)) {
6863                 GtkWidget *header_view;
6864                 TnyList* headers = NULL;
6865                 TnyIterator *iter;
6866                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6867                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6868                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6869                 if (!headers || tny_list_get_length (headers) == 0) {
6870                         if (headers)
6871                                 g_object_unref (headers);
6872                         return NULL;
6873                 }
6874                 iter = tny_list_create_iterator (headers);
6875                 header = TNY_HEADER (tny_iterator_get_current (iter));
6876                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6877                 g_object_unref (iter);
6878                 g_object_unref (headers);
6879 #else
6880         if (MODEST_IS_HEADER_WINDOW (win)) {
6881                 GtkWidget *header_view;
6882                 TnyList* headers = NULL;
6883                 TnyIterator *iter;
6884                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6885                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6886                 if (!headers || tny_list_get_length (headers) == 0) {
6887                         if (headers)
6888                                 g_object_unref (headers);
6889                         return NULL;
6890                 }
6891                 iter = tny_list_create_iterator (headers);
6892                 header = TNY_HEADER (tny_iterator_get_current (iter));
6893                 if (header) {
6894                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6895                 } else {
6896                         g_warning ("List should contain headers");
6897                 }
6898                 g_object_unref (iter);
6899                 g_object_unref (headers);
6900 #endif
6901         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6902                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6903                 if (header)
6904                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6905         }
6906
6907         if (!header || !folder)
6908                 goto frees;
6909
6910         /* Get the account type */
6911         account = tny_folder_get_account (TNY_FOLDER (folder));
6912         proto = modest_tny_account_get_protocol_type (account);
6913         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6914                                                                   proto);
6915
6916         subject = tny_header_dup_subject (header);
6917         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6918         if (subject)
6919                 g_free (subject);
6920         if (msg == NULL) {
6921                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6922         }
6923
6924  frees:
6925         /* Frees */
6926         if (account)
6927                 g_object_unref (account);
6928         if (folder)
6929                 g_object_unref (folder);
6930         if (header)
6931                 g_object_unref (header);
6932
6933         return msg;
6934 }
6935
6936 gboolean
6937 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6938                                      const gchar *account_name,
6939                                      const gchar *account_title)
6940 {
6941         ModestAccountMgr *account_mgr;
6942         gchar *txt = NULL;
6943         gint response;
6944         ModestProtocol *protocol;
6945         gboolean removed = FALSE;
6946
6947         g_return_val_if_fail (account_name, FALSE);
6948         g_return_val_if_fail (account_title, FALSE);
6949
6950         account_mgr = modest_runtime_get_account_mgr();
6951
6952         /* The warning text depends on the account type: */
6953         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6954                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6955                                                                                                          account_name));
6956         txt = modest_protocol_get_translation (protocol,
6957                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6958                                                account_title);
6959         if (txt == NULL)
6960                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6961
6962         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6963         g_free (txt);
6964         txt = NULL;
6965
6966         if (response == GTK_RESPONSE_OK) {
6967                 /* Remove account. If it succeeds then it also removes
6968                    the account from the ModestAccountView: */
6969                 gboolean is_default = FALSE;
6970                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6971                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6972                         is_default = TRUE;
6973                 g_free (default_account_name);
6974
6975                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6976                 if (removed) {
6977                         /* Close all email notifications, we cannot
6978                            distinguish if the notification belongs to
6979                            this account or not, so for safety reasons
6980                            we remove them all */
6981                         modest_platform_remove_new_mail_notifications (FALSE);
6982                 } else {
6983                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6984                 }
6985         }
6986         return removed;
6987 }
6988
6989 static void
6990 on_fetch_images_performer (gboolean canceled,
6991                            GError *err,
6992                            GtkWindow *parent_window,
6993                            TnyAccount *account,
6994                            gpointer user_data)
6995 {
6996         if (err || canceled) {
6997                 /* Show an unable to retrieve images ??? */
6998                 return;
6999         }
7000
7001         /* Note that the user could have closed the window while connecting */
7002         if (GTK_WIDGET_VISIBLE (parent_window))
7003                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
7004         g_object_unref ((GObject *) user_data);
7005 }
7006
7007 void
7008 modest_ui_actions_on_fetch_images (GtkAction *action,
7009                                    ModestWindow *window)
7010 {
7011         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
7012
7013         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
7014                                              NULL,
7015                                              on_fetch_images_performer, 
7016                                              g_object_ref (window));
7017 }
7018
7019 void
7020 modest_ui_actions_on_reload_message (const gchar *msg_id)
7021 {
7022         ModestWindow *window = NULL;
7023
7024         g_return_if_fail (msg_id && msg_id[0] != '\0');
7025         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
7026                                                             msg_id,
7027                                                             &window))
7028                 return;
7029
7030
7031         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
7032                 return;
7033
7034         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
7035 }
7036
7037 /** Check whether any connections are active, and cancel them if 
7038  * the user wishes.
7039  * Returns TRUE is there was no problem, 
7040  * or if an operation was cancelled so we can continue.
7041  * Returns FALSE if the user chose to cancel his request instead.
7042  */
7043
7044 gboolean
7045 modest_ui_actions_check_for_active_account (ModestWindow *self,
7046                                             const gchar* account_name)
7047 {
7048         ModestTnySendQueue *send_queue;
7049         ModestTnyAccountStore *acc_store;
7050         ModestMailOperationQueue* queue;
7051         TnyConnectionStatus store_conn_status;
7052         TnyAccount *store_account = NULL, *transport_account = NULL;
7053         gboolean retval = TRUE, sending = FALSE;
7054
7055         acc_store = modest_runtime_get_account_store ();
7056         queue = modest_runtime_get_mail_operation_queue ();
7057
7058         store_account = 
7059                 modest_tny_account_store_get_server_account (acc_store,
7060                                                              account_name,
7061                                                              TNY_ACCOUNT_TYPE_STORE);
7062
7063         /* This could happen if the account was deleted before the
7064            call to this function */
7065         if (!store_account)
7066                 return FALSE;
7067
7068         transport_account = 
7069                 modest_tny_account_store_get_server_account (acc_store,
7070                                                              account_name,
7071                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
7072
7073         /* This could happen if the account was deleted before the
7074            call to this function */
7075         if (!transport_account) {
7076                 g_object_unref (store_account);
7077                 return FALSE;
7078         }
7079
7080         /* If the transport account was not used yet, then the send
7081            queue could not exist (it's created on demand) */
7082         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
7083         if (TNY_IS_SEND_QUEUE (send_queue))
7084                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
7085
7086         store_conn_status = tny_account_get_connection_status (store_account);
7087         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
7088                 gint response;
7089
7090                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
7091                                                                 _("emev_nc_disconnect_account"));
7092                 if (response == GTK_RESPONSE_OK) {
7093                         retval = TRUE;
7094                 } else {
7095                         retval = FALSE;
7096                 }
7097         }
7098
7099         if (retval) {
7100
7101                 /* FIXME: We should only cancel those of this account */
7102                 modest_mail_operation_queue_cancel_all (queue);
7103
7104                 /* Also disconnect the account */
7105                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
7106                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
7107                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
7108                                                       FALSE, NULL, NULL);
7109                 }
7110                 if (sending) {
7111                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
7112                                                       FALSE, NULL, NULL);
7113                 }
7114         }
7115                 
7116         /* Frees */
7117         g_object_unref (store_account);
7118         g_object_unref (transport_account);
7119         
7120         return retval;
7121 }