* src/modest-ui-actions.c:
[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-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
57
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
70
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
74
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
81
82 #include <gtkhtml/gtkhtml.h>
83
84 typedef struct _GetMsgAsyncHelper {     
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;     
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         GtkWidget *parent_window;
104 } ReplyForwardHelper;
105
106 typedef struct _MoveToHelper {
107         ModestMailOperation *mail_op;
108         TnyFolder *folder;
109 } MoveToHelper;
110
111 typedef struct _PasteAsAttachmentHelper {
112         ModestMsgEditWindow *window;
113         GtkWidget *banner;
114 } PasteAsAttachmentHelper;
115
116
117 /*
118  * The do_headers_action uses this kind of functions to perform some
119  * action to each member of a list of headers
120  */
121 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
122
123 static void     do_headers_action     (ModestWindow *win, 
124                                        HeadersFunc func,
125                                        gpointer user_data);
126
127 static void     open_msg_cb            (ModestMailOperation *mail_op, 
128                                         TnyHeader *header, 
129                                         TnyMsg *msg,
130                                         gpointer user_data);
131
132 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
133                                         TnyHeader *header, 
134                                         TnyMsg *msg,
135                                         gpointer user_data);
136
137 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
138
139 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
140                                         TnyFolder *folder, 
141                                         gpointer user_data);
142
143 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
144                                                    ModestMailOperationState *state,
145                                                    gpointer user_data);
146
147 static gint header_list_count_uncached_msgs (TnyList *header_list);
148 static gboolean connect_to_get_msg (
149                                                 GtkWindow *win,
150                                                 gint num_of_uncached_msgs);
151
152 static gboolean remote_folder_is_pop (const TnyFolderStore *folder);
153
154 static gboolean msgs_already_deleted_from_server ( TnyList *headers,
155                                                    const TnyFolderStore *src_folder);
156
157
158 /*
159  * This function checks whether a TnyFolderStore is a pop account
160  */
161 static gboolean
162 remote_folder_is_pop (const TnyFolderStore *folder)
163 {
164         const gchar *proto = NULL;
165         TnyAccount *account = NULL;
166
167         g_return_val_if_fail (TNY_IS_FOLDER_STORE(folder), FALSE);
168
169         if (TNY_IS_ACCOUNT (folder)) {
170                 account = TNY_ACCOUNT(folder);
171                 g_object_ref(account);
172         } else if (TNY_IS_FOLDER (folder)) {
173                 account = tny_folder_get_account(TNY_FOLDER(folder));
174         }
175
176         proto = tny_account_get_proto(account);
177         g_object_unref (account);
178
179         return proto &&
180           (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
181 }
182
183 /*
184  * This functions checks whether if a list of messages are already
185  * deleted from the server: that is, if the server is a POP account
186  * and all messages are already cached.
187  */
188 static gboolean
189 msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_folder)
190 {
191         g_return_val_if_fail (TNY_IS_FOLDER_STORE(src_folder), FALSE);
192         g_return_val_if_fail (TNY_IS_LIST(headers), FALSE);
193
194         gboolean src_is_pop = remote_folder_is_pop (src_folder);
195         gint uncached_msgs = header_list_count_uncached_msgs (headers);
196
197         return (src_is_pop && !uncached_msgs);
198 }
199
200 /* Show the account creation wizard dialog.
201  * returns: TRUE if an account was created. FALSE if the user cancelled.
202  */
203 gboolean
204 modest_run_account_setup_wizard (ModestWindow *win)
205 {
206         gboolean result = FALSE;
207         GtkDialog *wizard;
208         
209         wizard = modest_window_mgr_get_easysetup_dialog
210                 (modest_runtime_get_window_mgr());
211         if (wizard) {
212                 /* old wizard is active already; present it and
213                  * act as if the user cancelled the non-existing
214                  * new one
215                  */
216                 printf ("wizard already active\n");
217                 return FALSE;
218         } else {
219                 /* there is no such wizard yet */
220                 wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ());
221                 modest_window_mgr_set_easysetup_dialog
222                         (modest_runtime_get_window_mgr(), GTK_DIALOG(wizard));
223         } 
224
225         
226         /* always present a main window in the background 
227          * we do it here, so we cannot end up with to wizards (as this
228          * function might be called in modest_window_mgr_get_main_window as well */
229         if (!win) 
230                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
231
232         /* make sure the mainwindow is visible */
233         gtk_widget_show_all (GTK_WIDGET(win));
234         gtk_window_present (GTK_WINDOW(win));
235
236         
237         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
238
239         /* Don't make this a modal window, because secondary windows will then 
240          * be unusable, freezing the UI: */
241         /* gtk_window_set_modal (GTK_WINDOW (wizard), TRUE); */
242         
243         gint dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
244         if (dialog_response == GTK_RESPONSE_CANCEL)
245                 result = FALSE;
246         else {
247                 /* Check whether an account was created: */
248                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
249         }
250         
251         gtk_widget_destroy (GTK_WIDGET (wizard));
252
253         /* clear it from the window mgr */
254         modest_window_mgr_set_easysetup_dialog
255                 (modest_runtime_get_window_mgr(), NULL);
256         
257         return result;
258 }
259
260
261 void   
262 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
263 {
264         GtkWidget *about;
265         const gchar *authors[] = {
266                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
267                 NULL
268         };
269         about = gtk_about_dialog_new ();
270         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
271         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
272         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
273                                         _("Copyright (c) 2006, Nokia Corporation\n"
274                                           "All rights reserved."));
275         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
276                                        _("a modest e-mail client\n\n"
277                                          "design and implementation: Dirk-Jan C. Binnema\n"
278                                          "contributions from the fine people at KC and Ig\n"
279                                          "uses the tinymail email framework written by Philip van Hoof"));
280         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
281         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
282         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
283         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
284         
285         gtk_dialog_run (GTK_DIALOG (about));
286         gtk_widget_destroy(about);
287 }
288
289 /*
290  * Gets the list of currently selected messages. If the win is the
291  * main window, then it returns a newly allocated list of the headers
292  * selected in the header view. If win is the msg view window, then
293  * the value returned is a list with just a single header.
294  *
295  * The caller of this funcion must free the list.
296  */
297 static TnyList *
298 get_selected_headers (ModestWindow *win)
299 {
300         if (MODEST_IS_MAIN_WINDOW(win)) {
301                 GtkWidget *header_view;         
302                 
303                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
304                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
305                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
306                 
307         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
308                 /* for MsgViewWindows, we simply return a list with one element */
309                 TnyHeader *header;
310                 TnyList *list = NULL;
311                 
312                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
313                 if (header != NULL) {
314                         list = tny_simple_list_new ();
315                         tny_list_prepend (list, G_OBJECT(header));
316                         g_object_unref (G_OBJECT(header));
317                 }
318
319                 return list;
320
321         } else
322                 return NULL;
323 }
324
325 static void
326 headers_action_mark_as_read (TnyHeader *header,
327                              ModestWindow *win,
328                              gpointer user_data)
329 {
330         TnyHeaderFlags flags;
331
332         g_return_if_fail (TNY_IS_HEADER(header));
333
334         flags = tny_header_get_flags (header);
335         if (flags & TNY_HEADER_FLAG_SEEN) return;
336         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
337 }
338
339 static void
340 headers_action_mark_as_unread (TnyHeader *header,
341                                ModestWindow *win,
342                                gpointer user_data)
343 {
344         TnyHeaderFlags flags;
345
346         g_return_if_fail (TNY_IS_HEADER(header));
347
348         flags = tny_header_get_flags (header);
349         if (flags & TNY_HEADER_FLAG_SEEN)  {
350                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
351         }
352 }
353
354 /** A convenience method, because deleting a message is 
355  * otherwise complicated, and it's best to change it in one place 
356  * when we change it.
357  */
358 void modest_do_message_delete (TnyHeader *header, ModestWindow *win)
359 {
360         ModestMailOperation *mail_op = NULL;
361         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
362                 win ? G_OBJECT(win) : NULL);
363         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
364                                          mail_op);
365         
366         /* Always delete. TODO: Move to trash still not supported */
367         modest_mail_operation_remove_msg (mail_op, header, FALSE);
368         g_object_unref (G_OBJECT (mail_op));
369 }
370
371 /** A convenience method, because deleting a message is 
372  * otherwise complicated, and it's best to change it in one place 
373  * when we change it.
374  */
375 void modest_do_messages_delete (TnyList *headers, ModestWindow *win)
376 {
377         ModestMailOperation *mail_op = NULL;
378         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
379                 win ? G_OBJECT(win) : NULL);
380         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
381                                          mail_op);
382         
383         /* Always delete. TODO: Move to trash still not supported */
384         modest_mail_operation_remove_msgs (mail_op, headers, FALSE);
385         g_object_unref (G_OBJECT (mail_op));
386 }
387
388 /** After deleing a message that is currently visible in a window, 
389  * show the next message from the list, or close the window if there are no more messages.
390  **/
391 void 
392 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
393 {
394         /* Close msg view window or select next */
395         if (modest_msg_view_window_last_message_selected (win) &&
396                 modest_msg_view_window_first_message_selected (win)) {
397                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
398         } else if (!modest_msg_view_window_select_next_message (win)) {
399                 gboolean ret_value;
400                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
401         }
402 }
403
404 void
405 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
406 {
407         TnyList *header_list = NULL;
408         TnyIterator *iter = NULL;
409         TnyHeader *header = NULL;
410         gchar *message = NULL;
411         gchar *desc = NULL;
412         gint response;
413         ModestWindowMgr *mgr;
414         GtkWidget *header_view = NULL;
415
416         g_return_if_fail (MODEST_IS_WINDOW(win));
417         
418         /* Check first if the header view has the focus */
419         if (MODEST_IS_MAIN_WINDOW (win)) {
420                 header_view = 
421                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
422                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
423                 if (!gtk_widget_is_focus (header_view))
424                         return;
425         }
426         
427         /* Get the headers, either from the header view (if win is the main window),
428          * or from the message view window: */
429         header_list = get_selected_headers (win);
430         if (!header_list) return;
431                         
432         /* Check if any of the headers are already opened, or in the process of being opened */
433         if (MODEST_IS_MAIN_WINDOW (win)) {
434                 gint opened_headers = 0;
435
436                 iter = tny_list_create_iterator (header_list);
437                 mgr = modest_runtime_get_window_mgr ();
438                 while (!tny_iterator_is_done (iter)) {
439                         header = TNY_HEADER (tny_iterator_get_current (iter));
440                         if (header) {
441                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
442                                         opened_headers++;
443                                 g_object_unref (header);
444                         }
445                         tny_iterator_next (iter);
446                 }
447                 g_object_unref (iter);
448
449                 if (opened_headers > 0) {
450                         gchar *msg;
451
452                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
453                                                opened_headers);
454
455                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
456                         
457                         g_free (msg);
458                         g_object_unref (header_list);
459                         return;
460                 }
461         }
462
463         /* Select message */
464         if (tny_list_get_length(header_list) == 1) {
465                 iter = tny_list_create_iterator (header_list);
466                 header = TNY_HEADER (tny_iterator_get_current (iter));
467                 if (header) {
468                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
469                         g_object_unref (header);
470                 }
471
472                 g_object_unref (iter);
473         }
474         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
475                                            tny_list_get_length(header_list)), desc);
476
477         /* Confirmation dialog */
478         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
479                                                             message);
480         
481
482         if (response == GTK_RESPONSE_OK) {      
483                 ModestWindow *main_window = NULL;
484                 ModestWindowMgr *mgr = NULL;
485                 GtkTreeModel *model = NULL;
486                 GtkTreeSelection *sel = NULL;
487                 GList *sel_list = NULL, *tmp = NULL;
488                 GtkTreeRowReference *next_row_reference = NULL;
489                 GtkTreeRowReference *prev_row_reference = NULL;
490                 GtkTreePath *next_path = NULL;
491                 GtkTreePath *prev_path = NULL;
492                 GError *err = NULL;
493
494                 /* Find last selected row */                    
495                 if (MODEST_IS_MAIN_WINDOW (win)) {
496                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
497                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
498                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
499                         for (tmp=sel_list; tmp; tmp=tmp->next) {
500                                 if (tmp->next == NULL) {
501                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
502                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
503
504                                         gtk_tree_path_prev (prev_path);
505                                         gtk_tree_path_next (next_path);
506
507                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
508                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
509                                 }
510                         }
511                 }
512                 
513                 /* Disable window dimming management */
514                 modest_window_disable_dimming (MODEST_WINDOW(win));
515
516                 /* Remove each header. If it's a view window header_view == NULL */
517                 modest_do_messages_delete (header_list, win);
518                 
519                 /* Enable window dimming management */
520                 if (sel != NULL) {
521                         gtk_tree_selection_unselect_all (sel);
522                 }
523                 modest_window_enable_dimming (MODEST_WINDOW(win));
524                 
525                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
526                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
527                         
528                         /* Get main window */
529                         mgr = modest_runtime_get_window_mgr ();
530                         main_window = modest_window_mgr_get_main_window (mgr);
531                 }
532                 else {                  
533                         /* Move cursor to next row */
534                         main_window = win; 
535
536                         /* Select next or previous row */
537                         if (gtk_tree_row_reference_valid (next_row_reference)) {
538 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
539                                 gtk_tree_selection_select_path (sel, next_path);
540                         }
541                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
542                                 gtk_tree_selection_select_path (sel, prev_path);
543                         }
544
545                         /* Free */
546                         if (next_row_reference != NULL) 
547                                 gtk_tree_row_reference_free (next_row_reference);
548                         if (next_path != NULL) 
549                                 gtk_tree_path_free (next_path);                         
550                         if (prev_row_reference != NULL) 
551                                 gtk_tree_row_reference_free (prev_row_reference);
552                         if (prev_path != NULL) 
553                                 gtk_tree_path_free (prev_path);                         
554                 }
555
556                 if (err != NULL) {
557                         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, err->code, err->message);
558                         g_error_free(err);
559                 }
560                 
561                 /* Update toolbar dimming state */
562                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
563
564                 /* Free */
565                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
566                 g_list_free (sel_list);
567         }
568
569         /* Free*/
570         g_free(message);
571         g_free(desc);
572         g_object_unref (header_list);
573 }
574
575
576
577
578 /* delete either message or folder, based on where we are */
579 void
580 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
581 {
582         g_return_if_fail (MODEST_IS_WINDOW(win));
583         
584         /* Check first if the header view has the focus */
585         if (MODEST_IS_MAIN_WINDOW (win)) {
586                 GtkWidget *w;
587                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
588                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
589                 if (gtk_widget_is_focus (w)) {
590                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
591                         return;
592                 }
593         }
594         modest_ui_actions_on_delete_message (action, win);
595 }
596
597
598
599 void
600 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
601 {       
602         ModestWindowMgr *mgr = NULL;
603         
604 #ifdef MODEST_PLATFORM_MAEMO
605         modest_osso_save_state();
606 #endif /* MODEST_PLATFORM_MAEMO */
607
608         g_debug ("closing down, clearing %d item(s) from operation queue",
609                  modest_mail_operation_queue_num_elements
610                  (modest_runtime_get_mail_operation_queue()));
611
612         /* cancel all outstanding operations */
613         modest_mail_operation_queue_cancel_all 
614                 (modest_runtime_get_mail_operation_queue());
615         
616         g_debug ("queue has been cleared");
617
618
619         /* Check if there are opened editing windows */ 
620         mgr = modest_runtime_get_window_mgr ();
621         modest_window_mgr_close_all_windows (mgr);
622
623         /* note: when modest-tny-account-store is finalized,
624            it will automatically set all network connections
625            to offline */
626
627 /*      gtk_main_quit (); */
628 }
629
630 void
631 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
632 {
633         gboolean ret_value;
634
635         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
636
637 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
638 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
639 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
640 /*              gboolean ret_value; */
641 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
642 /*      } else if (MODEST_IS_WINDOW (win)) { */
643 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
644 /*      } else { */
645 /*              g_return_if_reached (); */
646 /*      } */
647 }
648
649 void
650 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
651 {
652         GtkClipboard *clipboard = NULL;
653         gchar *selection = NULL;
654
655         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
656         selection = gtk_clipboard_wait_for_text (clipboard);
657
658         /* Question: why is the clipboard being used here? 
659          * It doesn't really make a lot of sense. */
660
661         if (selection)
662         {
663                 modest_address_book_add_address (selection);
664                 g_free (selection);
665         }
666 }
667
668 void
669 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
670 {
671         /* This is currently only implemented for Maemo */
672 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
673         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
674                 modest_run_account_setup_wizard (win);
675                 return;
676         } else  {
677                 /* Show the list of accounts: */
678                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
679                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
680                 
681                 /* The accounts dialog must be modal  */
682                 gtk_window_set_modal (GTK_WINDOW (account_win), TRUE);
683                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); 
684         }
685 #else
686         GtkWidget *dialog, *label;
687         
688         /* Create the widgets */
689         
690         dialog = gtk_dialog_new_with_buttons ("Message",
691                                               GTK_WINDOW(win),
692                                               GTK_DIALOG_DESTROY_WITH_PARENT,
693                                               GTK_STOCK_OK,
694                                               GTK_RESPONSE_NONE,
695                                               NULL);
696         label = gtk_label_new ("Hello World!");
697         
698         /* Ensure that the dialog box is destroyed when the user responds. */
699         
700         g_signal_connect_swapped (dialog, "response", 
701                                   G_CALLBACK (gtk_widget_destroy),
702                                   dialog);
703         
704         /* Add the label, and show everything we've added to the dialog. */
705         
706         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
707                            label);
708         gtk_widget_show_all (dialog);
709 #endif /* MODEST_PLATFORM_MAEMO */
710 }
711
712 static void
713 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
714 {
715         /* Save any changes. */
716         modest_connection_specific_smtp_window_save_server_accounts (
717                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
718         gtk_widget_destroy (GTK_WIDGET (window));
719 }
720
721
722
723 void
724 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
725 {
726         /* This is currently only implemented for Maemo,
727          * because it requires an API (libconic) to detect different connection 
728          * possiblities.
729          */
730 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
731         
732         /* Create the window if necessary: */
733         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
734         modest_connection_specific_smtp_window_fill_with_connections (
735                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
736                 modest_runtime_get_account_mgr());
737
738         /* Show the window: */  
739         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
740         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
741         gtk_widget_show (specific_window);
742     
743         /* Save changes when the window is hidden: */
744         g_signal_connect (specific_window, "hide", 
745                 G_CALLBACK (on_smtp_servers_window_hide), win);
746 #endif /* MODEST_PLATFORM_MAEMO */
747 }
748
749 void
750 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
751 {
752         ModestWindow *msg_win = NULL;
753         TnyMsg *msg = NULL;
754         TnyFolder *folder = NULL;
755         gchar *account_name = NULL;
756         gchar *from_str = NULL;
757 /*      GError *err = NULL; */
758         TnyAccount *account = NULL;
759         ModestWindowMgr *mgr;
760         gchar *signature = NULL, *blank_and_signature = NULL;
761
762         /* if there are no accounts yet, just show the wizard */
763         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
764                         const gboolean created = modest_run_account_setup_wizard (win);
765                         if (!created)
766                                 return;
767         }
768         
769         account_name = g_strdup (modest_window_get_active_account (win));
770         if (!account_name)
771                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
772         if (!account_name) {
773                 g_printerr ("modest: no account found\n");
774                 goto cleanup;
775         }
776         
777         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
778                                                                        account_name,
779                                                                        TNY_ACCOUNT_TYPE_STORE);
780         if (!account) {
781                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
782                 goto cleanup;
783         }
784
785         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
786         if (!from_str) {
787                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
788                 goto cleanup;
789         }
790
791         gboolean use_signature = FALSE;
792         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr (), account_name, &use_signature);
793
794         if (use_signature) {
795                 blank_and_signature = g_strconcat ("\n", signature, NULL);
796         } else {
797                 blank_and_signature = g_strdup ("");
798         }
799
800         g_free (signature);
801
802         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
803         if (!msg) {
804                 g_printerr ("modest: failed to create new msg\n");
805                 goto cleanup;
806         }
807         
808         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
809         if (!folder) {
810                 g_printerr ("modest: failed to find Drafts folder\n");
811                 goto cleanup;
812         }
813         
814         
815         /* Create and register edit window */
816         /* This is destroyed by TODO. */
817         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
818         mgr = modest_runtime_get_window_mgr ();
819         modest_window_mgr_register_window (mgr, msg_win);
820
821         if (win)
822                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
823                                               GTK_WINDOW (win));
824         gtk_widget_show_all (GTK_WIDGET (msg_win));
825
826 cleanup:
827         g_free (account_name);
828         g_free (from_str);
829         g_free (blank_and_signature);
830         if (msg_win)
831                 g_object_unref (msg_win);
832         if (account)
833                 g_object_unref (G_OBJECT(account));
834         if (msg)
835                 g_object_unref (G_OBJECT(msg));
836         if (folder)
837                 g_object_unref (G_OBJECT(folder));
838 }
839
840 gboolean 
841 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
842                                        TnyHeader *header,
843                                        TnyMsg *msg)
844 {
845         ModestMailOperationStatus status;
846
847         /* If there is no message or the operation was not successful */
848         status = modest_mail_operation_get_status (mail_op);
849         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
850
851                 /* Remove the header from the preregistered uids */
852                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
853                                                      header);
854
855                 return FALSE;
856         }
857
858         return TRUE;
859 }
860
861 static void
862 open_msg_cb (ModestMailOperation *mail_op, TnyHeader *header,  TnyMsg *msg, gpointer user_data)
863 {
864         ModestWindowMgr *mgr = NULL;
865         ModestWindow *parent_win = NULL;
866         ModestWindow *win = NULL;
867         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
868         gchar *account = NULL;
869         TnyFolder *folder;
870         
871         /* Do nothing if there was any problem with the mail
872            operation. The error will be shown by the error_handler of
873            the mail operation */
874         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
875                 return;
876
877         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
878         folder = tny_header_get_folder (header);
879
880         /* Mark header as read */
881         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
882
883         /* Get account */
884         account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
885         if (!account)
886                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
887         
888         /* Gets folder type (OUTBOX headers will be opened in edit window */
889         if (modest_tny_folder_is_local_folder (folder))
890                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
891
892         /* If the header is in the drafts folder then open the editor,
893            else the message view window */
894         if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
895             (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
896                 /* we cannot edit without a valid account... */
897                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
898                         const gboolean created = modest_run_account_setup_wizard(parent_win);
899                         if (!created)
900                                 goto cleanup;
901                 }
902                 win = modest_msg_edit_window_new (msg, account, TRUE);
903
904
905                 /* Show banner */
906                 modest_platform_information_banner (NULL, NULL, _("mail_ib_opening_draft_message"));
907
908         } else {
909                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
910                 
911                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
912                         GtkWidget *header_view;
913                         GtkTreeSelection *sel;
914                         GList *sel_list = NULL;
915                         GtkTreeModel *model;
916                         
917                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
918                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
919
920                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
921                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
922
923                         if (sel_list != NULL) {
924                                 GtkTreeRowReference *row_reference;
925
926                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
927                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
928                                 g_list_free (sel_list);
929                                 
930                                 win = modest_msg_view_window_new_with_header_model (
931                                                 msg, account, (const gchar*) uid,
932                                                 model, row_reference);
933                                 gtk_tree_row_reference_free (row_reference);
934                         } else {
935                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
936                         }
937                 } else {
938                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
939                 }
940                 g_free (uid);
941         }
942         
943         /* Register and show new window */
944         if (win != NULL) {
945                 mgr = modest_runtime_get_window_mgr ();
946                 modest_window_mgr_register_window (mgr, win);
947                 g_object_unref (win);
948                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
949                 gtk_widget_show_all (GTK_WIDGET(win));
950         }
951
952         /* Update toolbar dimming state */
953         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
954                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
955         }
956
957 cleanup:
958         /* Free */
959         g_free(account);
960         g_object_unref (parent_win);
961         g_object_unref (folder);
962 }
963
964 void
965 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
966                                                gpointer user_data)
967 {
968         const GError *error;
969         GObject *win = modest_mail_operation_get_source (mail_op);
970
971         error = modest_mail_operation_get_error (mail_op);
972 /*      printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message); */
973  
974         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
975
976                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
977                                                         error->message);
978         } else {
979                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
980                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
981         }
982
983         if (win)
984                 g_object_unref (win);
985 }
986
987 /*
988  * This function is used by both modest_ui_actions_on_open and
989  * modest_ui_actions_on_header_activated. This way we always do the
990  * same when trying to open messages.
991  */
992 static void
993 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
994 {
995         ModestWindowMgr *mgr = NULL;
996         TnyIterator *iter = NULL;
997         ModestMailOperation *mail_op = NULL;
998         TnyList *not_opened_headers = NULL;
999         TnyHeaderFlags flags = 0;
1000                 
1001         g_return_if_fail (headers != NULL);
1002
1003         /* Check that only one message is selected for opening */
1004         if (tny_list_get_length (headers) != 1) {
1005                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1006                                                         _("mcen_ib_select_one_message"));
1007                 return;
1008         }
1009
1010
1011         /* Look if we already have a message view for each header. If
1012            true, then remove the header from the list of headers to
1013            open */
1014         mgr = modest_runtime_get_window_mgr ();
1015         iter = tny_list_create_iterator (headers);
1016         not_opened_headers = tny_simple_list_new ();
1017         
1018         while (!tny_iterator_is_done (iter)) {
1019
1020                 ModestWindow *window = NULL;
1021                 TnyHeader *header = NULL;
1022                 gboolean found = FALSE;
1023                 
1024                 header = TNY_HEADER (tny_iterator_get_current (iter));
1025                 if (header)
1026                         flags = tny_header_get_flags (header);
1027
1028                 window = NULL;
1029                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1030                 
1031                 /* Do not open again the message and present the
1032                    window to the user */
1033                 if (found) {
1034                         if (window)
1035                                 gtk_window_present (GTK_WINDOW (window));
1036                         else
1037                                 /* the header has been registered already, we don't do
1038                                  * anything but wait for the window to come up*/
1039                                 g_debug ("header %p already registered, waiting for window", header);
1040                 } else {
1041                         tny_list_append (not_opened_headers, G_OBJECT (header));
1042                 }
1043
1044                 if (header)
1045                         g_object_unref (header);
1046
1047                 tny_iterator_next (iter);
1048         }
1049         g_object_unref (iter);
1050         iter = NULL;
1051         
1052         /* If some messages would have to be downloaded, ask the user to 
1053          * make a connection. It's generally easier to do this here (in the mainloop) 
1054          * than later in a thread:
1055          */
1056         if (tny_list_get_length (not_opened_headers) > 0) {
1057                 TnyIterator *iter;
1058                 gboolean found = FALSE;
1059
1060                 iter = tny_list_create_iterator (not_opened_headers);
1061                 while (!tny_iterator_is_done (iter) && !found) {
1062                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1063                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1064                                 found = TRUE;
1065                         else
1066                                 tny_iterator_next (iter);
1067
1068                         g_object_unref (header);
1069                 }
1070                 g_object_unref (iter);
1071
1072                 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
1073                         g_object_unref (not_opened_headers);
1074                         return;                 
1075                 }
1076         }
1077         
1078         /* Register the headers before actually creating the windows: */
1079         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
1080         while (!tny_iterator_is_done (iter_not_opened)) {
1081                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1082                 if (header) {
1083                         modest_window_mgr_register_header (mgr, header);
1084                         g_object_unref (header);
1085                 }
1086                 
1087                 tny_iterator_next (iter_not_opened);
1088         }
1089         g_object_unref (iter_not_opened);
1090         iter_not_opened = NULL;
1091         
1092         /* Open each message */
1093         if (tny_list_get_length (not_opened_headers) > 0) {
1094                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1095                                                                          G_OBJECT (win), 
1096                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1097                                                                          NULL);
1098                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1099                 if (tny_list_get_length (not_opened_headers) > 1) {
1100                         modest_mail_operation_get_msgs_full (mail_op, 
1101                                                              not_opened_headers, 
1102                                                              open_msg_cb, 
1103                                                              NULL, 
1104                                                              NULL);
1105                 } else {
1106                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1107                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1108                         modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1109                         g_object_unref (header);
1110                         g_object_unref (iter);
1111                 }
1112                 g_object_unref (mail_op);
1113         }
1114
1115         /* Clean */
1116         if (not_opened_headers != NULL)
1117                 g_object_unref (not_opened_headers);
1118 }
1119
1120 void
1121 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1122 {
1123         TnyList *headers;
1124
1125         /* Get headers */
1126         headers = get_selected_headers (win);
1127         if (!headers)
1128                 return;
1129
1130         /* Open them */
1131         _modest_ui_actions_open (headers, win);
1132
1133         g_object_unref(headers);
1134 }
1135
1136
1137 static void
1138 free_reply_forward_helper (gpointer data)
1139 {
1140         ReplyForwardHelper *helper;
1141
1142         helper = (ReplyForwardHelper *) data;
1143         g_free (helper->account_name);
1144         g_slice_free (ReplyForwardHelper, helper);
1145 }
1146
1147 static void
1148 reply_forward_cb (ModestMailOperation *mail_op,  TnyHeader *header, TnyMsg *msg,
1149                   gpointer user_data)
1150 {
1151         TnyMsg *new_msg;
1152         ReplyForwardHelper *rf_helper;
1153         ModestWindow *msg_win = NULL;
1154         ModestEditType edit_type;
1155         gchar *from = NULL;
1156         TnyAccount *account = NULL;
1157         ModestWindowMgr *mgr = NULL;
1158         gchar *signature = NULL;
1159
1160         /* If there was any error. The mail operation could be NULL,
1161            this means that we already have the message downloaded and
1162            that we didn't do a mail operation to retrieve it */
1163         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1164                 return;
1165                         
1166         g_return_if_fail (user_data != NULL);
1167         rf_helper = (ReplyForwardHelper *) user_data;
1168
1169         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1170                                                    rf_helper->account_name);
1171         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1172                                          rf_helper->account_name,
1173                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1174                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1175                                                            rf_helper->account_name,
1176                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1177         }
1178
1179         /* Create reply mail */
1180         switch (rf_helper->action) {
1181         case ACTION_REPLY:
1182                 new_msg = 
1183                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1184                                                          rf_helper->reply_forward_type,
1185                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1186                 break;
1187         case ACTION_REPLY_TO_ALL:
1188                 new_msg = 
1189                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1190                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1191                 edit_type = MODEST_EDIT_TYPE_REPLY;
1192                 break;
1193         case ACTION_FORWARD:
1194                 new_msg = 
1195                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1196                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1197                 break;
1198         default:
1199                 g_return_if_reached ();
1200                 return;
1201         }
1202
1203         g_free (signature);
1204
1205         if (!new_msg) {
1206                 g_printerr ("modest: failed to create message\n");
1207                 goto cleanup;
1208         }
1209
1210         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1211                                                                        rf_helper->account_name,
1212                                                                        TNY_ACCOUNT_TYPE_STORE);
1213         if (!account) {
1214                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1215                 goto cleanup;
1216         }
1217
1218         /* Create and register the windows */
1219         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1220         mgr = modest_runtime_get_window_mgr ();
1221         modest_window_mgr_register_window (mgr, msg_win);
1222
1223         if (rf_helper->parent_window != NULL) {
1224                 gdouble parent_zoom;
1225
1226                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1227                 modest_window_set_zoom (msg_win, parent_zoom);
1228         }
1229
1230         /* Show edit window */
1231         gtk_widget_show_all (GTK_WIDGET (msg_win));
1232
1233 cleanup:
1234         if (msg_win)
1235                 g_object_unref (msg_win);
1236         if (new_msg)
1237                 g_object_unref (G_OBJECT (new_msg));
1238         if (account)
1239                 g_object_unref (G_OBJECT (account));
1240 /*      g_object_unref (msg); */
1241         free_reply_forward_helper (rf_helper);
1242 }
1243
1244 /* Checks a list of headers. If any of them are not currently
1245  * downloaded (CACHED) then returns TRUE else returns FALSE.
1246  */
1247 static gint
1248 header_list_count_uncached_msgs (TnyList *header_list)
1249 {
1250         TnyIterator *iter;
1251         gint uncached_messages = 0;
1252
1253         iter = tny_list_create_iterator (header_list);
1254         while (!tny_iterator_is_done (iter)) {
1255                 TnyHeader *header;
1256
1257                 header = TNY_HEADER (tny_iterator_get_current (iter));
1258                 if (header) {
1259                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1260                                 uncached_messages ++;
1261                         g_object_unref (header);
1262                 }
1263
1264                 tny_iterator_next (iter);
1265         }
1266         g_object_unref (iter);
1267
1268         return uncached_messages;
1269 }
1270
1271 /* Returns FALSE if the user does not want to download the
1272  * messages. Returns TRUE if the user allowed the download.
1273  */
1274 static gboolean
1275 connect_to_get_msg (GtkWindow *win,
1276                     gint num_of_uncached_msgs)
1277 {
1278         /* Allways download if we are online. */
1279         if (tny_device_is_online (modest_runtime_get_device ()))
1280                 return TRUE;
1281
1282         /* If offline, then ask for user permission to download the messages */
1283         GtkResponseType response;
1284         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1285                         ngettext("mcen_nc_get_msg",
1286                         "mcen_nc_get_msgs",
1287                         num_of_uncached_msgs));
1288         if (response == GTK_RESPONSE_CANCEL)
1289                 return FALSE;
1290
1291         return modest_platform_connect_and_wait(win, NULL);     
1292 }
1293
1294 /*
1295  * Common code for the reply and forward actions
1296  */
1297 static void
1298 reply_forward (ReplyForwardAction action, ModestWindow *win)
1299 {
1300         ModestMailOperation *mail_op = NULL;
1301         TnyList *header_list = NULL;
1302         ReplyForwardHelper *rf_helper = NULL;
1303         guint reply_forward_type;
1304         gboolean continue_download = TRUE;
1305         gboolean do_retrieve = TRUE;
1306         
1307         g_return_if_fail (MODEST_IS_WINDOW(win));
1308
1309         /* we need an account when editing */
1310         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1311                 const gboolean created = modest_run_account_setup_wizard (win);
1312                 if (!created)
1313                         return;
1314         }
1315         
1316         header_list = get_selected_headers (win);
1317         if (!header_list)
1318                 return;
1319
1320         reply_forward_type = 
1321                 modest_conf_get_int (modest_runtime_get_conf (),
1322                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1323                                      NULL);
1324
1325         /* check if we need to download msg before asking about it */
1326         do_retrieve = (action == ACTION_FORWARD) ||
1327                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1328
1329         if (do_retrieve){
1330                 gint num_of_unc_msgs;
1331                 /* check that the messages have been previously downloaded */
1332                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1333                 /* If there are any uncached message ask the user
1334                  * whether he/she wants to download them. */
1335                 if (num_of_unc_msgs)
1336                         continue_download = connect_to_get_msg (
1337                                                                 GTK_WINDOW (win),
1338                                                                 num_of_unc_msgs);
1339         }
1340
1341         if (!continue_download) {
1342                 g_object_unref (header_list);
1343                 return;
1344         }
1345         
1346         /* We assume that we can only select messages of the
1347            same folder and that we reply all of them from the
1348            same account. In fact the interface currently only
1349            allows single selection */
1350         
1351         /* Fill helpers */
1352         rf_helper = g_slice_new0 (ReplyForwardHelper);
1353         rf_helper->reply_forward_type = reply_forward_type;
1354         rf_helper->action = action;
1355         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1356         
1357         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1358                 rf_helper->parent_window = GTK_WIDGET (win);
1359         if (!rf_helper->account_name)
1360                 rf_helper->account_name =
1361                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1362
1363         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1364                 TnyMsg *msg;
1365                 TnyHeader *header;
1366                 /* Get header and message. Do not free them here, the
1367                    reply_forward_cb must do it */
1368                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1369                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1370                 if (!msg || !header) {
1371                         if (msg)
1372                                 g_object_unref (msg);
1373                         g_printerr ("modest: no message found\n");
1374                         return;
1375                 } else {
1376                         reply_forward_cb (NULL, header, msg, rf_helper);
1377                 }
1378                 if (header)
1379                         g_object_unref (header);
1380         } else {
1381                 TnyHeader *header;
1382                 TnyIterator *iter;
1383
1384                 /* Only reply/forward to one message */
1385                 iter = tny_list_create_iterator (header_list);
1386                 header = TNY_HEADER (tny_iterator_get_current (iter));
1387                 g_object_unref (iter);
1388
1389                 if (header) {
1390                         /* Retrieve messages */
1391                         if (do_retrieve) {
1392                                 mail_op = modest_mail_operation_new_with_error_handling (
1393                                         MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1394                                         G_OBJECT(win),
1395                                         modest_ui_actions_get_msgs_full_error_handler, 
1396                                         NULL);
1397                                 modest_mail_operation_queue_add (
1398                                         modest_runtime_get_mail_operation_queue (), mail_op);
1399                                 
1400                                 modest_mail_operation_get_msg (mail_op,
1401                                                                header,
1402                                                                reply_forward_cb,
1403                                                                rf_helper);
1404                                 /* Clean */
1405                                 g_object_unref(mail_op);
1406                         } else {
1407                                 /* we put a ref here to prevent double unref as the reply
1408                                  * forward callback unrefs the header at its end */
1409                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1410                         }
1411
1412
1413                         g_object_unref (header);
1414                 }
1415
1416         }
1417
1418         /* Free */
1419         g_object_unref (header_list);
1420 }
1421
1422 void
1423 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1424 {
1425         g_return_if_fail (MODEST_IS_WINDOW(win));
1426
1427         reply_forward (ACTION_REPLY, win);
1428 }
1429
1430 void
1431 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1432 {
1433         g_return_if_fail (MODEST_IS_WINDOW(win));
1434
1435         reply_forward (ACTION_FORWARD, win);
1436 }
1437
1438 void
1439 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1440 {
1441         g_return_if_fail (MODEST_IS_WINDOW(win));
1442
1443         reply_forward (ACTION_REPLY_TO_ALL, win);
1444 }
1445
1446 void 
1447 modest_ui_actions_on_next (GtkAction *action, 
1448                            ModestWindow *window)
1449 {
1450         if (MODEST_IS_MAIN_WINDOW (window)) {
1451                 GtkWidget *header_view;
1452
1453                 header_view = modest_main_window_get_child_widget (
1454                                 MODEST_MAIN_WINDOW(window),
1455                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1456                 if (!header_view)
1457                         return;
1458         
1459                 modest_header_view_select_next (
1460                                 MODEST_HEADER_VIEW(header_view)); 
1461         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1462                 modest_msg_view_window_select_next_message (
1463                                 MODEST_MSG_VIEW_WINDOW (window));
1464         } else {
1465                 g_return_if_reached ();
1466         }
1467 }
1468
1469 void 
1470 modest_ui_actions_on_prev (GtkAction *action, 
1471                            ModestWindow *window)
1472 {
1473         g_return_if_fail (MODEST_IS_WINDOW(window));
1474
1475         if (MODEST_IS_MAIN_WINDOW (window)) {
1476                 GtkWidget *header_view;
1477                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1478                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1479                 if (!header_view)
1480                         return;
1481                 
1482                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1483         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1484                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1485         } else {
1486                 g_return_if_reached ();
1487         }
1488 }
1489
1490 void 
1491 modest_ui_actions_on_sort (GtkAction *action, 
1492                            ModestWindow *window)
1493 {
1494         g_return_if_fail (MODEST_IS_WINDOW(window));
1495
1496         if (MODEST_IS_MAIN_WINDOW (window)) {
1497                 GtkWidget *header_view;
1498                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1499                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1500                 if (!header_view) {
1501                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1502
1503                         return;
1504                 }
1505
1506                 /* Show sorting dialog */
1507                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1508         }
1509 }
1510
1511 static void
1512 new_messages_arrived (ModestMailOperation *self, 
1513                       TnyList *new_headers,
1514                       gpointer user_data)
1515 {
1516         ModestMainWindow *win = NULL;
1517         GtkWidget *folder_view = NULL;
1518         TnyFolderStore *folder = NULL;
1519         gboolean folder_empty = FALSE;
1520
1521         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
1522         win = MODEST_MAIN_WINDOW (user_data);
1523
1524         /* Don't do anything if there are not new headers, this could
1525            happen if there was any problem with the mail operation */
1526         if (!new_headers)
1527                 return;
1528
1529         /* Set contents style of headers view */
1530         if (modest_main_window_get_contents_style (win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1531                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1532                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1533                 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));             
1534                 
1535
1536                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1537                 
1538                 if (!folder_empty)
1539                         modest_main_window_set_contents_style (win,
1540                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1541         }       
1542
1543         /* Notify new messages have been downloaded */
1544         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0)) {
1545                 TnyIterator *iter = tny_list_create_iterator (new_headers);
1546                 do {
1547                         TnyHeader *header =  NULL;
1548
1549                         header = TNY_HEADER (tny_iterator_get_current (iter));
1550                         modest_platform_on_new_header_received (header);
1551                         g_object_unref (header);
1552
1553                         tny_iterator_next (iter);
1554                 } while (!tny_iterator_is_done (iter));
1555                 g_object_unref (iter);
1556         }
1557 }
1558
1559 /*
1560  * This function performs the send & receive required actions. The
1561  * window is used to create the mail operation. Typically it should
1562  * always be the main window, but we pass it as argument in order to
1563  * be more flexible.
1564  */
1565 void
1566 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1567 {
1568         gchar *acc_name = NULL;
1569         ModestMailOperation *mail_op;
1570         TnyAccount *store_account = NULL;
1571
1572         /* If no account name was provided then get the current account, and if
1573            there is no current account then pick the default one: */
1574         if (!account_name) {
1575                 acc_name = g_strdup (modest_window_get_active_account(win));
1576                 if (!acc_name)
1577                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1578                 if (!acc_name) {
1579                         g_printerr ("modest: cannot get default account\n");
1580                         return;
1581                 }
1582         } else {
1583                 acc_name = g_strdup (account_name);
1584         }
1585
1586
1587         /* Ensure that we have a connection available */
1588         store_account =
1589                 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1590                                                              acc_name,
1591                                                              TNY_ACCOUNT_TYPE_STORE);
1592         if (!modest_platform_connect_and_wait (NULL, TNY_ACCOUNT (store_account))) {
1593                 g_object_unref (store_account);
1594                 return;
1595         }
1596         g_object_unref (store_account);
1597
1598         /* Set send/receive operation in progress */    
1599         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1600
1601         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1602                                                                  G_OBJECT (win),
1603                                                                  modest_ui_actions_send_receive_error_handler,
1604                                                                  NULL);
1605
1606         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1607                           G_CALLBACK (_on_send_receive_progress_changed), 
1608                           win);
1609
1610         /* Send & receive. */
1611         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1612         /* Receive and then send. The operation is tagged initially as
1613            a receive operation because the account update performs a
1614            receive and then a send. The operation changes its type
1615            internally, so the progress objects will receive the proper
1616            progress information */
1617         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1618         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1619         g_object_unref (G_OBJECT (mail_op));
1620         
1621         /* Free */
1622         g_free (acc_name);
1623 }
1624
1625
1626 static void
1627 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1628                                   ModestWindow *win)
1629 {
1630         TnyTransportAccount *transport_account;
1631         TnySendQueue *send_queue = NULL;
1632         GError *error = NULL;
1633
1634         /* Get transport account */
1635         transport_account =
1636                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1637                                       (modest_runtime_get_account_store(),
1638                                        account_name,
1639                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1640         if (!transport_account) {
1641                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1642                 goto frees;
1643         }
1644
1645         /* Get send queue*/
1646         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1647         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1648                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1649                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1650                              "modest: could not find send queue for account\n");
1651         } else {
1652                 /* Keeep messages in outbox folder */
1653                 tny_send_queue_cancel (send_queue, FALSE, &error);
1654         }       
1655
1656  frees:
1657         if (transport_account != NULL) 
1658                 g_object_unref (G_OBJECT (transport_account));
1659 }
1660
1661 static void
1662 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1663 {
1664         GSList *account_names, *iter;
1665
1666         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1667                                                           TRUE);
1668
1669         iter = account_names;
1670         while (iter) {                  
1671                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1672                 iter = g_slist_next (iter);
1673         }
1674
1675         modest_account_mgr_free_account_names (account_names);
1676         account_names = NULL;
1677 }
1678
1679 void
1680 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1681
1682 {
1683         /* Check if accounts exist */
1684         gboolean accounts_exist = 
1685                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1686         
1687         /* If not, allow the user to create an account before trying to send/receive. */
1688         if (!accounts_exist)
1689                 modest_ui_actions_on_accounts (NULL, win);
1690         
1691         /* Cancel all sending operaitons */     
1692         modest_ui_actions_cancel_send_all (win);
1693 }
1694
1695 /*
1696  * Refreshes all accounts. This function will be used by automatic
1697  * updates
1698  */
1699 void
1700 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1701 {
1702         GSList *account_names, *iter;
1703
1704         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1705                                                           TRUE);
1706
1707         iter = account_names;
1708         while (iter) {                  
1709                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1710                 iter = g_slist_next (iter);
1711         }
1712
1713         modest_account_mgr_free_account_names (account_names);
1714         account_names = NULL;
1715 }
1716
1717 void 
1718 modest_do_refresh_current_folder(ModestWindow *win)
1719 {
1720         /* Refresh currently selected folder. Note that if we only
1721            want to retreive the headers, then the refresh only will
1722            invoke a poke_status over all folders, i.e., only the
1723            total/unread count will be updated */
1724         if (MODEST_IS_MAIN_WINDOW (win)) {
1725                 GtkWidget *header_view, *folder_view;
1726                 TnyFolderStore *folder_store;
1727
1728                 /* Get folder and header view */
1729                 folder_view = 
1730                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1731                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1732                 if (!folder_view)
1733                         return;
1734
1735                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1736
1737                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1738                         header_view = 
1739                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1740                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1741                 
1742                         /* We do not need to set the contents style
1743                            because it hasn't changed. We also do not
1744                            need to save the widget status. Just force
1745                            a refresh */
1746                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1747                                                        TNY_FOLDER (folder_store),
1748                                                        folder_refreshed_cb,
1749                                                        MODEST_MAIN_WINDOW (win));
1750                 }
1751                 
1752                 if (folder_store)
1753                         g_object_unref (folder_store);
1754         }
1755 }
1756
1757
1758 /*
1759  * Handler of the click on Send&Receive button in the main toolbar
1760  */
1761 void
1762 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1763 {
1764         /* Check if accounts exist */
1765         gboolean accounts_exist = 
1766                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1767         
1768         /* If not, allow the user to create an account before trying to send/receive. */
1769         if (!accounts_exist)
1770                 modest_ui_actions_on_accounts (NULL, win);
1771
1772         modest_do_refresh_current_folder (win);
1773         
1774         /* Refresh the active account */
1775         modest_ui_actions_do_send_receive (NULL, win);
1776 }
1777
1778
1779 void
1780 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1781 {
1782         ModestConf *conf;
1783         GtkWidget *header_view;
1784         
1785         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1786
1787         header_view = modest_main_window_get_child_widget (main_window,
1788                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1789         if (!header_view)
1790                 return;
1791
1792         conf = modest_runtime_get_conf ();
1793         
1794         /* what is saved/restored is depending on the style; thus; we save with
1795          * old style, then update the style, and restore for this new style
1796          */
1797         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1798         
1799         if (modest_header_view_get_style
1800             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1801                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1802                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1803         else
1804                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1805                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1806
1807         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1808                                       MODEST_CONF_HEADER_VIEW_KEY);
1809 }
1810
1811
1812 void 
1813 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1814                                       TnyHeader *header,
1815                                       ModestMainWindow *main_window)
1816 {
1817         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1818         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1819         
1820         /* in the case the folder is empty, show the empty folder message and focus
1821          * folder view */
1822         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1823                 if (modest_header_view_is_empty (header_view)) {
1824                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1825                         GtkWidget *folder_view = 
1826                                 modest_main_window_get_child_widget (main_window,
1827                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1828                         if (folder != NULL) 
1829                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1830                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1831                         return;
1832                 }
1833         }
1834         /* If no header has been selected then exit */
1835         if (!header)
1836                 return;
1837
1838         /* Update focus */
1839         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1840             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1841
1842         /* Update toolbar dimming state */
1843         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1844 }
1845
1846 void
1847 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1848                                        TnyHeader *header,
1849                                        ModestMainWindow *main_window)
1850 {
1851         TnyList *headers;
1852
1853         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1854         
1855         if (!header)
1856                 return;
1857
1858
1859 /*      headers = tny_simple_list_new (); */
1860 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1861         headers = modest_header_view_get_selected_headers (header_view);
1862
1863         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1864
1865         g_object_unref (headers);
1866 }
1867
1868 static void
1869 set_active_account_from_tny_account (TnyAccount *account,
1870                                      ModestWindow *window)
1871 {
1872         const gchar *server_acc_name = tny_account_get_id (account);
1873         
1874         /* We need the TnyAccount provided by the
1875            account store because that is the one that
1876            knows the name of the Modest account */
1877         TnyAccount *modest_server_account = modest_server_account = 
1878                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1879                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1880                                                              server_acc_name);
1881         if (!modest_server_account) {
1882                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
1883                 return;
1884         }
1885
1886         /* Update active account, but only if it's not a pseudo-account */
1887         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
1888             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
1889                 const gchar *modest_acc_name = 
1890                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1891                 if (modest_acc_name)
1892                         modest_window_set_active_account (window, modest_acc_name);
1893         }
1894         
1895         g_object_unref (modest_server_account);
1896 }
1897
1898
1899 static void
1900 folder_refreshed_cb (ModestMailOperation *mail_op, 
1901                      TnyFolder *folder, 
1902                      gpointer user_data)
1903 {
1904         ModestMainWindow *win = NULL;
1905         GtkWidget *header_view;
1906         gboolean folder_empty = FALSE;
1907         gboolean all_marked_as_deleted = FALSE;
1908
1909         g_return_if_fail (TNY_IS_FOLDER (folder));
1910
1911         win = MODEST_MAIN_WINDOW (user_data);
1912         header_view = 
1913                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1914
1915         if (header_view) {
1916                 TnyFolder *current_folder;
1917
1918                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1919                 if (current_folder != NULL && folder != current_folder) {
1920                         g_object_unref (current_folder);
1921                         return;
1922                 }
1923                 g_object_unref (current_folder);
1924         }
1925
1926         /* Check if folder is empty and set headers view contents style */
1927         folder_empty = (tny_folder_get_all_count (folder) == 0);
1928         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1929         if (folder_empty || all_marked_as_deleted)
1930                 modest_main_window_set_contents_style (win,
1931                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1932 }
1933
1934 void 
1935 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1936                                                TnyFolderStore *folder_store, 
1937                                                gboolean selected,
1938                                                ModestMainWindow *main_window)
1939 {
1940         ModestConf *conf;
1941         GtkWidget *header_view;
1942
1943         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1944
1945         header_view = modest_main_window_get_child_widget(main_window,
1946                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1947         if (!header_view)
1948                 return;
1949         
1950         conf = modest_runtime_get_conf ();
1951
1952         if (TNY_IS_ACCOUNT (folder_store)) {
1953                 if (selected) {
1954                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1955                         
1956                         /* Show account details */
1957                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1958                 }
1959         } else {
1960                 if (TNY_IS_FOLDER (folder_store) && selected) {
1961                         
1962                         /* Update the active account */
1963                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1964                         if (account) {
1965                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1966                                 g_object_unref (account);
1967                                 account = NULL;
1968                         }
1969
1970                         /* Set the header style by default, it could
1971                            be changed later by the refresh callback to
1972                            empty */
1973                         modest_main_window_set_contents_style (main_window, 
1974                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1975
1976                         /* Set folder on header view. This function
1977                            will call tny_folder_refresh_async so we
1978                            pass a callback that will be called when
1979                            finished. We use that callback to set the
1980                            empty view if there are no messages */
1981                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1982                                                        TNY_FOLDER (folder_store),
1983                                                        folder_refreshed_cb,
1984                                                        main_window);
1985                         
1986                         /* Restore configuration. We need to do this
1987                            *after* the set_folder because the widget
1988                            memory asks the header view about its
1989                            folder  */
1990                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1991                                                       G_OBJECT(header_view),
1992                                                       MODEST_CONF_HEADER_VIEW_KEY);
1993                 } else {
1994                         /* Update the active account */
1995                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1996                         /* Save only if we're seeing headers */
1997                         if (modest_main_window_get_contents_style (main_window) ==
1998                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1999                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2000                                                            MODEST_CONF_HEADER_VIEW_KEY);
2001                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2002                 }
2003         }
2004
2005         /* Update toolbar dimming state */
2006         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2007 }
2008
2009 void 
2010 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2011                                      ModestWindow *win)
2012 {
2013         GtkWidget *dialog;
2014         gchar *txt, *item;
2015         gboolean online;
2016
2017         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2018         
2019         online = tny_device_is_online (modest_runtime_get_device());
2020
2021         if (online) {
2022                 /* already online -- the item is simply not there... */
2023                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2024                                                  GTK_DIALOG_MODAL,
2025                                                  GTK_MESSAGE_WARNING,
2026                                                  GTK_BUTTONS_NONE,
2027                                                  _("The %s you selected cannot be found"),
2028                                                  item);
2029                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2030                 gtk_dialog_run (GTK_DIALOG(dialog));
2031         } else {
2032                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2033                                                       GTK_WINDOW (win),
2034                                                       GTK_DIALOG_MODAL,
2035                                                       _("mcen_bd_dialog_cancel"),
2036                                                       GTK_RESPONSE_REJECT,
2037                                                       _("mcen_bd_dialog_ok"),
2038                                                       GTK_RESPONSE_ACCEPT,
2039                                                       NULL);
2040                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2041                                          "Do you want to get online?"), item);
2042                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2043                                     gtk_label_new (txt), FALSE, FALSE, 0);
2044                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2045                 g_free (txt);
2046
2047                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2048                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2049                         /* TODO: Comment about why is this commented out: */
2050                         /* modest_platform_connect_and_wait (); */
2051                 }
2052         }
2053         gtk_widget_destroy (dialog);
2054 }
2055
2056 void
2057 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2058                                      ModestWindow *win)
2059 {
2060         /* g_message ("%s %s", __FUNCTION__, link); */
2061 }       
2062
2063
2064 void
2065 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2066                                         ModestWindow *win)
2067 {
2068         modest_platform_activate_uri (link);
2069 }
2070
2071 void
2072 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2073                                           ModestWindow *win)
2074 {
2075         modest_platform_show_uri_popup (link);
2076 }
2077
2078 void
2079 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2080                                              ModestWindow *win)
2081 {
2082         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2083 }
2084
2085 void
2086 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2087                                           const gchar *address,
2088                                           ModestWindow *win)
2089 {
2090         /* g_message ("%s %s", __FUNCTION__, address); */
2091 }
2092
2093 void
2094 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2095 {
2096         TnyTransportAccount *transport_account;
2097         ModestMailOperation *mail_operation;
2098         MsgData *data;
2099         gchar *account_name, *from;
2100         ModestAccountMgr *account_mgr;
2101         gchar *info_text = NULL;
2102
2103         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2104         
2105         data = modest_msg_edit_window_get_msg_data (edit_window);
2106
2107         account_mgr = modest_runtime_get_account_mgr();
2108         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2109         if (!account_name) 
2110                 account_name = modest_account_mgr_get_default_account (account_mgr);
2111         if (!account_name) {
2112                 g_printerr ("modest: no account found\n");
2113                 modest_msg_edit_window_free_msg_data (edit_window, data);
2114                 return;
2115         }
2116
2117         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2118                 account_name = g_strdup (data->account_name);
2119         }
2120
2121         transport_account =
2122                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2123                                       (modest_runtime_get_account_store(),
2124                                        account_name,
2125                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2126         if (!transport_account) {
2127                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2128                 g_free (account_name);
2129                 modest_msg_edit_window_free_msg_data (edit_window, data);
2130                 return;
2131         }
2132         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2133
2134         /* Create the mail operation */         
2135         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2136         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2137
2138         modest_mail_operation_save_to_drafts (mail_operation,
2139                                               transport_account,
2140                                               data->draft_msg,
2141                                               edit_window,
2142                                               from,
2143                                               data->to, 
2144                                               data->cc, 
2145                                               data->bcc,
2146                                               data->subject, 
2147                                               data->plain_body, 
2148                                               data->html_body,
2149                                               data->attachments,
2150                                               data->priority_flags);
2151         /* Frees */
2152         g_free (from);
2153         g_free (account_name);
2154         g_object_unref (G_OBJECT (transport_account));
2155         g_object_unref (G_OBJECT (mail_operation));
2156
2157         modest_msg_edit_window_free_msg_data (edit_window, data);
2158
2159         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2160         modest_platform_information_banner (NULL, NULL, info_text);
2161         g_free (info_text);
2162 }
2163
2164 /* For instance, when clicking the Send toolbar button when editing a message: */
2165 void
2166 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2167 {
2168         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2169
2170         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2171                 return;
2172         
2173         /* Offer the connection dialog, if necessary: */        
2174         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2175                 return;
2176         
2177         /* FIXME: Code added just for testing. The final version will
2178            use the send queue provided by tinymail and some
2179            classifier */
2180         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2181         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2182         if (!account_name) 
2183                 account_name = modest_account_mgr_get_default_account (account_mgr);
2184                 
2185         if (!account_name) {
2186                 /* Run account setup wizard */
2187                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2188                 if (!created)
2189                         return;
2190         }
2191         
2192         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2193
2194         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2195                 account_name = g_strdup (data->account_name);
2196         }
2197         
2198         /* Get the currently-active transport account for this modest account: */
2199         TnyTransportAccount *transport_account =
2200                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2201                                       (modest_runtime_get_account_store(),
2202                                        account_name));
2203         if (!transport_account) {
2204                 /* Run account setup wizard */
2205                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2206                 if (!created)
2207                         return;
2208         }
2209         
2210         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2211
2212         /* Create the mail operation */
2213         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2214         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2215
2216         modest_mail_operation_send_new_mail (mail_operation,
2217                                              transport_account,
2218                                              data->draft_msg,
2219                                              from,
2220                                              data->to, 
2221                                              data->cc, 
2222                                              data->bcc,
2223                                              data->subject, 
2224                                              data->plain_body, 
2225                                              data->html_body,
2226                                              data->attachments,
2227                                              data->priority_flags);
2228                                              
2229         /* Free data: */
2230         g_free (from);
2231         g_free (account_name);
2232         g_object_unref (G_OBJECT (transport_account));
2233         g_object_unref (G_OBJECT (mail_operation));
2234
2235         modest_msg_edit_window_free_msg_data (edit_window, data);
2236         modest_msg_edit_window_set_sent (edit_window, TRUE);
2237
2238         /* Save settings and close the window: */
2239         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2240 }
2241
2242 void 
2243 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2244                                   ModestMsgEditWindow *window)
2245 {
2246         ModestMsgEditFormatState *format_state = NULL;
2247
2248         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2249         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2250
2251         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2252                 return;
2253
2254         format_state = modest_msg_edit_window_get_format_state (window);
2255         g_return_if_fail (format_state != NULL);
2256
2257         format_state->bold = gtk_toggle_action_get_active (action);
2258         modest_msg_edit_window_set_format_state (window, format_state);
2259         g_free (format_state);
2260         
2261 }
2262
2263 void 
2264 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2265                                      ModestMsgEditWindow *window)
2266 {
2267         ModestMsgEditFormatState *format_state = NULL;
2268
2269         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2270         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2271
2272         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2273                 return;
2274
2275         format_state = modest_msg_edit_window_get_format_state (window);
2276         g_return_if_fail (format_state != NULL);
2277
2278         format_state->italics = gtk_toggle_action_get_active (action);
2279         modest_msg_edit_window_set_format_state (window, format_state);
2280         g_free (format_state);
2281         
2282 }
2283
2284 void 
2285 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2286                                      ModestMsgEditWindow *window)
2287 {
2288         ModestMsgEditFormatState *format_state = NULL;
2289
2290         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2291         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2292
2293         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2294                 return;
2295
2296         format_state = modest_msg_edit_window_get_format_state (window);
2297         g_return_if_fail (format_state != NULL);
2298
2299         format_state->bullet = gtk_toggle_action_get_active (action);
2300         modest_msg_edit_window_set_format_state (window, format_state);
2301         g_free (format_state);
2302         
2303 }
2304
2305 void 
2306 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2307                                      GtkRadioAction *selected,
2308                                      ModestMsgEditWindow *window)
2309 {
2310         ModestMsgEditFormatState *format_state = NULL;
2311         GtkJustification value;
2312
2313         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2314
2315         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2316                 return;
2317
2318         value = gtk_radio_action_get_current_value (selected);
2319
2320         format_state = modest_msg_edit_window_get_format_state (window);
2321         g_return_if_fail (format_state != NULL);
2322
2323         format_state->justification = value;
2324         modest_msg_edit_window_set_format_state (window, format_state);
2325         g_free (format_state);
2326 }
2327
2328 void 
2329 modest_ui_actions_on_select_editor_color (GtkAction *action,
2330                                           ModestMsgEditWindow *window)
2331 {
2332         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2333         g_return_if_fail (GTK_IS_ACTION (action));
2334
2335         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2336                 return;
2337
2338         modest_msg_edit_window_select_color (window);
2339 }
2340
2341 void 
2342 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2343                                                      ModestMsgEditWindow *window)
2344 {
2345         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2346         g_return_if_fail (GTK_IS_ACTION (action));
2347
2348         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2349                 return;
2350
2351         modest_msg_edit_window_select_background_color (window);
2352 }
2353
2354 void 
2355 modest_ui_actions_on_insert_image (GtkAction *action,
2356                                    ModestMsgEditWindow *window)
2357 {
2358         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2359         g_return_if_fail (GTK_IS_ACTION (action));
2360
2361         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2362                 return;
2363
2364         modest_msg_edit_window_insert_image (window);
2365 }
2366
2367 void 
2368 modest_ui_actions_on_attach_file (GtkAction *action,
2369                                   ModestMsgEditWindow *window)
2370 {
2371         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2372         g_return_if_fail (GTK_IS_ACTION (action));
2373
2374         modest_msg_edit_window_offer_attach_file (window);
2375 }
2376
2377 void 
2378 modest_ui_actions_on_remove_attachments (GtkAction *action,
2379                                          ModestMsgEditWindow *window)
2380 {
2381         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2382         g_return_if_fail (GTK_IS_ACTION (action));
2383
2384         modest_msg_edit_window_remove_attachments (window, NULL);
2385 }
2386
2387 static void
2388 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2389                                             gpointer user_data)
2390 {
2391         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2392         const GError *error = modest_mail_operation_get_error (mail_op);
2393
2394         if(error)
2395         {
2396                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2397                                                     modest_mail_operation_get_error (mail_op)->message);
2398         }
2399 }
2400
2401 static void
2402 modest_ui_actions_create_folder(GtkWidget *parent_window,
2403                                 GtkWidget *folder_view)
2404 {
2405         TnyFolderStore *parent_folder;
2406
2407         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2408         
2409         if (parent_folder) {
2410                 gboolean finished = FALSE;
2411                 gint result;
2412                 gchar *folder_name = NULL, *suggested_name = NULL;
2413                 const gchar *proto_str = NULL;
2414                 TnyAccount *account;
2415
2416                 if (TNY_IS_ACCOUNT (parent_folder))
2417                         account = g_object_ref (parent_folder);
2418                 else
2419                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2420                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2421
2422                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2423                     MODEST_PROTOCOL_STORE_POP) {
2424                         finished = TRUE;
2425                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2426                 }
2427                 g_object_unref (account);
2428
2429                 /* Run the new folder dialog */
2430                 while (!finished) {
2431                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2432                                                                         parent_folder,
2433                                                                         suggested_name,
2434                                                                         &folder_name);
2435
2436                         g_free (suggested_name);
2437                         suggested_name = NULL;
2438
2439                         if (result == GTK_RESPONSE_REJECT) {
2440                                 finished = TRUE;
2441                         } else {
2442                                 ModestMailOperation *mail_op;
2443                                 TnyFolder *new_folder = NULL;
2444
2445                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2446                                                                                           G_OBJECT(parent_window),
2447                                                                                           modest_ui_actions_new_folder_error_handler,
2448                                                                                           parent_window);
2449
2450                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2451                                                                  mail_op);
2452                                 new_folder = modest_mail_operation_create_folder (mail_op,
2453                                                                                   parent_folder,
2454                                                                                   (const gchar *) folder_name);
2455                                 if (new_folder) {
2456                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2457                                                                           new_folder, TRUE);
2458
2459                                         g_object_unref (new_folder);
2460                                         finished = TRUE;
2461                                 }
2462                                 g_object_unref (mail_op);
2463                         }
2464
2465                         suggested_name = folder_name;
2466                         folder_name = NULL;
2467                 }
2468
2469                 g_object_unref (parent_folder);
2470         }
2471 }
2472
2473 void 
2474 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2475 {
2476         GtkWidget *folder_view;
2477         
2478         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2479
2480         folder_view = modest_main_window_get_child_widget (main_window,
2481                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2482         if (!folder_view)
2483                 return;
2484
2485         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2486 }
2487
2488 static void
2489 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2490                                                gpointer user_data)
2491 {
2492         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2493         const GError *error = NULL;
2494         const gchar *message = NULL;
2495         
2496         /* Get error message */
2497         error = modest_mail_operation_get_error (mail_op);
2498         if (!error)
2499                 g_return_if_reached ();
2500
2501         switch (error->code) {
2502         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2503                 message = _CS("ckdg_ib_folder_already_exists");
2504                 break;
2505         default:
2506                 g_return_if_reached ();
2507         }
2508
2509         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2510 }
2511
2512 void 
2513 modest_ui_actions_on_rename_folder (GtkAction *action,
2514                                      ModestMainWindow *main_window)
2515 {
2516         TnyFolderStore *folder;
2517         GtkWidget *folder_view;
2518         GtkWidget *header_view; 
2519
2520         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2521
2522         folder_view = modest_main_window_get_child_widget (main_window,
2523                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2524         if (!folder_view)
2525                 return;
2526
2527         header_view = modest_main_window_get_child_widget (main_window,
2528                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2529         
2530         if (!header_view)
2531                 return;
2532
2533         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2534
2535         if (!folder)
2536                 return;
2537
2538         if (TNY_IS_FOLDER (folder)) {
2539                 gchar *folder_name;
2540                 gint response;
2541                 const gchar *current_name;
2542                 TnyFolderStore *parent;
2543                 gboolean do_rename = TRUE;
2544
2545                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2546                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2547                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2548                                                                      parent, current_name, 
2549                                                                      &folder_name);
2550                 g_object_unref (parent);
2551
2552                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2553                         do_rename = FALSE;
2554                 } else if (modest_platform_is_network_folderstore(folder) &&
2555                            !tny_device_is_online (modest_runtime_get_device())) {
2556                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2557                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2558                         g_object_unref(account);
2559                 }
2560
2561                 if (do_rename) {
2562                         ModestMailOperation *mail_op;
2563                         GtkTreeSelection *sel = NULL;
2564
2565                         mail_op = 
2566                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2567                                                                                G_OBJECT(main_window),
2568                                                                                modest_ui_actions_rename_folder_error_handler,
2569                                                                                main_window);
2570
2571                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2572                                                          mail_op);
2573
2574                         /* Clear the headers view */
2575                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2576                         gtk_tree_selection_unselect_all (sel);
2577
2578                         /* Select *after* the changes */
2579                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2580                                                           TNY_FOLDER(folder), TRUE);
2581
2582                         /* Actually rename the folder */
2583                         modest_mail_operation_rename_folder (mail_op,
2584                                                              TNY_FOLDER (folder),
2585                                                              (const gchar *) folder_name);
2586
2587                         g_object_unref (mail_op);
2588                         g_free (folder_name);
2589                 }
2590         }
2591         g_object_unref (folder);
2592 }
2593
2594 static void
2595 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2596                                                gpointer user_data)
2597 {
2598         GObject *win = modest_mail_operation_get_source (mail_op);
2599
2600         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2601                                                 _("mail_in_ui_folder_delete_error"));
2602         g_object_unref (win);
2603 }
2604
2605 static gboolean
2606 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2607 {
2608         TnyFolderStore *folder;
2609         GtkWidget *folder_view;
2610         gint response;
2611         gchar *message;
2612         gboolean do_delete = TRUE;
2613
2614         g_return_val_if_fail (MODEST_IS_MAIN_WINDOW (main_window), FALSE);
2615
2616         folder_view = modest_main_window_get_child_widget (main_window,
2617                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2618         if (!folder_view)
2619                 return FALSE;
2620
2621         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2622
2623         /* Show an error if it's an account */
2624         if (!TNY_IS_FOLDER (folder)) {
2625                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2626                                                         _("mail_in_ui_folder_delete_error"));
2627                 g_object_unref (G_OBJECT (folder));
2628                 return FALSE;
2629         }
2630
2631         /* Ask the user */      
2632         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2633                                     tny_folder_get_name (TNY_FOLDER (folder)));
2634         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2635                                                             (const gchar *) message);
2636         g_free (message);
2637
2638         if (response != GTK_RESPONSE_OK) {
2639                 do_delete = FALSE;
2640         } else if (modest_platform_is_network_folderstore(folder) &&
2641                    !tny_device_is_online (modest_runtime_get_device())) {
2642                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2643                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2644                 g_object_unref(account);
2645         }
2646
2647         if (do_delete) {
2648                 ModestMailOperation *mail_op;
2649                 GtkTreeSelection *sel;
2650
2651                 /* Unselect the folder before deleting it to free the headers */
2652                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2653                 gtk_tree_selection_unselect_all (sel);
2654
2655                 /* Create the mail operation */
2656                 mail_op =
2657                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2658                                                                        G_OBJECT(main_window),
2659                                                                        modest_ui_actions_delete_folder_error_handler,
2660                                                                        NULL);
2661
2662                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2663                                                  mail_op);
2664                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2665                 g_object_unref (G_OBJECT (mail_op));
2666         }
2667
2668         g_object_unref (G_OBJECT (folder));
2669
2670         return do_delete;
2671 }
2672
2673 void 
2674 modest_ui_actions_on_delete_folder (GtkAction *action,
2675                                      ModestMainWindow *main_window)
2676 {
2677         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2678
2679         if (delete_folder (main_window, FALSE)) {
2680                 GtkWidget *folder_view;
2681
2682                 folder_view = modest_main_window_get_child_widget (main_window,
2683                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2684                 modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2685         }
2686 }
2687
2688 void 
2689 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2690 {
2691         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2692         
2693         delete_folder (main_window, TRUE);
2694 }
2695
2696
2697 static void
2698 show_error (GtkWidget *parent_widget, const gchar* text)
2699 {
2700         hildon_banner_show_information(parent_widget, NULL, text);
2701         
2702 #if 0
2703         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2704         /*
2705           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2706           (GtkDialogFlags)0,
2707           GTK_MESSAGE_ERROR,
2708           GTK_BUTTONS_OK,
2709           text ));
2710         */
2711                  
2712         gtk_dialog_run (dialog);
2713         gtk_widget_destroy (GTK_WIDGET (dialog));
2714 #endif
2715 }
2716
2717 void
2718 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2719                                          const gchar* server_account_name,
2720                                          gchar **username,
2721                                          gchar **password, 
2722                                          gboolean *cancel, 
2723                                          gboolean *remember,
2724                                          ModestMainWindow *main_window)
2725 {
2726         g_return_if_fail(server_account_name);
2727         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2728         
2729         /* Initalize output parameters: */
2730         if (cancel)
2731                 *cancel = FALSE;
2732                 
2733         if (remember)
2734                 *remember = TRUE;
2735                 
2736 #ifdef MODEST_PLATFORM_MAEMO
2737         /* Maemo uses a different (awkward) button order,
2738          * It should probably just use gtk_alternative_dialog_button_order ().
2739          */
2740         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2741                                               NULL,
2742                                               GTK_DIALOG_MODAL,
2743                                               _("mcen_bd_dialog_ok"),
2744                                               GTK_RESPONSE_ACCEPT,
2745                                               _("mcen_bd_dialog_cancel"),
2746                                               GTK_RESPONSE_REJECT,
2747                                               NULL);
2748 #else
2749         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2750                                               NULL,
2751                                               GTK_DIALOG_MODAL,
2752                                               GTK_STOCK_CANCEL,
2753                                               GTK_RESPONSE_REJECT,
2754                                               GTK_STOCK_OK,
2755                                               GTK_RESPONSE_ACCEPT,
2756                                               NULL);
2757 #endif /* MODEST_PLATFORM_MAEMO */
2758
2759         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2760         
2761         gchar *server_name = modest_server_account_get_hostname (
2762                 modest_runtime_get_account_mgr(), server_account_name);
2763         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2764                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2765                 *cancel = TRUE;
2766                 return;
2767         }
2768         
2769         /* This causes a warning because the logical ID has no %s in it, 
2770          * though the translation does, but there is not much we can do about that: */
2771         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2772         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2773                             FALSE, FALSE, 0);
2774         g_free (txt);
2775         g_free (server_name);
2776         server_name = NULL;
2777
2778         /* username: */
2779         gchar *initial_username = modest_server_account_get_username (
2780                 modest_runtime_get_account_mgr(), server_account_name);
2781         
2782         GtkWidget *entry_username = gtk_entry_new ();
2783         if (initial_username)
2784                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2785         /* Dim this if a connection has ever succeeded with this username,
2786          * as per the UI spec: */
2787         const gboolean username_known = 
2788                 modest_server_account_get_username_has_succeeded(
2789                         modest_runtime_get_account_mgr(), server_account_name);
2790         gtk_widget_set_sensitive (entry_username, !username_known);
2791         
2792 #ifdef MODEST_PLATFORM_MAEMO
2793         /* Auto-capitalization is the default, so let's turn it off: */
2794         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2795         
2796         /* Create a size group to be used by all captions.
2797          * Note that HildonCaption does not create a default size group if we do not specify one.
2798          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2799         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2800         
2801         GtkWidget *caption = hildon_caption_new (sizegroup, 
2802                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2803         gtk_widget_show (entry_username);
2804         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2805                 FALSE, FALSE, MODEST_MARGIN_HALF);
2806         gtk_widget_show (caption);
2807 #else 
2808         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2809                             TRUE, FALSE, 0);
2810 #endif /* MODEST_PLATFORM_MAEMO */      
2811                             
2812         /* password: */
2813         GtkWidget *entry_password = gtk_entry_new ();
2814         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2815         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2816         
2817 #ifdef MODEST_PLATFORM_MAEMO
2818         /* Auto-capitalization is the default, so let's turn it off: */
2819         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2820                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2821         
2822         caption = hildon_caption_new (sizegroup, 
2823                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2824         gtk_widget_show (entry_password);
2825         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2826                 FALSE, FALSE, MODEST_MARGIN_HALF);
2827         gtk_widget_show (caption);
2828         g_object_unref (sizegroup);
2829 #else 
2830         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2831                             TRUE, FALSE, 0);
2832 #endif /* MODEST_PLATFORM_MAEMO */      
2833                                 
2834 /* This is not in the Maemo UI spec:
2835         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2836         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2837                             TRUE, FALSE, 0);
2838 */
2839
2840         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2841         
2842         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2843                 if (username) {
2844                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2845                         
2846                         modest_server_account_set_username (
2847                                  modest_runtime_get_account_mgr(), server_account_name, 
2848                                  *username);
2849                                  
2850                         const gboolean username_was_changed = 
2851                                 (strcmp (*username, initial_username) != 0);
2852                         if (username_was_changed) {
2853                                 g_warning ("%s: tinymail does not yet support changing the "
2854                                         "username in the get_password() callback.\n", __FUNCTION__);
2855                         }
2856                 }
2857                         
2858                 if (password) {
2859                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2860                         
2861                         /* We do not save the password in the configuration, 
2862                          * because this function is only called for passwords that should 
2863                          * not be remembered:
2864                         modest_server_account_set_password (
2865                                  modest_runtime_get_account_mgr(), server_account_name, 
2866                                  *password);
2867                         */
2868                 }
2869                 
2870                 if (cancel)
2871                         *cancel   = FALSE;
2872                         
2873         } else {
2874                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2875                 
2876                 if (username)
2877                         *username = NULL;
2878                         
2879                 if (password)
2880                         *password = NULL;
2881                         
2882                 if (cancel)
2883                         *cancel   = TRUE;
2884         }
2885
2886 /* This is not in the Maemo UI spec:
2887         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2888                 *remember = TRUE;
2889         else
2890                 *remember = FALSE;
2891 */
2892
2893         gtk_widget_destroy (dialog);
2894         
2895         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2896 }
2897
2898 void
2899 modest_ui_actions_on_cut (GtkAction *action,
2900                           ModestWindow *window)
2901 {
2902         GtkWidget *focused_widget;
2903         GtkClipboard *clipboard;
2904
2905         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2906         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2907         if (GTK_IS_EDITABLE (focused_widget)) {
2908                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2909                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2910                 gtk_clipboard_store (clipboard);
2911         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2912                 GtkTextBuffer *buffer;
2913
2914                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2915                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2916                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2917                 gtk_clipboard_store (clipboard);
2918         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2919                 TnyList *header_list = modest_header_view_get_selected_headers (
2920                                 MODEST_HEADER_VIEW (focused_widget));
2921                 gboolean continue_download = FALSE;
2922                 gint num_of_unc_msgs;
2923
2924                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2925
2926                 if (num_of_unc_msgs)
2927                         continue_download = connect_to_get_msg(
2928                                                                 GTK_WINDOW (window),
2929                                                                 num_of_unc_msgs);
2930
2931                 if (num_of_unc_msgs == 0 || continue_download) {
2932 /*                      modest_platform_information_banner (
2933                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
2934                         modest_header_view_cut_selection (
2935                                         MODEST_HEADER_VIEW (focused_widget));
2936                 }
2937
2938                 g_object_unref (header_list);
2939         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2940                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2941         }
2942 }
2943
2944 void
2945 modest_ui_actions_on_copy (GtkAction *action,
2946                            ModestWindow *window)
2947 {
2948         GtkClipboard *clipboard;
2949         GtkWidget *focused_widget;
2950         gboolean copied = TRUE;
2951
2952         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2953         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2954
2955         if (GTK_IS_LABEL (focused_widget)) {
2956                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2957                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2958                 gtk_clipboard_store (clipboard);
2959         } else if (GTK_IS_EDITABLE (focused_widget)) {
2960                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2961                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2962                 gtk_clipboard_store (clipboard);
2963         } else if (GTK_IS_HTML (focused_widget)) {
2964                 gtk_html_copy (GTK_HTML (focused_widget));
2965                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2966                 gtk_clipboard_store (clipboard);
2967         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2968                 GtkTextBuffer *buffer;
2969                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2970                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2971                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2972                 gtk_clipboard_store (clipboard);
2973         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2974                 TnyList *header_list = modest_header_view_get_selected_headers (
2975                                 MODEST_HEADER_VIEW (focused_widget));
2976                 gboolean continue_download = FALSE;
2977                 gint num_of_unc_msgs;
2978
2979                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2980
2981                 if (num_of_unc_msgs)
2982                         continue_download = connect_to_get_msg(
2983                                                                 GTK_WINDOW (window),
2984                                                                 num_of_unc_msgs);
2985
2986                 if (num_of_unc_msgs == 0 || continue_download) {
2987                         modest_platform_information_banner (
2988                                         NULL, NULL, _CS("mcen_ib_getting_items"));
2989                         modest_header_view_copy_selection (
2990                                         MODEST_HEADER_VIEW (focused_widget));
2991                 } else
2992                         copied = FALSE;
2993
2994                 g_object_unref (header_list);
2995
2996         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2997                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2998         }
2999
3000         /* Show information banner if there was a copy to clipboard */
3001         if(copied)
3002                 modest_platform_information_banner (
3003                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3004 }
3005
3006 void
3007 modest_ui_actions_on_undo (GtkAction *action,
3008                            ModestWindow *window)
3009 {
3010         ModestEmailClipboard *clipboard = NULL;
3011
3012         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3013                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3014         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3015                 /* Clear clipboard source */
3016                 clipboard = modest_runtime_get_email_clipboard ();
3017                 modest_email_clipboard_clear (clipboard);               
3018         }
3019         else {
3020                 g_return_if_reached ();
3021         }
3022 }
3023
3024 void
3025 modest_ui_actions_on_redo (GtkAction *action,
3026                            ModestWindow *window)
3027 {
3028         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3029                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3030         }
3031         else {
3032                 g_return_if_reached ();
3033         }
3034 }
3035
3036
3037 static void
3038 destroy_information_note (ModestMailOperation *mail_op, gpointer user_data)
3039 {
3040         /* destroy information note */
3041         gtk_widget_destroy (GTK_WIDGET(user_data));
3042 }
3043
3044
3045 static void
3046 paste_as_attachment_free (gpointer data)
3047 {
3048         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3049
3050         gtk_widget_destroy (helper->banner);
3051         g_object_unref (helper->banner);
3052         g_free (helper);
3053 }
3054
3055 static void
3056 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3057                             TnyHeader *header,
3058                             TnyMsg *msg,
3059                             gpointer userdata)
3060 {
3061         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3062         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3063
3064         if (msg == NULL)
3065                 return;
3066
3067         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3068         
3069 }
3070
3071 void
3072 modest_ui_actions_on_paste (GtkAction *action,
3073                             ModestWindow *window)
3074 {
3075         GtkWidget *focused_widget = NULL;
3076         GtkWidget *inf_note = NULL;
3077         ModestMailOperation *mail_op = NULL;
3078
3079         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3080         if (GTK_IS_EDITABLE (focused_widget)) {
3081                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3082         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3083                 ModestEmailClipboard *e_clipboard = NULL;
3084                 e_clipboard = modest_runtime_get_email_clipboard ();
3085                 if (modest_email_clipboard_cleared (e_clipboard)) {
3086                         GtkTextBuffer *buffer;
3087                         GtkClipboard *clipboard;
3088
3089                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3090                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3091                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3092                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3093                         ModestMailOperation *mail_op;
3094                         TnyFolder *src_folder;
3095                         TnyList *data;
3096                         gboolean delete;
3097                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3098                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3099                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3100                                                                            _CS("ckct_nw_pasting"));
3101                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3102                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3103                                                              G_OBJECT (window));
3104                         if (helper->banner != NULL) {
3105                                 g_object_ref (G_OBJECT (helper->banner));
3106                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3107                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3108                         }
3109
3110                         if (data != NULL) {
3111                                 modest_mail_operation_get_msgs_full (mail_op, 
3112                                                                      data,
3113                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3114                                                                      helper,
3115                                                                      paste_as_attachment_free);
3116                         }
3117                 }
3118         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3119                 ModestEmailClipboard *clipboard = NULL;
3120                 TnyFolder *src_folder = NULL;
3121                 TnyFolderStore *folder_store = NULL;
3122                 TnyList *data = NULL;           
3123                 gboolean delete = FALSE;
3124                 
3125                 /* Check clipboard source */
3126                 clipboard = modest_runtime_get_email_clipboard ();
3127                 if (modest_email_clipboard_cleared (clipboard)) 
3128                         return;
3129                 
3130                 /* Get elements to paste */
3131                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3132
3133                 /* Create a new mail operation */
3134                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3135                 
3136                 /* Get destination folder */
3137                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3138
3139                 /* transfer messages  */
3140                 if (data != NULL) {
3141                         gint response = 0;
3142
3143                         /* Ask for user confirmation */
3144                         response = msgs_move_to_confirmation (GTK_WINDOW (window), 
3145                                                               TNY_FOLDER (folder_store), 
3146                                                               delete,
3147                                                               data);
3148                         
3149                         if (response == GTK_RESPONSE_OK) {
3150                                 /* Launch notification */
3151                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3152                                                                              _CS("ckct_nw_pasting"));
3153                                 if (inf_note != NULL)  {
3154                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3155                                         gtk_widget_show (GTK_WIDGET(inf_note));
3156                                 }
3157
3158                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3159                                 modest_mail_operation_xfer_msgs (mail_op, 
3160                                                                  data,
3161                                                                  TNY_FOLDER (folder_store),
3162                                                                  delete,
3163                                                                  destroy_information_note,
3164                                                                  inf_note);                             
3165                         } else {
3166                                 g_object_unref (mail_op);
3167                         }
3168                         
3169                 } else if (src_folder != NULL) {                        
3170                         /* Launch notification */
3171                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3172                                                                      _CS("ckct_nw_pasting"));
3173                         if (inf_note != NULL)  {
3174                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3175                                 gtk_widget_show (GTK_WIDGET(inf_note));
3176                         }
3177                         
3178                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3179                         modest_mail_operation_xfer_folder (mail_op, 
3180                                                            src_folder,
3181                                                            folder_store,
3182                                                            delete,
3183                                                            destroy_information_note,
3184                                                            inf_note);
3185                 }
3186
3187                 /* Free */
3188                 if (data != NULL) 
3189                         g_object_unref (data);
3190                 if (src_folder != NULL) 
3191                         g_object_unref (src_folder);
3192                 if (folder_store != NULL) 
3193                         g_object_unref (folder_store);
3194         }
3195 }
3196
3197
3198 void
3199 modest_ui_actions_on_select_all (GtkAction *action,
3200                                  ModestWindow *window)
3201 {
3202         GtkWidget *focused_widget;
3203
3204         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3205         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3206                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3207         } else if (GTK_IS_LABEL (focused_widget)) {
3208                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3209         } else if (GTK_IS_EDITABLE (focused_widget)) {
3210                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3211         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3212                 GtkTextBuffer *buffer;
3213                 GtkTextIter start, end;
3214
3215                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3216                 gtk_text_buffer_get_start_iter (buffer, &start);
3217                 gtk_text_buffer_get_end_iter (buffer, &end);
3218                 gtk_text_buffer_select_range (buffer, &start, &end);
3219         } else if (GTK_IS_HTML (focused_widget)) {
3220                 gtk_html_select_all (GTK_HTML (focused_widget));
3221         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3222                 GtkWidget *header_view = focused_widget;
3223                 GtkTreeSelection *selection = NULL;
3224                 
3225                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3226                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3227                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3228                 }
3229                                 
3230                 /* Disable window dimming management */
3231                 modest_window_disable_dimming (MODEST_WINDOW(window));
3232                 
3233                 /* Select all messages */
3234                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3235                 gtk_tree_selection_select_all (selection);
3236
3237                 /* Set focuse on header view */
3238                 gtk_widget_grab_focus (header_view);
3239
3240
3241                 /* Enable window dimming management */
3242                 modest_window_enable_dimming (MODEST_WINDOW(window));
3243                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3244         }
3245
3246 }
3247
3248 void
3249 modest_ui_actions_on_mark_as_read (GtkAction *action,
3250                                    ModestWindow *window)
3251 {       
3252         g_return_if_fail (MODEST_IS_WINDOW(window));
3253                 
3254         /* Mark each header as read */
3255         do_headers_action (window, headers_action_mark_as_read, NULL);
3256 }
3257
3258 void
3259 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3260                                      ModestWindow *window)
3261 {       
3262         g_return_if_fail (MODEST_IS_WINDOW(window));
3263                 
3264         /* Mark each header as read */
3265         do_headers_action (window, headers_action_mark_as_unread, NULL);
3266 }
3267
3268 void
3269 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3270                                   GtkRadioAction *selected,
3271                                   ModestWindow *window)
3272 {
3273         gint value;
3274
3275         value = gtk_radio_action_get_current_value (selected);
3276         if (MODEST_IS_WINDOW (window)) {
3277                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3278         }
3279 }
3280
3281 void     
3282 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3283                                                GtkRadioAction *selected,
3284                                                ModestWindow *window)
3285 {
3286         TnyHeaderFlags flags;
3287         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3288
3289         flags = gtk_radio_action_get_current_value (selected);
3290         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3291 }
3292
3293 void     
3294 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3295                                                   GtkRadioAction *selected,
3296                                                   ModestWindow *window)
3297 {
3298         gint file_format;
3299
3300         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3301
3302         file_format = gtk_radio_action_get_current_value (selected);
3303         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3304 }
3305
3306
3307 void     
3308 modest_ui_actions_on_zoom_plus (GtkAction *action,
3309                                 ModestWindow *window)
3310 {
3311         g_return_if_fail (MODEST_IS_WINDOW (window));
3312
3313         modest_window_zoom_plus (MODEST_WINDOW (window));
3314 }
3315
3316 void     
3317 modest_ui_actions_on_zoom_minus (GtkAction *action,
3318                                  ModestWindow *window)
3319 {
3320         g_return_if_fail (MODEST_IS_WINDOW (window));
3321
3322         modest_window_zoom_minus (MODEST_WINDOW (window));
3323 }
3324
3325 void     
3326 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3327                                            ModestWindow *window)
3328 {
3329         ModestWindowMgr *mgr;
3330         gboolean fullscreen, active;
3331         g_return_if_fail (MODEST_IS_WINDOW (window));
3332
3333         mgr = modest_runtime_get_window_mgr ();
3334
3335         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3336         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3337
3338         if (active != fullscreen) {
3339                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3340                 gtk_window_present (GTK_WINDOW (window));
3341         }
3342 }
3343
3344 void
3345 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3346                                         ModestWindow *window)
3347 {
3348         ModestWindowMgr *mgr;
3349         gboolean fullscreen;
3350
3351         g_return_if_fail (MODEST_IS_WINDOW (window));
3352
3353         mgr = modest_runtime_get_window_mgr ();
3354         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3355         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3356
3357         gtk_window_present (GTK_WINDOW (window));
3358 }
3359
3360 /* 
3361  * Used by modest_ui_actions_on_details to call do_headers_action 
3362  */
3363 static void
3364 headers_action_show_details (TnyHeader *header, 
3365                              ModestWindow *window,
3366                              gpointer user_data)
3367
3368 {
3369         GtkWidget *dialog;
3370         
3371         /* Create dialog */
3372         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3373
3374         /* Run dialog */
3375         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3376         gtk_widget_show_all (dialog);
3377         gtk_dialog_run (GTK_DIALOG (dialog));
3378
3379         gtk_widget_destroy (dialog);
3380 }
3381
3382 /*
3383  * Show the folder details in a ModestDetailsDialog widget
3384  */
3385 static void
3386 show_folder_details (TnyFolder *folder, 
3387                      GtkWindow *window)
3388 {
3389         GtkWidget *dialog;
3390         
3391         /* Create dialog */
3392         dialog = modest_details_dialog_new_with_folder (window, folder);
3393
3394         /* Run dialog */
3395         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3396         gtk_widget_show_all (dialog);
3397         gtk_dialog_run (GTK_DIALOG (dialog));
3398
3399         gtk_widget_destroy (dialog);
3400 }
3401
3402 /*
3403  * Show the header details in a ModestDetailsDialog widget
3404  */
3405 void     
3406 modest_ui_actions_on_details (GtkAction *action, 
3407                               ModestWindow *win)
3408 {
3409         TnyList * headers_list;
3410         TnyIterator *iter;
3411         TnyHeader *header;              
3412
3413         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3414                 TnyMsg *msg;
3415
3416                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3417                 if (!msg)
3418                         return;
3419                 g_object_unref (msg);           
3420
3421                 headers_list = get_selected_headers (win);
3422                 if (!headers_list)
3423                         return;
3424
3425                 iter = tny_list_create_iterator (headers_list);
3426
3427                 header = TNY_HEADER (tny_iterator_get_current (iter));
3428                 if (header) {
3429                         headers_action_show_details (header, win, NULL);
3430                         g_object_unref (header);
3431                 }
3432
3433                 g_object_unref (iter);
3434                 g_object_unref (headers_list);
3435
3436         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3437                 GtkWidget *folder_view, *header_view;
3438
3439                 /* Check which widget has the focus */
3440                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3441                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3442                 if (gtk_widget_is_focus (folder_view)) {
3443                         TnyFolderStore *folder_store
3444                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3445                         if (!folder_store) {
3446                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3447                                 return; 
3448                         }
3449                         /* Show only when it's a folder */
3450                         /* This function should not be called for account items, 
3451                          * because we dim the menu item for them. */
3452                         if (TNY_IS_FOLDER (folder_store)) {
3453                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3454                         }
3455
3456                         g_object_unref (folder_store);
3457
3458                 } else {
3459                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3460                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3461                         /* Show details of each header */
3462                         do_headers_action (win, headers_action_show_details, header_view);
3463                 }
3464         }
3465 }
3466
3467 void     
3468 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3469                                      ModestMsgEditWindow *window)
3470 {
3471         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3472
3473         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3474 }
3475
3476 void     
3477 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3478                                       ModestMsgEditWindow *window)
3479 {
3480         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3481
3482         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3483 }
3484
3485 void
3486 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3487                                        ModestMainWindow *main_window)
3488 {
3489         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3490
3491         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3492                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3493         else
3494                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3495 }
3496
3497 void 
3498 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3499                                      ModestWindow *window)
3500 {
3501         gboolean active, fullscreen = FALSE;
3502         ModestWindowMgr *mgr;
3503
3504         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3505
3506         /* Check if we want to toggle the toolbar vuew in fullscreen
3507            or normal mode */
3508         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3509                      "ViewShowToolbarFullScreen")) {
3510                 fullscreen = TRUE;
3511         }
3512
3513         /* Toggle toolbar */
3514         mgr = modest_runtime_get_window_mgr ();
3515         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3516 }
3517
3518 void     
3519 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3520                                            ModestMsgEditWindow *window)
3521 {
3522         modest_msg_edit_window_select_font (window);
3523 }
3524
3525 void
3526 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3527                                                   const gchar *display_name,
3528                                                   GtkWindow *window)
3529 {
3530         /* Do not change the application name if the widget has not
3531            the focus. This callback could be called even if the folder
3532            view has not the focus, because the handled signal could be
3533            emitted when the folder view is redrawn */
3534         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3535                 if (display_name)
3536                         gtk_window_set_title (window, display_name);
3537                 else
3538                         gtk_window_set_title (window, " ");
3539         }
3540 }
3541
3542 void
3543 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3544 {
3545         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3546         modest_msg_edit_window_select_contacts (window);
3547 }
3548
3549 void
3550 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3551 {
3552         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3553         modest_msg_edit_window_check_names (window, FALSE);
3554 }
3555
3556 static void
3557 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3558 {
3559         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3560                                          GTK_WIDGET (user_data));
3561 }
3562
3563 /*
3564  * This function is used to track changes in the selection of the
3565  * folder view that is inside the "move to" dialog to enable/disable
3566  * the OK button because we do not want the user to select a disallowed
3567  * destination for a folder.
3568  * The user also not desired to be able to use NEW button on items where
3569  * folder creation is not possibel.
3570  */
3571 static void
3572 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3573                                             TnyFolderStore *folder_store,
3574                                             gboolean selected,
3575                                             gpointer user_data)
3576 {
3577         GtkWidget *dialog = NULL;
3578         GtkWidget *ok_button = NULL, *new_button = NULL;
3579         GList *children = NULL;
3580         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3581         gboolean moving_folder = FALSE;
3582         gboolean is_local_account = TRUE;
3583         GtkWidget *folder_view = NULL;
3584         ModestTnyFolderRules rules;
3585
3586         if (!selected)
3587                 return;
3588
3589         /* Get the OK button */
3590         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3591         if (!dialog)
3592                 return;
3593
3594         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3595         ok_button = GTK_WIDGET (children->next->next->data);
3596         new_button = GTK_WIDGET (children->next->data);
3597         g_list_free (children);
3598
3599         /* check if folder_store is an remote account */
3600         if (TNY_IS_ACCOUNT (folder_store)) {
3601                 TnyAccount *local_account = NULL;
3602                 ModestTnyAccountStore *account_store = NULL;
3603
3604                 account_store = modest_runtime_get_account_store ();
3605                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3606
3607                 if ((gpointer) local_account != (gpointer) folder_store) {
3608                         is_local_account = FALSE;
3609                         /* New button should be dimmed on remote
3610                            account root */
3611                         new_sensitive = FALSE;
3612                 }
3613                 g_object_unref (local_account);
3614         }
3615
3616         /* Check the target folder rules */
3617         if (TNY_IS_FOLDER (folder_store)) {
3618                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3619                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3620                         ok_sensitive = FALSE;
3621                         new_sensitive = FALSE;
3622                         goto end;
3623                 }
3624         }
3625
3626         /* Check if we're moving a folder */
3627         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3628                 /* Get the widgets */
3629                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3630                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3631                 if (gtk_widget_is_focus (folder_view))
3632                         moving_folder = TRUE;
3633         }
3634
3635         if (moving_folder) {
3636                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3637
3638                 /* Get the folder to move */
3639                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3640                 
3641                 /* Check that we're not moving to the same folder */
3642                 if (TNY_IS_FOLDER (moved_folder)) {
3643                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3644                         if (parent == folder_store)
3645                                 ok_sensitive = FALSE;
3646                         g_object_unref (parent);
3647                 } 
3648
3649                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3650                         /* Do not allow to move to an account unless it's the
3651                            local folders account */
3652                         if (!is_local_account)
3653                                 ok_sensitive = FALSE;
3654                 } 
3655
3656                 if (ok_sensitive && (moved_folder == folder_store)) {
3657                         /* Do not allow to move to itself */
3658                         ok_sensitive = FALSE;
3659                 }
3660                 g_object_unref (moved_folder);
3661         } else {
3662                 TnyHeader *header = NULL;
3663                 TnyFolder *src_folder = NULL;
3664
3665                 /* Moving a message */
3666                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3667                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3668                         src_folder = tny_header_get_folder (header);
3669                         g_object_unref (header);
3670                 } else {
3671                         src_folder = 
3672                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3673                 }
3674
3675                 /* Do not allow to move the msg to the same folder */
3676                 /* Do not allow to move the msg to an account */
3677                 if ((gpointer) src_folder == (gpointer) folder_store ||
3678                     TNY_IS_ACCOUNT (folder_store))
3679                         ok_sensitive = FALSE;
3680                 g_object_unref (src_folder);
3681         }
3682
3683  end:
3684         /* Set sensitivity of the OK button */
3685         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3686         /* Set sensitivity of the NEW button */
3687         gtk_widget_set_sensitive (new_button, new_sensitive);
3688 }
3689
3690 static GtkWidget*
3691 create_move_to_dialog (GtkWindow *win,
3692                        GtkWidget *folder_view,
3693                        GtkWidget **tree_view)
3694 {
3695         GtkWidget *dialog, *scroll;
3696         GtkWidget *new_button;
3697
3698         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3699                                               GTK_WINDOW (win),
3700                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3701                                               NULL);
3702
3703         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3704         /* We do this manually so GTK+ does not associate a response ID for
3705          * the button. */
3706         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3707         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3708         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3709
3710         /* Create scrolled window */
3711         scroll = gtk_scrolled_window_new (NULL, NULL);
3712         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3713                                          GTK_POLICY_AUTOMATIC,
3714                                          GTK_POLICY_AUTOMATIC);
3715
3716         /* Create folder view */
3717         *tree_view = modest_platform_create_folder_view (NULL);
3718
3719         /* Track changes in the selection to
3720          * disable the OK button whenever "Move to" is not possible
3721          * disbale NEW button whenever New is not possible */
3722         g_signal_connect (*tree_view,
3723                           "folder_selection_changed",
3724                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3725                           win);
3726
3727         /* Listen to clicks on New button */
3728         g_signal_connect (G_OBJECT (new_button), 
3729                           "clicked", 
3730                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3731                           *tree_view);
3732
3733         /* It could happen that we're trying to move a message from a
3734            window (msg window for example) after the main window was
3735            closed, so we can not just get the model of the folder
3736            view */
3737         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3738                 const gchar *visible_id = NULL;
3739
3740                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3741                                                MODEST_FOLDER_VIEW(*tree_view));
3742
3743                 visible_id = 
3744                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3745
3746                 /* Show the same account than the one that is shown in the main window */
3747                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3748                                                                              visible_id);
3749         } else {
3750                 const gchar *active_account_name = NULL;
3751                 ModestAccountMgr *mgr = NULL;
3752                 ModestAccountData *acc_data = NULL;
3753
3754                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3755                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3756
3757                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3758                 mgr = modest_runtime_get_account_mgr ();
3759                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3760
3761                 /* Set the new visible & active account */
3762                 if (acc_data && acc_data->store_account) { 
3763                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3764                                                                                      acc_data->store_account->account_name);
3765                         modest_account_mgr_free_account_data (mgr, acc_data);
3766                 }
3767         }
3768
3769         /* Hide special folders */
3770         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3771         
3772         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3773
3774         /* Add scroll to dialog */
3775         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3776                             scroll, TRUE, TRUE, 0);
3777
3778         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3779         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3780
3781         return dialog;
3782 }
3783
3784 /*
3785  * Returns TRUE if at least one of the headers of the list belongs to
3786  * a message that has been fully retrieved.
3787  */
3788 #if 0 /* no longer in use. delete in 2007.10 */
3789 static gboolean
3790 has_retrieved_msgs (TnyList *list)
3791 {
3792         TnyIterator *iter;
3793         gboolean found = FALSE;
3794
3795         iter = tny_list_create_iterator (list);
3796         while (!tny_iterator_is_done (iter) && !found) {
3797                 TnyHeader *header;
3798                 TnyHeaderFlags flags = 0;
3799
3800                 header = TNY_HEADER (tny_iterator_get_current (iter));
3801                 if (header) {
3802                         flags = tny_header_get_flags (header);
3803                         if (flags & TNY_HEADER_FLAG_CACHED)
3804 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3805                                 found = TRUE;
3806
3807                         g_object_unref (header);
3808                 }
3809
3810                 if (!found)
3811                         tny_iterator_next (iter);
3812         }
3813         g_object_unref (iter);
3814
3815         return found;
3816 }
3817 #endif /* 0 */
3818
3819
3820 /*
3821  * Shows a confirmation dialog to the user when we're moving messages
3822  * from a remote server to the local storage. Returns the dialog
3823  * response. If it's other kind of movement then it always returns
3824  * GTK_RESPONSE_OK
3825  *
3826  * This one is used by the next functions:
3827  *      modest_ui_actions_on_paste                      - commented out
3828  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3829  */
3830 gint
3831 msgs_move_to_confirmation (GtkWindow *win,
3832                            TnyFolder *dest_folder,
3833                            gboolean delete,
3834                            TnyList *headers)
3835 {
3836         gint response = GTK_RESPONSE_OK;
3837
3838         /* return with OK if the destination is a remote folder */
3839         if (modest_tny_folder_is_remote_folder (dest_folder))
3840                 return GTK_RESPONSE_OK;
3841
3842         TnyFolder *src_folder = NULL;
3843         TnyIterator *iter = NULL;
3844         TnyHeader *header = NULL;
3845
3846         /* Get source folder */
3847         iter = tny_list_create_iterator (headers);
3848         header = TNY_HEADER (tny_iterator_get_current (iter));
3849         if (header) {
3850                 src_folder = tny_header_get_folder (header);
3851                 g_object_unref (header);
3852         }
3853         g_object_unref (iter);
3854
3855         /* if no src_folder, message may be an attahcment */
3856         if (src_folder == NULL) 
3857                 return GTK_RESPONSE_CANCEL;
3858
3859         /* If the source is a local or MMC folder */
3860         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3861                 g_object_unref (src_folder);
3862                 return GTK_RESPONSE_OK;
3863         }
3864         g_object_unref (src_folder);
3865
3866         /* now if offline we ask the user */
3867         if(connect_to_get_msg(  GTK_WINDOW (win),
3868                                         tny_list_get_length (headers)))
3869                 response = GTK_RESPONSE_OK;
3870         else
3871                 response = GTK_RESPONSE_CANCEL;
3872
3873         return response;
3874 }
3875
3876
3877
3878 static void
3879 move_to_cb (ModestMailOperation *mail_op, gpointer user_data)
3880 {
3881         /* Note that the operation could have failed, in that case do
3882            nothing */
3883         if (modest_mail_operation_get_status (mail_op) == 
3884             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
3885
3886                 GObject *object = modest_mail_operation_get_source (mail_op);
3887                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
3888                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
3889
3890                         if (!modest_msg_view_window_select_next_message (self))
3891                                 if (!modest_msg_view_window_select_previous_message (self))
3892                                         /* No more messages to view, so close this window */
3893                                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3894                 }
3895                 g_object_unref (object);
3896         }
3897
3898         /* Close the "Pasting" information banner */
3899         gtk_widget_destroy (GTK_WIDGET(user_data));
3900 }
3901
3902 void
3903 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3904                                              gpointer user_data)
3905 {
3906         ModestWindow *main_window = NULL;
3907         GtkWidget *folder_view = NULL;
3908         GObject *win = modest_mail_operation_get_source (mail_op);
3909         const GError *error = NULL;
3910         const gchar *message = NULL;
3911         
3912         /* Get error message */
3913         error = modest_mail_operation_get_error (mail_op);
3914         if (error != NULL && error->message != NULL) {
3915                 message = error->message;
3916         } else {
3917                 message = _("mail_in_ui_folder_move_target_error");
3918         }
3919         
3920         /* Disable next automatic folder selection */
3921         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ());
3922         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
3923                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
3924         modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
3925         
3926         if (user_data && TNY_IS_FOLDER (user_data)) {
3927                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
3928                                                   TNY_FOLDER (user_data), FALSE);
3929         }
3930
3931         /* Show notification dialog */
3932         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3933         g_object_unref (win);
3934 }
3935
3936 void
3937 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3938                                               gpointer user_data)
3939 {
3940         GObject *win = modest_mail_operation_get_source (mail_op);
3941         const GError *error = modest_mail_operation_get_error (mail_op);
3942
3943         g_return_if_fail (error != NULL);
3944         if (error->message != NULL)             
3945                 g_printerr ("modest: %s\n", error->message);
3946         else
3947                 g_printerr ("modest: unkonw error on send&receive operation");
3948
3949         /* Show error message */
3950 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3951 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3952 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3953 /*      else  */
3954 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3955 /*                                                      _CS("sfil_ib_unable_to_send")); */
3956         g_object_unref (win);
3957 }
3958
3959 static void
3960 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3961                        TnyHeader *header, 
3962                        TnyMsg *msg, 
3963                        gpointer user_data)
3964 {
3965         TnyList *parts;
3966         TnyIterator *iter;
3967         gint pending_purges = 0;
3968         gboolean some_purged = FALSE;
3969         ModestWindow *win = MODEST_WINDOW (user_data);
3970         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3971
3972         /* If there was any error */
3973         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3974                 modest_window_mgr_unregister_header (mgr, header);
3975                 return;
3976         }
3977
3978         /* Once the message has been retrieved for purging, we check if
3979          * it's all ok for purging */
3980
3981         parts = tny_simple_list_new ();
3982         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3983         iter = tny_list_create_iterator (parts);
3984
3985         while (!tny_iterator_is_done (iter)) {
3986                 TnyMimePart *part;
3987                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3988                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3989                         if (tny_mime_part_is_purged (part))
3990                                 some_purged = TRUE;
3991                         else
3992                                 pending_purges++;
3993                 }
3994
3995                 if (part)
3996                         g_object_unref (part);
3997
3998                 tny_iterator_next (iter);
3999         }
4000         g_object_unref (iter);
4001         
4002
4003         if (pending_purges>0) {
4004                 gint response;
4005                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4006
4007                 if (response == GTK_RESPONSE_OK) {
4008                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4009                         iter = tny_list_create_iterator (parts);
4010                         while (!tny_iterator_is_done (iter)) {
4011                                 TnyMimePart *part;
4012                                 
4013                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4014                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4015                                         tny_mime_part_set_purged (part);
4016
4017                                 if (part)
4018                                         g_object_unref (part);
4019
4020                                 tny_iterator_next (iter);
4021                         }
4022                         
4023                         tny_msg_rewrite_cache (msg);
4024                 }
4025         } else {
4026                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4027         }
4028         g_object_unref (iter);
4029
4030         modest_window_mgr_unregister_header (mgr, header);
4031
4032         g_object_unref (parts);
4033 }
4034
4035 static void
4036 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4037                                                      ModestMainWindow *win)
4038 {
4039         GtkWidget *header_view;
4040         TnyList *header_list;
4041         TnyIterator *iter;
4042         TnyHeader *header;
4043         TnyHeaderFlags flags;
4044         ModestWindow *msg_view_window =  NULL;
4045         gboolean found;
4046
4047         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4048
4049         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4050                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4051
4052         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4053
4054         if (tny_list_get_length (header_list) == 1) {
4055                 iter = tny_list_create_iterator (header_list);
4056                 header = TNY_HEADER (tny_iterator_get_current (iter));
4057                 g_object_unref (iter);
4058         } else {
4059                 return;
4060         }
4061
4062         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4063                                                           header, &msg_view_window);
4064         flags = tny_header_get_flags (header);
4065         if (!(flags & TNY_HEADER_FLAG_CACHED))
4066                 return;
4067         if (found) {
4068                 if (msg_view_window != NULL) 
4069                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4070                 else {
4071                         /* do nothing; uid was registered before, so window is probably on it's way */
4072                         g_warning ("debug: header %p has already been registered", header);
4073                 }
4074         } else {
4075                 ModestMailOperation *mail_op = NULL;
4076                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
4077                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4078                                                                          G_OBJECT (win),
4079                                                                          modest_ui_actions_get_msgs_full_error_handler,
4080                                                                          NULL);
4081                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4082                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4083                 
4084                 g_object_unref (mail_op);
4085         }
4086         if (header)
4087                 g_object_unref (header);
4088         if (header_list)
4089                 g_object_unref (header_list);
4090 }
4091
4092 /**
4093  * Utility function that transfer messages from both the main window
4094  * and the msg view window when using the "Move to" dialog
4095  */
4096 static void
4097 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4098                                               ModestWindow *win)
4099 {
4100         TnyList *headers = NULL;
4101         TnyAccount *dst_account = NULL;
4102         const gchar *proto_str = NULL;
4103         gboolean dst_is_pop = FALSE;
4104
4105         if (!TNY_IS_FOLDER (dst_folder)) {
4106                 modest_platform_information_banner (GTK_WIDGET (win),
4107                                                     NULL,
4108                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4109                 return;
4110         }
4111
4112         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4113         proto_str = tny_account_get_proto (dst_account);
4114
4115         /* tinymail will return NULL for local folders it seems */
4116         dst_is_pop = proto_str &&
4117                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4118                  MODEST_PROTOCOL_STORE_POP);
4119
4120         g_object_unref (dst_account);
4121
4122         /* Get selected headers */
4123         headers = get_selected_headers (MODEST_WINDOW (win));
4124
4125         if (dst_is_pop) {
4126                 modest_platform_information_banner (GTK_WIDGET (win),
4127                                                     NULL,
4128                                                     ngettext("mail_in_ui_folder_move_target_error",
4129                                                              "mail_in_ui_folder_move_targets_error",
4130                                                              tny_list_get_length (headers)));
4131                 g_object_unref (headers);
4132                 return;
4133         }
4134
4135         GtkWidget *inf_note;
4136         inf_note = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4137                                                      _CS("ckct_nw_pasting"));
4138         if (inf_note != NULL)  {
4139                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4140                 gtk_widget_show (GTK_WIDGET(inf_note));
4141         }
4142
4143         ModestMailOperation *mail_op = 
4144                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4145                                                                G_OBJECT(win),
4146                                                                modest_ui_actions_move_folder_error_handler,
4147                                                                NULL);
4148         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4149                                          mail_op);
4150
4151         modest_mail_operation_xfer_msgs (mail_op, 
4152                                          headers,
4153                                          TNY_FOLDER (dst_folder),
4154                                          TRUE,
4155                                          move_to_cb,
4156                                          inf_note);
4157
4158         g_object_unref (G_OBJECT (mail_op));
4159         g_object_unref (headers);
4160 }
4161
4162 /*
4163  * UI handler for the "Move to" action when invoked from the
4164  * ModestMainWindow
4165  */
4166 static void 
4167 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4168                                           GtkWidget *folder_view,
4169                                           TnyFolderStore *dst_folder,
4170                                           ModestMainWindow *win)
4171 {
4172         ModestHeaderView *header_view = NULL;
4173         ModestMailOperation *mail_op = NULL;
4174         TnyFolderStore *src_folder;
4175         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4176
4177         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4178
4179         /* Get the source folder */
4180         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4181
4182         /* Get header view */
4183         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4184
4185         /* Get folder or messages to transfer */
4186         if (gtk_widget_is_focus (folder_view)) {
4187                 GtkTreeSelection *sel;
4188                 gboolean do_xfer = TRUE;
4189
4190                 /* Allow only to transfer folders to the local root folder */
4191                 if (TNY_IS_ACCOUNT (dst_folder) && 
4192                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4193                         do_xfer = FALSE;
4194                 } else if (!TNY_IS_FOLDER (src_folder)) {
4195                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4196                         do_xfer = FALSE;
4197                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4198                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER(src_folder));
4199                         if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4200                                 do_xfer = FALSE;
4201                         }
4202                 }
4203
4204                 if (do_xfer) {
4205                         GtkWidget *inf_note;
4206                         inf_note = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4207                                                                      _CS("ckct_nw_pasting"));
4208                         if (inf_note != NULL)  {
4209                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4210                                 gtk_widget_show (GTK_WIDGET(inf_note));
4211                         }
4212                         /* Clean folder on header view before moving it */
4213                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4214                         gtk_tree_selection_unselect_all (sel);
4215
4216                         mail_op =
4217                           modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4218                                                                          G_OBJECT(win),
4219                                                                          modest_ui_actions_move_folder_error_handler,
4220                                                                          src_folder);
4221                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4222                                                          mail_op);
4223
4224                         /* Select *after* the changes */
4225                         /* TODO: this function hangs UI after transfer */ 
4226 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4227 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4228                         
4229                         modest_mail_operation_xfer_folder (mail_op,
4230                                                            TNY_FOLDER (src_folder),
4231                                                            dst_folder,
4232                                                            TRUE, 
4233                                                            move_to_cb, 
4234                                                            inf_note);
4235                         /* Unref mail operation */
4236                         g_object_unref (G_OBJECT (mail_op));
4237                 }
4238         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4239                 gboolean do_xfer = TRUE;
4240                 /* Ask for confirmation if the source folder is remote and we're not connected */
4241                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4242                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4243                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4244                                 guint num_headers = tny_list_get_length(headers);
4245                                 if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4246                                         do_xfer = FALSE;
4247                                 }
4248                         }
4249                         g_object_unref(headers);
4250                 }
4251                 if (do_xfer) /* Transfer messages */
4252                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4253         }
4254
4255     if (src_folder)
4256         g_object_unref (src_folder);
4257 }
4258
4259
4260 /*
4261  * UI handler for the "Move to" action when invoked from the
4262  * ModestMsgViewWindow
4263  */
4264 static void 
4265 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4266                                               TnyFolderStore *dst_folder,
4267                                               ModestMsgViewWindow *win)
4268 {
4269         TnyHeader *header = NULL;
4270         TnyFolderStore *src_folder;
4271
4272         /* Create header list */
4273         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4274         src_folder = TNY_FOLDER_STORE(tny_header_get_folder(header));
4275         g_object_unref (header);
4276
4277         /* Transfer the message if online or confirmed by the user */
4278         if (tny_device_is_online (modest_runtime_get_device()) || remote_folder_is_pop(src_folder) ||
4279             (modest_platform_is_network_folderstore(src_folder) && connect_to_get_msg(GTK_WINDOW(win), 1))) {
4280                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4281         }
4282
4283         g_object_unref (src_folder);
4284 }
4285
4286 void 
4287 modest_ui_actions_on_move_to (GtkAction *action, 
4288                               ModestWindow *win)
4289 {
4290         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4291         gint result = 0;
4292         TnyFolderStore *dst_folder = NULL;
4293         ModestMainWindow *main_window;
4294
4295         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4296                           MODEST_IS_MSG_VIEW_WINDOW (win));
4297
4298         /* Get the main window if exists */
4299         if (MODEST_IS_MAIN_WINDOW (win))
4300                 main_window = MODEST_MAIN_WINDOW (win);
4301         else
4302                 main_window = 
4303                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4304
4305         /* Get the folder view widget if exists */
4306         if (main_window)
4307                 folder_view = modest_main_window_get_child_widget (main_window,
4308                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4309         else
4310                 folder_view = NULL;
4311
4312         /* Create and run the dialog */
4313         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4314         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4315         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4316         result = gtk_dialog_run (GTK_DIALOG(dialog));
4317         g_object_ref (tree_view);
4318         gtk_widget_destroy (dialog);
4319
4320         if (result != GTK_RESPONSE_ACCEPT)
4321                 return;
4322
4323         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4324         /* Do window specific stuff */
4325         if (MODEST_IS_MAIN_WINDOW (win)) {
4326                 modest_ui_actions_on_main_window_move_to (action,
4327                                                           folder_view,
4328                                                           dst_folder,
4329                                                           MODEST_MAIN_WINDOW (win));
4330         } else {
4331                 modest_ui_actions_on_msg_view_window_move_to (action,
4332                                                               dst_folder,
4333                                                               MODEST_MSG_VIEW_WINDOW (win));
4334         }
4335
4336         if (dst_folder)
4337                 g_object_unref (dst_folder);
4338 }
4339
4340 /*
4341  * Calls #HeadersFunc for each header already selected in the main
4342  * window or the message currently being shown in the msg view window
4343  */
4344 static void
4345 do_headers_action (ModestWindow *win, 
4346                    HeadersFunc func,
4347                    gpointer user_data)
4348 {
4349         TnyList *headers_list = NULL;
4350         TnyIterator *iter = NULL;
4351         TnyHeader *header = NULL;
4352         TnyFolder *folder = NULL;
4353
4354         /* Get headers */
4355         headers_list = get_selected_headers (win);
4356         if (!headers_list)
4357                 return;
4358
4359         /* Get the folder */
4360         iter = tny_list_create_iterator (headers_list);
4361         header = TNY_HEADER (tny_iterator_get_current (iter));
4362         if (header) {
4363                 folder = tny_header_get_folder (header);
4364                 g_object_unref (header);
4365         }
4366
4367         /* Call the function for each header */
4368         while (!tny_iterator_is_done (iter)) {
4369                 header = TNY_HEADER (tny_iterator_get_current (iter));
4370                 func (header, win, user_data);
4371                 g_object_unref (header);
4372                 tny_iterator_next (iter);
4373         }
4374
4375         /* Trick: do a poke status in order to speed up the signaling
4376            of observers */
4377         tny_folder_poke_status (folder);
4378
4379         /* Frees */
4380         g_object_unref (folder);
4381         g_object_unref (iter);
4382         g_object_unref (headers_list);
4383 }
4384
4385 void 
4386 modest_ui_actions_view_attachment (GtkAction *action,
4387                                    ModestWindow *window)
4388 {
4389         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4390                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4391         } else {
4392                 /* not supported window for this action */
4393                 g_return_if_reached ();
4394         }
4395 }
4396
4397 void
4398 modest_ui_actions_save_attachments (GtkAction *action,
4399                                     ModestWindow *window)
4400 {
4401         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4402                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4403         } else {
4404                 /* not supported window for this action */
4405                 g_return_if_reached ();
4406         }
4407 }
4408
4409 void
4410 modest_ui_actions_remove_attachments (GtkAction *action,
4411                                       ModestWindow *window)
4412 {
4413         if (MODEST_IS_MAIN_WINDOW (window)) {
4414                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4415         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4416                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4417         } else {
4418                 /* not supported window for this action */
4419                 g_return_if_reached ();
4420         }
4421 }
4422
4423 void 
4424 modest_ui_actions_on_settings (GtkAction *action, 
4425                                ModestWindow *win)
4426 {
4427         GtkWidget *dialog;
4428
4429         dialog = modest_platform_get_global_settings_dialog ();
4430         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4431         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4432         gtk_widget_show_all (dialog);
4433
4434         gtk_dialog_run (GTK_DIALOG (dialog));
4435
4436         gtk_widget_destroy (dialog);
4437 }
4438
4439 void 
4440 modest_ui_actions_on_help (GtkAction *action, 
4441                            ModestWindow *win)
4442 {
4443         const gchar *help_id = NULL;
4444
4445         if (MODEST_IS_MAIN_WINDOW (win)) {
4446                 GtkWidget *folder_view;
4447                 TnyFolderStore *folder_store;
4448                 
4449                 /* Get selected folder */
4450                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4451                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4452                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4453
4454                 /* Switch help_id */
4455                 if (TNY_IS_FOLDER (folder_store)) {
4456                         switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4457                         case TNY_FOLDER_TYPE_NORMAL:
4458                                 help_id = "applications_email_managefolders";
4459                                 break;
4460                         case TNY_FOLDER_TYPE_INBOX:
4461                                 help_id = "applications_email_inbox";
4462                                 break;
4463                         case TNY_FOLDER_TYPE_OUTBOX:
4464                                 help_id = "applications_email_outbox";
4465                                 break;
4466                         case TNY_FOLDER_TYPE_SENT:
4467                                 help_id = "applications_email_sent";
4468                                 break;
4469                         case TNY_FOLDER_TYPE_DRAFTS:
4470                                 help_id = "applications_email_drafts";
4471                                 break;
4472                         case TNY_FOLDER_TYPE_ARCHIVE:
4473                                 help_id = "applications_email_managefolders";
4474                                 break;
4475                         default:
4476                                 help_id = "applications_email_managefolders";
4477                         }
4478                 } else {
4479                         help_id = "applications_email_mainview";
4480                 }
4481                 g_object_unref (folder_store);
4482         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4483                 help_id = "applications_email_viewer";
4484         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4485                 help_id = "applications_email_editor";
4486
4487         modest_platform_show_help (GTK_WINDOW (win), help_id);
4488 }
4489
4490 void 
4491 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4492                                             ModestWindow *window)
4493 {
4494         ModestMailOperation *mail_op;
4495         TnyList *headers;
4496
4497         /* Get headers */
4498         headers = get_selected_headers (window);
4499         if (!headers)
4500                 return;
4501
4502         /* Create mail operation */
4503         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4504                                                                  G_OBJECT (window),
4505                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4506                                                                  NULL);
4507         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4508         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4509
4510         /* Frees */
4511         g_object_unref (headers);
4512         g_object_unref (mail_op);
4513 }
4514
4515 void
4516 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4517                                           ModestWindow *window)
4518 {
4519         g_return_if_fail (MODEST_IS_WINDOW (window));
4520         
4521         /* Update dimmed */     
4522         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4523 }
4524
4525 void
4526 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4527                                           ModestWindow *window)
4528 {
4529         g_return_if_fail (MODEST_IS_WINDOW (window));
4530
4531         /* Update dimmed */     
4532         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4533 }
4534
4535 void
4536 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4537                                           ModestWindow *window)
4538 {
4539         g_return_if_fail (MODEST_IS_WINDOW (window));
4540
4541         /* Update dimmed */     
4542         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4543 }
4544
4545 void
4546 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4547                                             ModestWindow *window)
4548 {
4549         g_return_if_fail (MODEST_IS_WINDOW (window));
4550
4551         /* Update dimmed */     
4552         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4553 }
4554
4555 void
4556 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4557                                           ModestWindow *window)
4558 {
4559         g_return_if_fail (MODEST_IS_WINDOW (window));
4560
4561         /* Update dimmed */     
4562         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4563 }
4564
4565 void
4566 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4567                                           ModestWindow *window)
4568 {
4569         g_return_if_fail (MODEST_IS_WINDOW (window));
4570
4571         /* Update dimmed */     
4572         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4573 }
4574
4575 void
4576 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4577                                                  ModestWindow *window)
4578 {
4579         g_return_if_fail (MODEST_IS_WINDOW (window));
4580
4581         /* Update dimmed */     
4582         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4583 }
4584
4585 void
4586 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4587                                                      ModestWindow *window)
4588 {
4589         g_return_if_fail (MODEST_IS_WINDOW (window));
4590
4591         /* Update dimmed */     
4592         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4593 }
4594
4595 void
4596 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4597                                                      ModestWindow *window)
4598 {
4599         g_return_if_fail (MODEST_IS_WINDOW (window));
4600
4601         /* Update dimmed */     
4602         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4603 }
4604
4605 void
4606 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4607 {
4608         g_return_if_fail (MODEST_IS_WINDOW (window));
4609
4610         /* Update dimmed */     
4611         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4612 }
4613
4614 void
4615 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4616 {
4617         g_return_if_fail (MODEST_IS_WINDOW (window));
4618
4619         modest_platform_show_search_messages (GTK_WINDOW (window));
4620 }
4621
4622 void     
4623 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4624 {
4625         g_return_if_fail (MODEST_IS_WINDOW (win));
4626         modest_platform_show_addressbook (GTK_WINDOW (win));
4627 }
4628
4629
4630 void
4631 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4632                                           ModestWindow *window)
4633 {
4634         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4635
4636         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4637 }
4638
4639 static void 
4640 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4641                                    ModestMailOperationState *state,
4642                                    gpointer user_data)
4643 {
4644         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4645
4646         /* Set send/receive operation finished */       
4647         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4648                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4649         
4650 }
4651
4652
4653 void 
4654 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4655                                                 TnyHeader *header, 
4656                                                 TnyMsg *msg, 
4657                                                 GError *err, 
4658                                                 gpointer user_data)
4659 {
4660         const gchar* server_name = NULL;
4661         TnyTransportAccount *server_account;
4662         gchar *message = NULL;
4663
4664         /* Don't show anything if the user cancelled something */
4665         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4666                 return;
4667
4668         /* Get the server name: */
4669         server_account = 
4670                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4671         if (server_account) {
4672                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4673                         
4674                 g_object_unref (server_account);
4675                 server_account = NULL;
4676         }
4677         
4678         g_return_if_fail (server_name);
4679
4680         /* Show the appropriate message text for the GError: */
4681         switch (err->code) {
4682         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4683                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4684                 break;
4685         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4686                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4687                 break;
4688         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4689                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4690                 break;
4691         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4692                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4693                 break;
4694         default:
4695                 g_return_if_reached ();
4696         }
4697         
4698         /* TODO if the username or the password where not defined we
4699            should show the Accounts Settings dialog or the Connection
4700            specific SMTP server window */
4701
4702         modest_platform_run_information_dialog (NULL, message);
4703         g_free (message);
4704 }
4705
4706 void
4707 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
4708                                                 gchar *msg_id, 
4709                                                 guint status,
4710                                                 gpointer user_data)
4711 {
4712         ModestMainWindow *main_window = NULL;
4713         ModestWindowMgr *mgr = NULL;
4714         GtkWidget *folder_view = NULL, *header_view = NULL;
4715         TnyFolderStore *selected_folder = NULL;
4716         TnyFolderType folder_type;
4717
4718         mgr = modest_runtime_get_window_mgr ();
4719         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr));
4720
4721         if (!main_window)
4722                 return;
4723
4724         /* Check if selected folder is OUTBOX */
4725         folder_view = modest_main_window_get_child_widget (main_window,
4726                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4727         header_view = modest_main_window_get_child_widget (main_window,
4728                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4729
4730         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4731         if (!TNY_IS_FOLDER (selected_folder)) 
4732                 goto frees;
4733
4734         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
4735 #if GTK_CHECK_VERSION(2, 8, 0) 
4736         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
4737         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
4738                 GtkTreeViewColumn *tree_column;
4739
4740                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
4741                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
4742                 gtk_tree_view_column_queue_resize (tree_column);
4743         }
4744 #else
4745         gtk_widget_queue_draw (header_view);
4746 #endif          
4747         
4748         /* Free */
4749  frees:
4750         if (selected_folder != NULL)
4751                 g_object_unref (selected_folder);
4752 }