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