111fd032d9cbd18d267eeeb686193d714965eb9d
[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
48 #ifdef MODEST_PLATFORM_MAEMO
49 #include "maemo/modest-osso-state-saving.h"
50 #endif /* MODEST_PLATFORM_MAEMO */
51
52 #include "widgets/modest-ui-constants.h"
53 #include <widgets/modest-main-window.h>
54 #include <widgets/modest-msg-view-window.h>
55 #include <widgets/modest-account-view-window.h>
56 #include <widgets/modest-details-dialog.h>
57 #include <widgets/modest-attachments-view.h>
58 #include "widgets/modest-folder-view.h"
59 #include "widgets/modest-global-settings-dialog.h"
60 #include "modest-connection-specific-smtp-window.h"
61 #include "modest-account-mgr-helpers.h"
62 #include "modest-mail-operation.h"
63 #include "modest-text-utils.h"
64
65 #ifdef MODEST_HAVE_EASYSETUP
66 #include "easysetup/modest-easysetup-wizard.h"
67 #endif /* MODEST_HAVE_EASYSETUP */
68
69 #include <modest-widget-memory.h>
70 #include <tny-error.h>
71 #include <tny-simple-list.h>
72 #include <tny-msg-view.h>
73 #include <tny-device.h>
74 #include <tny-merge-folder.h>
75
76 #include <gtkhtml/gtkhtml.h>
77
78 typedef struct _GetMsgAsyncHelper {     
79         ModestWindow *window;
80         ModestMailOperation *mail_op;
81         TnyIterator *iter;
82         guint num_ops;
83         GFunc func;     
84         gpointer user_data;
85 } GetMsgAsyncHelper;
86
87 typedef enum _ReplyForwardAction {
88         ACTION_REPLY,
89         ACTION_REPLY_TO_ALL,
90         ACTION_FORWARD
91 } ReplyForwardAction;
92
93 typedef struct _ReplyForwardHelper {
94         guint reply_forward_type;
95         ReplyForwardAction action;
96         gchar *account_name;
97         GtkWidget *parent_window;
98 } ReplyForwardHelper;
99
100
101 /*
102  * The do_headers_action uses this kind of functions to perform some
103  * action to each member of a list of headers
104  */
105 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
106
107 static void
108 do_headers_action (ModestWindow *win, 
109                    HeadersFunc func,
110                    gpointer user_data);
111
112
113 static void     open_msg_cb            (ModestMailOperation *mail_op, 
114                                         TnyHeader *header, 
115                                         TnyMsg *msg,
116                                         gpointer user_data);
117
118 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
119                                         TnyHeader *header, 
120                                         TnyMsg *msg,
121                                         gpointer user_data);
122
123 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
124
125 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
126
127
128 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
129                                                    ModestMailOperationState *state,
130                                                    gpointer user_data);
131
132
133
134 static void
135 run_account_setup_wizard (ModestWindow *win)
136 {
137         ModestEasysetupWizardDialog *wizard;
138
139         g_return_if_fail (MODEST_IS_WINDOW(win));
140         
141         wizard = modest_easysetup_wizard_dialog_new ();
142         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
143         gtk_dialog_run (GTK_DIALOG (wizard));
144         gtk_widget_destroy (GTK_WIDGET (wizard));
145 }
146
147
148 void   
149 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
150 {
151         GtkWidget *about;
152         const gchar *authors[] = {
153                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
154                 NULL
155         };
156         about = gtk_about_dialog_new ();
157         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
158         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
159         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
160                                         _("Copyright (c) 2006, Nokia Corporation\n"
161                                           "All rights reserved."));
162         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
163                                        _("a modest e-mail client\n\n"
164                                          "design and implementation: Dirk-Jan C. Binnema\n"
165                                          "contributions from the fine people at KC and Ig\n"
166                                          "uses the tinymail email framework written by Philip van Hoof"));
167         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
168         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
169         
170         gtk_dialog_run (GTK_DIALOG (about));
171         gtk_widget_destroy(about);
172 }
173
174 /*
175  * Gets the list of currently selected messages. If the win is the
176  * main window, then it returns a newly allocated list of the headers
177  * selected in the header view. If win is the msg view window, then
178  * the value returned is a list with just a single header.
179  *
180  * The caller of this funcion must free the list.
181  */
182 static TnyList *
183 get_selected_headers (ModestWindow *win)
184 {
185         if (MODEST_IS_MAIN_WINDOW(win)) {
186                 GtkWidget *header_view;         
187                 
188                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
189                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
190                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
191                 
192         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
193                 /* for MsgViewWindows, we simply return a list with one element */
194                 TnyHeader *header;
195                 TnyList *list = NULL;
196                 
197                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
198                 if (header != NULL) {
199                         list = tny_simple_list_new ();
200                         tny_list_prepend (list, G_OBJECT(header));
201                         g_object_unref (G_OBJECT(header));
202                 }
203
204                 return list;
205
206         } else
207                 return NULL;
208 }
209
210 static void
211 headers_action_mark_as_read (TnyHeader *header,
212                              ModestWindow *win,
213                              gpointer user_data)
214 {
215         TnyHeaderFlags flags;
216
217         g_return_if_fail (TNY_IS_HEADER(header));
218
219         flags = tny_header_get_flags (header);
220         if (flags & TNY_HEADER_FLAG_SEEN) return;
221         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
222 }
223
224 static void
225 headers_action_mark_as_unread (TnyHeader *header,
226                                ModestWindow *win,
227                                gpointer user_data)
228 {
229         TnyHeaderFlags flags;
230
231         g_return_if_fail (TNY_IS_HEADER(header));
232
233         flags = tny_header_get_flags (header);
234         if (flags & TNY_HEADER_FLAG_SEEN)  {
235                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
236         }
237 }
238
239
240 static void
241 headers_action_delete (TnyHeader *header,
242                        ModestWindow *win,
243                        gpointer user_data)
244 {
245         ModestMailOperation *mail_op = NULL;
246
247         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, G_OBJECT(win));
248         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
249                                          mail_op);
250         
251         /* Always delete. TODO: Move to trash still not supported */
252         modest_mail_operation_remove_msg (mail_op, header, FALSE);
253         g_object_unref (G_OBJECT (mail_op));
254 }
255
256 void
257 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
258 {
259         TnyList *header_list = NULL;
260         TnyIterator *iter = NULL;
261         TnyHeader *header = NULL;
262         gchar *message = NULL;
263         gchar *desc = NULL;
264         gint response;
265         gboolean found;
266         ModestWindowMgr *mgr;
267         GtkWidget *header_view;
268
269         g_return_if_fail (MODEST_IS_WINDOW(win));
270
271         /* Check first if the header view has the focus */
272         if (MODEST_IS_MAIN_WINDOW (win)) {
273                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
274                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
275                 if (!gtk_widget_is_focus (header_view))
276                         return;
277         }
278
279         header_list = get_selected_headers (win);
280         if (!header_list) return;
281
282         /* Check if any of the headers is already opened */
283         iter = tny_list_create_iterator (header_list);
284         found = FALSE;
285         mgr = modest_runtime_get_window_mgr ();
286         while (!tny_iterator_is_done (iter) && !found) {
287                 header = TNY_HEADER (tny_iterator_get_current (iter));
288                 if (modest_window_mgr_find_window_by_header (mgr, header))
289                         found = TRUE;
290                 g_object_unref (header);
291                 tny_iterator_next (iter);
292         }
293         g_object_unref (iter);
294
295         if (found) {
296                 gchar *num, *msg;
297
298                 num = g_strdup_printf ("%d", tny_list_get_length (header_list));
299                 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
300
301                 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
302
303                 g_free (msg);
304                 g_free (num);
305                 g_object_unref (header_list);
306                 return;
307         }
308
309         /* Select message */
310         if (tny_list_get_length(header_list) == 1) {
311                 iter = tny_list_create_iterator (header_list);
312                 header = TNY_HEADER (tny_iterator_get_current (iter));
313                 desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
314                 g_object_unref (header);
315                 g_object_unref (iter);
316         }
317         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
318                                            tny_list_get_length(header_list)), desc);
319
320         /* Confirmation dialog */               
321         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
322                                                             message);
323         
324
325         if (response == GTK_RESPONSE_OK) {
326                 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
327                         gboolean ret_value;
328                         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
329                         return;
330                 }
331                 
332                 /* Remove each header */
333                 do_headers_action (win, headers_action_delete, NULL);
334
335                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
336                         gtk_widget_destroy (GTK_WIDGET(win));
337                 } 
338         }
339
340         /* free */
341         g_free(message);
342         g_free(desc);
343         g_object_unref (header_list);
344 }
345
346
347 void
348 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
349 {
350         #ifdef MODEST_PLATFORM_MAEMO
351         modest_osso_save_state();
352         #endif /* MODEST_PLATFORM_MAEMO */
353         
354         gtk_main_quit ();
355 }
356
357 void
358 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
359 {
360         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
361                 gtk_widget_destroy (GTK_WIDGET (win));
362         } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
363                 gboolean ret_value;
364                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
365         } else if (MODEST_IS_WINDOW (win)) {
366                 gtk_widget_destroy (GTK_WIDGET (win));
367         } else {
368                 g_return_if_reached ();
369         }
370 }
371
372 void
373 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
374 {
375         GtkClipboard *clipboard = NULL;
376         gchar *selection = NULL;
377
378         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
379         selection = gtk_clipboard_wait_for_text (clipboard);
380
381         /* Question: why is the clipboard being used here? 
382          * It doesn't really make a lot of sense. */
383
384         if (selection)
385         {
386                 modest_address_book_add_address (selection);
387                 g_free (selection);
388         }
389 }
390
391 void
392 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
393 {
394         /* This is currently only implemented for Maemo */
395 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
396         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
397                 run_account_setup_wizard (win);
398                 return;
399         } else  {
400                 /* Show the list of accounts: */
401                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
402                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
403                 gtk_dialog_run (account_win);
404                 gtk_widget_destroy (GTK_WIDGET(account_win));
405         }
406 #else
407         GtkWidget *dialog, *label;
408         
409         /* Create the widgets */
410         
411         dialog = gtk_dialog_new_with_buttons ("Message",
412                                               GTK_WINDOW(win),
413                                               GTK_DIALOG_DESTROY_WITH_PARENT,
414                                               GTK_STOCK_OK,
415                                               GTK_RESPONSE_NONE,
416                                               NULL);
417         label = gtk_label_new ("Hello World!");
418         
419         /* Ensure that the dialog box is destroyed when the user responds. */
420         
421         g_signal_connect_swapped (dialog, "response", 
422                                   G_CALLBACK (gtk_widget_destroy),
423                                   dialog);
424         
425         /* Add the label, and show everything we've added to the dialog. */
426         
427         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
428                            label);
429         gtk_widget_show_all (dialog);
430 #endif /* MODEST_PLATFORM_MAEMO */
431 }
432
433 static void
434 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
435 {
436         ModestWindow *main_window = MODEST_WINDOW (user_data);
437         
438         /* Save any changes. */
439         modest_connection_specific_smtp_window_save_server_accounts (
440                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
441                         modest_window_get_active_account (main_window));
442         gtk_widget_destroy (GTK_WIDGET (window));
443 }
444
445
446
447 void
448 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
449 {
450         /* This is currently only implemented for Maemo,
451          * because it requires an API (libconic) to detect different connection 
452          * possiblities.
453          */
454 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
455         
456         /* Create the window if necessary: */
457         const gchar *active_account_name = modest_window_get_active_account (win);
458         
459         /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
460          * or show the default account?
461          * If we show the default account then the account name should be shown in 
462          * the window when we show it. */
463         if (!active_account_name) {
464                 g_warning ("%s: No account is active.", __FUNCTION__);
465                 return;
466         }
467                 
468         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
469         modest_connection_specific_smtp_window_fill_with_connections (
470                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
471                 modest_runtime_get_account_mgr(), 
472                 active_account_name);
473
474         /* Show the window: */  
475         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
476         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
477         gtk_widget_show (specific_window);
478     
479         /* Save changes when the window is hidden: */
480         g_signal_connect (specific_window, "hide", 
481                 G_CALLBACK (on_smtp_servers_window_hide), win);
482 #endif /* MODEST_PLATFORM_MAEMO */
483 }
484
485 void
486 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
487 {
488         ModestWindow *msg_win;
489         TnyMsg *msg = NULL;
490         TnyFolder *folder = NULL;
491         gchar *account_name = NULL;
492         gchar *from_str = NULL;
493 /*      GError *err = NULL; */
494         TnyAccount *account = NULL;
495         ModestWindowMgr *mgr;
496         gchar *signature = NULL, *blank_and_signature = NULL;
497
498         /* if there are no accounts yet, just show the wizard */
499         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
500                         run_account_setup_wizard (win);
501                         return;
502         }
503         
504         account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
505         if (!account_name)
506                 account_name = g_strdup (modest_window_get_active_account (win));
507         if (!account_name) {
508                 g_printerr ("modest: no account found\n");
509                 goto cleanup;
510         }
511         
512         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
513                                                                        account_name,
514                                                                        TNY_ACCOUNT_TYPE_STORE);
515         if (!account) {
516                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
517                 goto cleanup;
518         }
519
520         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
521         if (!from_str) {
522                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
523                 goto cleanup;
524         }
525
526         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
527                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
528                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
529                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
530                 blank_and_signature = g_strconcat ("\n", signature, NULL);
531                 g_free (signature);
532         } else {
533                 blank_and_signature = g_strdup ("");
534         }
535
536         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
537         if (!msg) {
538                 g_printerr ("modest: failed to create new msg\n");
539                 goto cleanup;
540         }
541         
542         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
543         if (!folder) {
544                 g_printerr ("modest: failed to find Drafts folder\n");
545                 goto cleanup;
546         }
547         
548
549         /* Create and register edit window */
550         /* This is destroyed by TOOD. */
551         msg_win = modest_msg_edit_window_new (msg, account_name);
552         mgr = modest_runtime_get_window_mgr ();
553         modest_window_mgr_register_window (mgr, msg_win);
554
555         if (win)
556                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
557                                               GTK_WINDOW (win));        
558         gtk_widget_show_all (GTK_WIDGET (msg_win));
559
560 cleanup:
561         g_free (account_name);
562         g_free (from_str);
563         g_free (blank_and_signature);
564         if (account)
565                 g_object_unref (G_OBJECT(account));
566         if (msg)
567                 g_object_unref (G_OBJECT(msg));
568         if (folder)
569                 g_object_unref (G_OBJECT(folder));
570 }
571
572 static void
573 open_msg_cb (ModestMailOperation *mail_op, 
574              TnyHeader *header, 
575              TnyMsg *msg, 
576              gpointer user_data)
577 {
578         ModestWindowMgr *mgr = NULL;
579         ModestWindow *parent_win = NULL;
580         ModestWindow *win = NULL;
581         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
582         gchar *account = NULL;
583         TnyFolder *folder;
584         
585         /* TODO: Show an error? (review the specs) */
586         if (!msg)
587                 return;
588
589         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
590         folder = tny_header_get_folder (header);
591
592         /* Mark header as read */
593         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
594
595         /* Get account */
596         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
597         if (!account)
598                 account =  g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
599         
600         /* Gets folder type (OUTBOX headers will be opened in edit window */
601         if (modest_tny_folder_is_local_folder (folder))
602                 folder_type = modest_tny_folder_get_local_folder_type (folder);
603
604         /* If the header is in the drafts folder then open the editor,
605            else the message view window */
606         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
607                 /* we cannot edit without a valid account... */
608                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
609                         run_account_setup_wizard(parent_win);
610                         goto cleanup;
611                 }
612                 win = modest_msg_edit_window_new (msg, account);
613         } else {
614                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
615
616                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
617                         GtkWidget *header_view;
618                         GtkTreeSelection *sel;
619                         GList *sel_list = NULL;
620                         GtkTreeModel *model;
621                 
622                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
623                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
624
625                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
626                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
627
628                         if (sel_list != NULL) {
629                                 GtkTreeRowReference *row_reference;
630
631                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
632                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
633                                 g_list_free (sel_list);
634                                 
635                                 win = modest_msg_view_window_new_with_header_model (msg, 
636                                                                                     account,
637                                                                                     (const gchar*) uid,
638                                                                                     model, 
639                                                                                     row_reference);
640                                 gtk_tree_row_reference_free (row_reference);
641                         } else {
642                                 win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
643                         }
644                 } else {
645                         win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
646                 }
647                 g_free (uid);
648         }
649         
650         /* Register and show new window */
651         if (win != NULL) {
652                 mgr = modest_runtime_get_window_mgr ();
653                 modest_window_mgr_register_window (mgr, win);
654                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
655                 gtk_widget_show_all (GTK_WIDGET(win));
656         }
657
658 cleanup:
659         /* Free */
660         g_free(account);
661         g_object_unref (parent_win);
662         g_object_unref (msg);
663         g_object_unref (folder);
664         g_object_unref (header);
665 }
666
667 /*
668  * This function is the error handler of the
669  * modest_mail_operation_get_msgs_full operation
670  */
671 static void
672 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
673                                                gpointer user_data)
674 {
675         const GError *error;
676
677         error = modest_mail_operation_get_error (mail_op);
678         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
679                 GObject *win = modest_mail_operation_get_source (mail_op);
680
681                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
682                                                         error->message);
683                 g_object_unref (win);
684         }
685 }
686
687 /*
688  * This function is used by both modest_ui_actions_on_open and
689  * modest_ui_actions_on_header_activated. This way we always do the
690  * same when trying to open messages.
691  */
692 static void
693 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
694 {
695         ModestWindowMgr *mgr;
696         TnyIterator *iter;
697         ModestMailOperation *mail_op;
698         TnyList *not_opened_headers;
699
700         /* Look if we already have a message view for each header. If
701            true, then remove the header from the list of headers to
702            open */
703         mgr = modest_runtime_get_window_mgr ();
704         iter = tny_list_create_iterator (headers);
705         not_opened_headers = tny_simple_list_new ();
706         while (!tny_iterator_is_done (iter)) {
707                 ModestWindow *window;
708                 TnyHeader *header;
709                 
710                 header = TNY_HEADER (tny_iterator_get_current (iter));
711                 window = modest_window_mgr_find_window_by_header (mgr, header);
712                 /* Do not open again the message and present the
713                    window to the user */
714                 if (window)
715                         gtk_window_present (GTK_WINDOW (window));
716                 else
717                         tny_list_append (not_opened_headers, G_OBJECT (header));
718
719                 g_object_unref (header);
720                 tny_iterator_next (iter);
721         }
722         
723         /* Open each message */
724         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
725                                                                  G_OBJECT (win), 
726                                                                  modest_ui_actions_get_msgs_full_error_handler, 
727                                                                  NULL);
728         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
729         if (tny_list_get_length (not_opened_headers) > 1) {
730                 modest_mail_operation_get_msgs_full (mail_op, 
731                                                      not_opened_headers, 
732                                                      open_msg_cb, 
733                                                      NULL, 
734                                                      NULL);
735         } else {
736                 TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
737                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
738                 modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
739                 g_object_unref (header);
740                 g_object_unref (iter);
741         }
742
743         /* Clean */
744         g_object_unref (not_opened_headers);
745         g_object_unref (iter);
746         g_object_unref (mail_op);
747 }
748
749 void
750 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
751 {
752         TnyList *headers;
753
754         /* Get headers */
755         headers = get_selected_headers (win);
756         if (!headers)
757                 return;
758
759         /* Open them */
760         _modest_ui_actions_open (headers, win);
761
762         g_object_unref(headers);
763 }
764
765
766 static void
767 free_reply_forward_helper (gpointer data)
768 {
769         ReplyForwardHelper *helper;
770
771         helper = (ReplyForwardHelper *) data;
772         g_free (helper->account_name);
773         g_slice_free (ReplyForwardHelper, helper);
774 }
775
776 static void
777 reply_forward_cb (ModestMailOperation *mail_op, 
778                   TnyHeader *header, 
779                   TnyMsg *msg,
780                   gpointer user_data)
781 {
782         TnyMsg *new_msg;
783         ReplyForwardHelper *rf_helper;
784         ModestWindow *msg_win;
785         ModestEditType edit_type;
786         gchar *from;
787         TnyAccount *account = NULL;
788         ModestWindowMgr *mgr;
789         gchar *signature = NULL;
790                         
791         g_return_if_fail (user_data != NULL);
792         rf_helper = (ReplyForwardHelper *) user_data;
793
794         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
795                                                    rf_helper->account_name);
796         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
797                                          rf_helper->account_name,
798                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
799                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
800                                                            rf_helper->account_name,
801                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
802         }
803
804         /* Create reply mail */
805         switch (rf_helper->action) {
806         case ACTION_REPLY:
807                 new_msg = 
808                         modest_tny_msg_create_reply_msg (msg,  from, signature,
809                                                          rf_helper->reply_forward_type,
810                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
811                 break;
812         case ACTION_REPLY_TO_ALL:
813                 new_msg = 
814                         modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
815                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
816                 edit_type = MODEST_EDIT_TYPE_REPLY;
817                 break;
818         case ACTION_FORWARD:
819                 new_msg = 
820                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
821                 edit_type = MODEST_EDIT_TYPE_FORWARD;
822                 break;
823         default:
824                 g_return_if_reached ();
825                 return;
826         }
827
828         g_free (signature);
829
830         if (!new_msg) {
831                 g_printerr ("modest: failed to create message\n");
832                 goto cleanup;
833         }
834
835         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
836                                                                        rf_helper->account_name,
837                                                                        TNY_ACCOUNT_TYPE_STORE);
838         if (!account) {
839                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
840                 goto cleanup;
841         }
842
843         /* Create and register the windows */
844         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
845         mgr = modest_runtime_get_window_mgr ();
846         modest_window_mgr_register_window (mgr, msg_win);
847
848         if (rf_helper->parent_window != NULL) {
849                 gdouble parent_zoom;
850
851                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
852                 modest_window_set_zoom (msg_win, parent_zoom);
853         }
854
855         /* Show edit window */
856         gtk_widget_show_all (GTK_WIDGET (msg_win));
857
858 cleanup:
859         if (new_msg)
860                 g_object_unref (G_OBJECT (new_msg));
861         if (account)
862                 g_object_unref (G_OBJECT (account));
863         g_object_unref (msg);
864         g_object_unref (header);
865 }
866
867 /*
868  * Checks a list of headers. If any of them are not currently
869  * downloaded (CACHED) then it asks the user for permission to
870  * download them.
871  *
872  * Returns FALSE if the user does not want to download the
873  * messages. Returns TRUE if the user allowed the download or if all
874  * of them are currently downloaded
875  */
876 static gboolean
877 download_uncached_messages (TnyList *header_list, GtkWindow *win)
878 {
879         TnyIterator *iter;
880         gboolean found, retval;
881
882         iter = tny_list_create_iterator (header_list);
883         found = FALSE;
884         while (!tny_iterator_is_done (iter) && !found) {
885                 TnyHeader *header;
886                 TnyHeaderFlags flags;
887
888                 header = TNY_HEADER (tny_iterator_get_current (iter));
889                 flags = tny_header_get_flags (header);
890                 /* TODO: is this the right flag?, it seems that some
891                    headers that have been previously downloaded do not
892                    come with it */
893                 found = !(flags & TNY_HEADER_FLAG_CACHED);
894                 g_object_unref (header);
895                 tny_iterator_next (iter);
896         }
897         g_object_unref (iter);
898
899         /* Ask for user permission to download the messages */
900         retval = TRUE;
901         if (found) {
902                 GtkResponseType response;
903                 response = 
904                         modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
905                                                                  _("mcen_nc_get_multi_msg_txt"));
906                 if (response == GTK_RESPONSE_CANCEL)
907                         retval = FALSE;
908         }
909         return retval;
910 }
911
912
913 /*
914  * Common code for the reply and forward actions
915  */
916 static void
917 reply_forward (ReplyForwardAction action, ModestWindow *win)
918 {
919         ModestMailOperation *mail_op = NULL;
920         TnyList *header_list = NULL;
921         ReplyForwardHelper *rf_helper = NULL;
922         guint reply_forward_type;
923         gboolean continue_download;
924         
925         g_return_if_fail (MODEST_IS_WINDOW(win));
926
927         /* we need an account when editing */
928         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
929                 run_account_setup_wizard (win);
930                 return;
931         }
932         
933         header_list = get_selected_headers (win);
934         if (!header_list)
935                 return;
936
937         /* Check that the messages have been previously downloaded */
938         continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
939         if (!continue_download) {
940                 g_object_unref (header_list);
941                 return;
942         }
943         
944         reply_forward_type = 
945                 modest_conf_get_int (modest_runtime_get_conf (),
946                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
947                                      NULL);
948         /* We assume that we can only select messages of the
949            same folder and that we reply all of them from the
950            same account. In fact the interface currently only
951            allows single selection */
952         
953         /* Fill helpers */
954         rf_helper = g_slice_new0 (ReplyForwardHelper);
955         rf_helper->reply_forward_type = reply_forward_type;
956         rf_helper->action = action;
957         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
958         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
959                 rf_helper->parent_window = GTK_WIDGET (win);
960         if (!rf_helper->account_name)
961                 rf_helper->account_name =
962                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
963
964         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
965                 TnyMsg *msg;
966                 TnyHeader *header;
967                 /* Get header and message. Do not free them here, the
968                    reply_forward_cb must do it */
969                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
970                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
971                 if (!msg || !header) {
972                         if (msg)
973                                 g_object_unref (msg);
974                         if (header)
975                                 g_object_unref (header);
976                         g_printerr ("modest: no message found\n");
977                         return;
978                 } else
979                         reply_forward_cb (NULL, header, msg, rf_helper);
980         } else {
981                 /* Retrieve messages */
982                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
983                                                                          G_OBJECT(win),
984                                                                          modest_ui_actions_get_msgs_full_error_handler, 
985                                                                          NULL);
986                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
987                 modest_mail_operation_get_msgs_full (mail_op, 
988                                                      header_list, 
989                                                      reply_forward_cb, 
990                                                      rf_helper, 
991                                                      free_reply_forward_helper);
992
993                 /* Clean */
994                 g_object_unref(mail_op);
995         }
996
997         /* Free */
998         g_object_unref (header_list);
999 }
1000
1001 void
1002 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1003 {
1004         g_return_if_fail (MODEST_IS_WINDOW(win));
1005
1006         reply_forward (ACTION_REPLY, win);
1007 }
1008
1009 void
1010 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1011 {
1012         g_return_if_fail (MODEST_IS_WINDOW(win));
1013
1014         reply_forward (ACTION_FORWARD, win);
1015 }
1016
1017 void
1018 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1019 {
1020         g_return_if_fail (MODEST_IS_WINDOW(win));
1021
1022         reply_forward (ACTION_REPLY_TO_ALL, win);
1023 }
1024
1025 void 
1026 modest_ui_actions_on_next (GtkAction *action, 
1027                            ModestWindow *window)
1028 {
1029         if (MODEST_IS_MAIN_WINDOW (window)) {
1030                 GtkWidget *header_view;
1031
1032                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1033                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1034                 if (!header_view)
1035                         return;
1036         
1037                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
1038         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1039                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
1040         } else {
1041                 g_return_if_reached ();
1042         }
1043 }
1044
1045 void 
1046 modest_ui_actions_on_prev (GtkAction *action, 
1047                            ModestWindow *window)
1048 {
1049         g_return_if_fail (MODEST_IS_WINDOW(window));
1050
1051         if (MODEST_IS_MAIN_WINDOW (window)) {
1052                 GtkWidget *header_view;
1053                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1054                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1055                 if (!header_view)
1056                         return;
1057                 
1058                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1059         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1060                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1061         } else {
1062                 g_return_if_reached ();
1063         }
1064 }
1065
1066 void 
1067 modest_ui_actions_on_sort (GtkAction *action, 
1068                            ModestWindow *window)
1069 {
1070         g_return_if_fail (MODEST_IS_WINDOW(window));
1071
1072         if (MODEST_IS_MAIN_WINDOW (window)) {
1073                 GtkWidget *header_view;
1074                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1075                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1076                 if (!header_view)
1077                         return;
1078
1079                 /* Show sorting dialog */
1080                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1081         }
1082 }
1083
1084 static void
1085 new_messages_arrived (ModestMailOperation *self, 
1086                       gint new_messages,
1087                       gpointer user_data)
1088 {
1089         if (new_messages == 0)
1090                 return;
1091
1092         modest_platform_on_new_msg ();
1093 }
1094
1095 /*
1096  * This function performs the send & receive required actions. The
1097  * window is used to create the mail operation. Typically it should
1098  * always be the main window, but we pass it as argument in order to
1099  * be more flexible.
1100  */
1101 void
1102 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1103 {
1104         gchar *acc_name = NULL;
1105         ModestMailOperation *mail_op;
1106
1107         /* If no account name was provided then get the current account, and if
1108            there is no current account then pick the default one: */
1109         if (!account_name) {
1110                 acc_name = g_strdup (modest_window_get_active_account(win));
1111                 if (!acc_name)
1112                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1113                 if (!acc_name) {
1114                         g_printerr ("modest: cannot get default account\n");
1115                         return;
1116                 }
1117         } else {
1118                 acc_name = g_strdup (account_name);
1119         }
1120
1121         /* Set send/receive operation in progress */    
1122         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1123
1124         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
1125         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1126                           G_CALLBACK (_on_send_receive_progress_changed), 
1127                           win);
1128
1129         /* Send & receive. */
1130         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1131         /* Receive and then send. The operation is tagged initially as
1132            a receive operation because the account update performs a
1133            receive and then a send. The operation changes its type
1134            internally, so the progress objects will receive the proper
1135            progress information */
1136         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1137         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, NULL);
1138         g_object_unref (G_OBJECT (mail_op));
1139         
1140         /* Free */
1141         g_free (acc_name);
1142 }
1143
1144 /*
1145  * Refreshes all accounts. This function will be used by automatic
1146  * updates
1147  */
1148 void
1149 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1150 {
1151         GSList *account_names, *iter;
1152
1153         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1154                                                           TRUE);
1155
1156         iter = account_names;
1157         while (iter) {                  
1158                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1159                 iter = g_slist_next (iter);
1160         }
1161
1162         modest_account_mgr_free_account_names (account_names);
1163         account_names = NULL;
1164 }
1165
1166 /*
1167  * Handler of the click on Send&Receive button in the main toolbar
1168  */
1169 void
1170 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
1171 {
1172         /* Check if accounts exist */
1173         gboolean accounts_exist = 
1174                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1175         
1176         /* If not, allow the user to create an account before trying to send/receive. */
1177         if (!accounts_exist)
1178                 modest_ui_actions_on_accounts (NULL, win);
1179         
1180         /* Refresh the active account */
1181         modest_ui_actions_do_send_receive (NULL, win);
1182 }
1183
1184
1185 void
1186 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1187 {
1188         ModestConf *conf;
1189         GtkWidget *header_view;
1190         
1191         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1192
1193         header_view = modest_main_window_get_child_widget (main_window,
1194                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1195         if (!header_view)
1196                 return;
1197
1198         conf = modest_runtime_get_conf ();
1199         
1200         /* what is saved/restored is depending on the style; thus; we save with
1201          * old style, then update the style, and restore for this new style
1202          */
1203         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1204         
1205         if (modest_header_view_get_style
1206             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1207                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1208                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1209         else
1210                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1211                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1212
1213         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1214                                       MODEST_CONF_HEADER_VIEW_KEY);
1215 }
1216
1217
1218 void 
1219 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1220                                       TnyHeader *header,
1221                                       ModestMainWindow *main_window)
1222 {
1223         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1224         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1225         
1226         /* If no header has been selected then exit */
1227         if (!header)
1228                 return;
1229         
1230         /* Update Main window title */
1231         if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
1232                 const gchar *subject = tny_header_get_subject (header);
1233                 if (subject && strlen(subject) > 0)
1234                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1235                 else
1236                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1237         }
1238
1239         /* Update toolbar dimming state */
1240         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1241 }
1242
1243 void
1244 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1245                                        TnyHeader *header,
1246                                        ModestMainWindow *main_window)
1247 {
1248         TnyList *headers;
1249
1250         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1251         
1252         if (!header)
1253                 return;
1254
1255         headers = tny_simple_list_new ();
1256         tny_list_prepend (headers, G_OBJECT (header));
1257
1258         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1259
1260         g_object_unref (headers);
1261 }
1262
1263 static void
1264 set_active_account_from_tny_account (TnyAccount *account,
1265                                      ModestWindow *window)
1266 {
1267         const gchar *server_acc_name = tny_account_get_id (account);
1268         
1269         /* We need the TnyAccount provided by the
1270            account store because that is the one that
1271            knows the name of the Modest account */
1272         TnyAccount *modest_server_account = modest_server_account = 
1273                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1274                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1275                                                              server_acc_name);
1276         
1277         const gchar *modest_acc_name = 
1278                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1279         modest_window_set_active_account (window, modest_acc_name);
1280         g_object_unref (modest_server_account);
1281 }
1282
1283
1284 static void
1285 folder_refreshed_cb (const GObject *obj, 
1286                      TnyFolder *folder, 
1287                      gpointer user_data)
1288 {
1289         ModestMainWindow *win = NULL;
1290         GtkWidget *header_view;
1291
1292         g_return_if_fail (TNY_IS_FOLDER (folder));
1293
1294         win = MODEST_MAIN_WINDOW (user_data);
1295         header_view = 
1296                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1297
1298         /* Check if folder is empty and set headers view contents style */
1299         if (tny_folder_get_all_count (folder) == 0) {
1300         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1301                 modest_main_window_set_contents_style (win,
1302                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1303         } else {
1304                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1305         }
1306 }
1307
1308 void 
1309 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1310                                                TnyFolderStore *folder_store, 
1311                                                gboolean selected,
1312                                                ModestMainWindow *main_window)
1313 {
1314         ModestConf *conf;
1315         GtkWidget *header_view;
1316
1317         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1318
1319         header_view = modest_main_window_get_child_widget(main_window,
1320                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1321         if (!header_view)
1322                 return;
1323         
1324         conf = modest_runtime_get_conf ();
1325
1326         if (TNY_IS_ACCOUNT (folder_store)) {
1327                 if (selected) {
1328                         /* Update active account */
1329                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1330                         /* Show account details */
1331                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1332                 }
1333         } else {
1334                 if (TNY_IS_FOLDER (folder_store) && selected) {
1335                         
1336                         /* Update the active account */
1337                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1338                         if (account) {
1339                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1340                                 g_object_unref (account);
1341                                 account = NULL;
1342                         }
1343
1344                         /* Set the header style by default, it could
1345                            be changed later by the refresh callback to
1346                            empty */
1347                         modest_main_window_set_contents_style (main_window, 
1348                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1349
1350                         /* Set folder on header view. This function
1351                            will call tny_folder_refresh_async so we
1352                            pass a callback that will be called when
1353                            finished. We use that callback to set the
1354                            empty view if there are no messages */
1355                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1356                                                        TNY_FOLDER (folder_store),
1357                                                        folder_refreshed_cb,
1358                                                        main_window);
1359                         
1360                         /* Restore configuration. We need to do this
1361                            *after* the set_folder because the widget
1362                            memory asks the header view about its
1363                            folder  */
1364                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1365                                                       G_OBJECT(header_view),
1366                                                       MODEST_CONF_HEADER_VIEW_KEY);
1367                 } else {
1368                         /* Update the active account */
1369                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1370                         /* Save only if we're seeing headers */
1371                         if (modest_main_window_get_contents_style (main_window) ==
1372                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1373                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1374                                                            MODEST_CONF_HEADER_VIEW_KEY);
1375                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1376                 }
1377         }
1378
1379         /* Update toolbar dimming state */
1380         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1381 }
1382
1383 void 
1384 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1385                                      ModestWindow *win)
1386 {
1387         GtkWidget *dialog;
1388         gchar *txt, *item;
1389         gboolean online;
1390
1391         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1392         
1393         if (g_main_depth > 0)   
1394                 gdk_threads_enter ();
1395         online = tny_device_is_online (modest_runtime_get_device());
1396
1397         if (online) {
1398                 /* already online -- the item is simply not there... */
1399                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1400                                                  GTK_DIALOG_MODAL,
1401                                                  GTK_MESSAGE_WARNING,
1402                                                  GTK_BUTTONS_OK,
1403                                                  _("The %s you selected cannot be found"),
1404                                                  item);
1405                 gtk_dialog_run (GTK_DIALOG(dialog));
1406         } else {
1407                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1408                                                       GTK_WINDOW (win),
1409                                                       GTK_DIALOG_MODAL,
1410                                                       GTK_STOCK_CANCEL,
1411                                                       GTK_RESPONSE_REJECT,
1412                                                       GTK_STOCK_OK,
1413                                                       GTK_RESPONSE_ACCEPT,
1414                                                       NULL);
1415                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1416                                          "Do you want to get online?"), item);
1417                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1418                                     gtk_label_new (txt), FALSE, FALSE, 0);
1419                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1420                 g_free (txt);
1421
1422                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1423                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1424 //                      modest_platform_connect_and_wait ();
1425                 }
1426         }
1427         gtk_widget_destroy (dialog);
1428         if (g_main_depth > 0)   
1429                 gdk_threads_leave ();
1430 }
1431
1432 void
1433 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1434                                      ModestWindow *win)
1435 {
1436         /* g_message ("%s %s", __FUNCTION__, link); */
1437 }       
1438
1439
1440 void
1441 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1442                                         ModestWindow *win)
1443 {
1444         modest_platform_activate_uri (link);
1445 }
1446
1447 void
1448 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1449                                           ModestWindow *win)
1450 {
1451         modest_platform_show_uri_popup (link);
1452 }
1453
1454 void
1455 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1456                                              ModestWindow *win)
1457 {
1458         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1459 }
1460
1461 void
1462 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1463                                           const gchar *address,
1464                                           ModestWindow *win)
1465 {
1466         /* g_message ("%s %s", __FUNCTION__, address); */
1467 }
1468
1469 void
1470 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1471 {
1472         TnyTransportAccount *transport_account;
1473         ModestMailOperation *mail_operation;
1474         MsgData *data;
1475         gchar *account_name, *from;
1476         ModestAccountMgr *account_mgr;
1477
1478         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1479         
1480         data = modest_msg_edit_window_get_msg_data (edit_window);
1481
1482         account_mgr = modest_runtime_get_account_mgr();
1483         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1484         if (!account_name) 
1485                 account_name = modest_account_mgr_get_default_account (account_mgr);
1486         if (!account_name) {
1487                 g_printerr ("modest: no account found\n");
1488                 modest_msg_edit_window_free_msg_data (edit_window, data);
1489                 return;
1490         }
1491
1492         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1493                 account_name = g_strdup (data->account_name);
1494         }
1495
1496         transport_account =
1497                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1498                                       (modest_runtime_get_account_store(),
1499                                        account_name,
1500                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1501         if (!transport_account) {
1502                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1503                 g_free (account_name);
1504                 modest_msg_edit_window_free_msg_data (edit_window, data);
1505                 return;
1506         }
1507         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1508
1509         /* Create the mail operation */         
1510         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1511         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1512
1513         modest_mail_operation_save_to_drafts (mail_operation,
1514                                               transport_account,
1515                                               data->draft_msg,
1516                                               from,
1517                                               data->to, 
1518                                               data->cc, 
1519                                               data->bcc,
1520                                               data->subject, 
1521                                               data->plain_body, 
1522                                               data->html_body,
1523                                               data->attachments,
1524                                               data->priority_flags);
1525         /* Frees */
1526         g_free (from);
1527         g_free (account_name);
1528         g_object_unref (G_OBJECT (transport_account));
1529         g_object_unref (G_OBJECT (mail_operation));
1530
1531         modest_msg_edit_window_free_msg_data (edit_window, data);
1532
1533         /* Save settings and close the window */
1534         gtk_widget_destroy (GTK_WIDGET (edit_window));
1535 }
1536
1537 /* For instance, when clicking the Send toolbar button when editing a message: */
1538 void
1539 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1540 {
1541         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1542
1543         if (!modest_msg_edit_window_check_names (edit_window))
1544                 return;
1545         
1546         /* FIXME: Code added just for testing. The final version will
1547            use the send queue provided by tinymail and some
1548            classifier */
1549         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1550         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1551         if (!account_name) 
1552                 account_name = modest_account_mgr_get_default_account (account_mgr);
1553                 
1554         if (!account_name) {
1555                 g_printerr ("modest: no account found\n");
1556                 return;
1557         }
1558         
1559         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1560
1561         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1562                 account_name = g_strdup (data->account_name);
1563         }
1564         
1565         /* Get the currently-active transport account for this modest account: */
1566         TnyTransportAccount *transport_account =
1567                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1568                                       (modest_runtime_get_account_store(),
1569                                        account_name));
1570         if (!transport_account) {
1571                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1572                 g_free (account_name);
1573                 modest_msg_edit_window_free_msg_data (edit_window, data);
1574                 return;
1575         }
1576         
1577         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1578
1579         /* mail content checks and dialogs */
1580         if (data->subject == NULL || data->subject[0] == '\0') {
1581                 GtkResponseType response;
1582                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1583                                                                     _("mcen_nc_subject_is_empty_send"));
1584                 if (response == GTK_RESPONSE_CANCEL) {
1585                         g_free (account_name);
1586                         return;
1587                 }
1588         }
1589
1590         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1591                 GtkResponseType response;
1592                 gchar *note_message;
1593                 gchar *note_subject = data->subject;
1594                 if (note_subject == NULL || note_subject[0] == '\0')
1595                         note_subject = _("mail_va_no_subject");
1596                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1597                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1598                                                                     note_message);
1599                 g_free (note_message);
1600                 if (response == GTK_RESPONSE_CANCEL) {
1601                         g_free (account_name);
1602                         return;
1603                 }
1604         }
1605
1606         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
1607
1608         /* Create the mail operation */
1609         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1610         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1611
1612         modest_mail_operation_send_new_mail (mail_operation,
1613                                              transport_account,
1614                                              data->draft_msg,
1615                                              from,
1616                                              data->to, 
1617                                              data->cc, 
1618                                              data->bcc,
1619                                              data->subject, 
1620                                              data->plain_body, 
1621                                              data->html_body,
1622                                              data->attachments,
1623                                              data->priority_flags);
1624                                              
1625         /* Free data: */
1626         g_free (from);
1627         g_free (account_name);
1628         g_object_unref (G_OBJECT (transport_account));
1629         g_object_unref (G_OBJECT (mail_operation));
1630
1631         modest_msg_edit_window_free_msg_data (edit_window, data);
1632
1633         /* Save settings and close the window: */
1634         gtk_widget_destroy (GTK_WIDGET (edit_window));
1635 }
1636
1637 void 
1638 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1639                                   ModestMsgEditWindow *window)
1640 {
1641         ModestMsgEditFormatState *format_state = NULL;
1642
1643         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1644         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1645
1646         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1647                 return;
1648
1649         format_state = modest_msg_edit_window_get_format_state (window);
1650         g_return_if_fail (format_state != NULL);
1651
1652         format_state->bold = gtk_toggle_action_get_active (action);
1653         modest_msg_edit_window_set_format_state (window, format_state);
1654         g_free (format_state);
1655         
1656 }
1657
1658 void 
1659 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1660                                      ModestMsgEditWindow *window)
1661 {
1662         ModestMsgEditFormatState *format_state = NULL;
1663
1664         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1665         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1666
1667         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1668                 return;
1669
1670         format_state = modest_msg_edit_window_get_format_state (window);
1671         g_return_if_fail (format_state != NULL);
1672
1673         format_state->italics = gtk_toggle_action_get_active (action);
1674         modest_msg_edit_window_set_format_state (window, format_state);
1675         g_free (format_state);
1676         
1677 }
1678
1679 void 
1680 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1681                                      ModestMsgEditWindow *window)
1682 {
1683         ModestMsgEditFormatState *format_state = NULL;
1684
1685         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1686         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1687
1688         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1689                 return;
1690
1691         format_state = modest_msg_edit_window_get_format_state (window);
1692         g_return_if_fail (format_state != NULL);
1693
1694         format_state->bullet = gtk_toggle_action_get_active (action);
1695         modest_msg_edit_window_set_format_state (window, format_state);
1696         g_free (format_state);
1697         
1698 }
1699
1700 void 
1701 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1702                                      GtkRadioAction *selected,
1703                                      ModestMsgEditWindow *window)
1704 {
1705         ModestMsgEditFormatState *format_state = NULL;
1706         GtkJustification value;
1707
1708         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1709
1710         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1711                 return;
1712
1713         value = gtk_radio_action_get_current_value (selected);
1714
1715         format_state = modest_msg_edit_window_get_format_state (window);
1716         g_return_if_fail (format_state != NULL);
1717
1718         format_state->justification = value;
1719         modest_msg_edit_window_set_format_state (window, format_state);
1720         g_free (format_state);
1721 }
1722
1723 void 
1724 modest_ui_actions_on_select_editor_color (GtkAction *action,
1725                                           ModestMsgEditWindow *window)
1726 {
1727         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1728         g_return_if_fail (GTK_IS_ACTION (action));
1729
1730         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1731                 return;
1732
1733         modest_msg_edit_window_select_color (window);
1734 }
1735
1736 void 
1737 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1738                                                      ModestMsgEditWindow *window)
1739 {
1740         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1741         g_return_if_fail (GTK_IS_ACTION (action));
1742
1743         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1744                 return;
1745
1746         modest_msg_edit_window_select_background_color (window);
1747 }
1748
1749 void 
1750 modest_ui_actions_on_insert_image (GtkAction *action,
1751                                    ModestMsgEditWindow *window)
1752 {
1753         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1754         g_return_if_fail (GTK_IS_ACTION (action));
1755
1756         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1757                 return;
1758
1759         modest_msg_edit_window_insert_image (window);
1760 }
1761
1762 void 
1763 modest_ui_actions_on_attach_file (GtkAction *action,
1764                                   ModestMsgEditWindow *window)
1765 {
1766         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1767         g_return_if_fail (GTK_IS_ACTION (action));
1768
1769         modest_msg_edit_window_attach_file (window);
1770 }
1771
1772 void 
1773 modest_ui_actions_on_remove_attachments (GtkAction *action,
1774                                          ModestMsgEditWindow *window)
1775 {
1776         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1777         g_return_if_fail (GTK_IS_ACTION (action));
1778
1779         modest_msg_edit_window_remove_attachments (window, NULL);
1780 }
1781
1782 /*
1783  * Shows a dialog with an entry that asks for some text. The returned
1784  * value must be freed by the caller. The dialog window title will be
1785  * set to @title.
1786  */
1787 static gchar *
1788 ask_for_folder_name (GtkWindow *parent_window,
1789                      const gchar *title)
1790 {
1791         GtkWidget *dialog, *entry;
1792         gchar *folder_name = NULL;
1793
1794         /* Ask for folder name */
1795         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1796                                               parent_window,
1797                                               GTK_DIALOG_MODAL,
1798                                               GTK_STOCK_CANCEL,
1799                                               GTK_RESPONSE_REJECT,
1800                                               GTK_STOCK_OK,
1801                                               GTK_RESPONSE_ACCEPT,
1802                                               NULL);
1803         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1804                             gtk_label_new(title),
1805                             FALSE, FALSE, 0);
1806                 
1807         entry = gtk_entry_new_with_max_length (40);
1808         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1809                             entry,
1810                             TRUE, FALSE, 0);    
1811         
1812         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1813         
1814         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1815                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1816
1817         gtk_widget_destroy (dialog);
1818
1819         return folder_name;
1820 }
1821
1822 void 
1823 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1824 {
1825         TnyFolderStore *parent_folder;
1826         GtkWidget *folder_view;
1827         
1828         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1829
1830         folder_view = modest_main_window_get_child_widget (main_window,
1831                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1832         if (!folder_view)
1833                 return;
1834
1835         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1836         
1837         if (parent_folder) {
1838                 gboolean finished = FALSE;
1839                 gint result;
1840                 gchar *folder_name = NULL, *suggested_name = NULL;
1841
1842                 /* Run the new folder dialog */
1843                 while (!finished) {
1844                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1845                                                                         parent_folder,
1846                                                                         suggested_name,
1847                                                                         &folder_name);
1848
1849                         if (result == GTK_RESPONSE_REJECT) {
1850                                 finished = TRUE;
1851                         } else {
1852                                 ModestMailOperation *mail_op;
1853                                 TnyFolder *new_folder = NULL;
1854
1855                                 mail_op  = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, 
1856                                                                       G_OBJECT(main_window));
1857                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1858                                                                  mail_op);
1859                                 new_folder = modest_mail_operation_create_folder (mail_op,
1860                                                                                   parent_folder,
1861                                                                                   (const gchar *) folder_name);
1862                                 if (new_folder) {
1863                                         g_object_unref (new_folder);
1864                                         finished = TRUE;
1865                                 }
1866                                 g_object_unref (mail_op);
1867                         }
1868                         g_free (folder_name);
1869                         folder_name = NULL;
1870                 }
1871
1872                 g_object_unref (parent_folder);
1873         }
1874 }
1875
1876 void 
1877 modest_ui_actions_on_rename_folder (GtkAction *action,
1878                                      ModestMainWindow *main_window)
1879 {
1880         TnyFolderStore *folder;
1881         GtkWidget *folder_view;
1882         GtkWidget *header_view; 
1883
1884         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1885
1886         folder_view = modest_main_window_get_child_widget (main_window,
1887                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1888         if (!folder_view)
1889                 return;
1890
1891         header_view = modest_main_window_get_child_widget (main_window,
1892                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1893         
1894         if (!header_view)
1895                 return;
1896
1897         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1898         
1899         if (folder && TNY_IS_FOLDER (folder)) {
1900                 gchar *folder_name;
1901                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1902                                                    _("Please enter a new name for the folder"));
1903
1904                 if (folder_name != NULL && strlen (folder_name) > 0) {
1905                         ModestMailOperation *mail_op;
1906
1907                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(main_window));
1908                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1909                                                          mail_op);
1910
1911                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
1912
1913                         modest_mail_operation_rename_folder (mail_op,
1914                                                              TNY_FOLDER (folder),
1915                                                              (const gchar *) folder_name);
1916
1917                         g_object_unref (mail_op);
1918                         g_free (folder_name);
1919                 }
1920                 g_object_unref (folder);
1921         }
1922 }
1923
1924 static void
1925 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
1926                                                gpointer user_data)
1927 {
1928         GObject *win = modest_mail_operation_get_source (mail_op);
1929
1930         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1931                                                 _("mail_in_ui_folder_delete_error"));
1932         g_object_unref (win);
1933 }
1934
1935 static void
1936 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1937 {
1938         TnyFolderStore *folder;
1939         GtkWidget *folder_view;
1940         gint response;
1941         gchar *message;
1942         
1943         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1944
1945         folder_view = modest_main_window_get_child_widget (main_window,
1946                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1947         if (!folder_view)
1948                 return;
1949
1950         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1951
1952         /* Show an error if it's an account */
1953         if (!TNY_IS_FOLDER (folder)) {
1954                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1955                                                         _("mail_in_ui_folder_delete_error"));
1956                 return ;
1957         }
1958
1959         /* Ask the user */      
1960         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1961                                     tny_folder_get_name (TNY_FOLDER (folder)));
1962         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1963                                                             (const gchar *) message);
1964         g_free (message);
1965
1966         if (response == GTK_RESPONSE_OK) {
1967                 ModestMailOperation *mail_op = 
1968                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
1969                                                                        G_OBJECT(main_window),
1970                                                                        modest_ui_actions_delete_folder_error_handler,
1971                                                                        NULL);
1972
1973                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1974                                                  mail_op);
1975                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1976                 g_object_unref (G_OBJECT (mail_op));
1977         }
1978
1979         g_object_unref (G_OBJECT (folder));
1980 }
1981
1982 void 
1983 modest_ui_actions_on_delete_folder (GtkAction *action,
1984                                      ModestMainWindow *main_window)
1985 {
1986         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1987
1988         delete_folder (main_window, FALSE);
1989 }
1990
1991 void 
1992 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1993 {
1994         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1995         
1996         delete_folder (main_window, TRUE);
1997 }
1998
1999 void
2000 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2001                                          const gchar* server_account_name,
2002                                          gchar **username,
2003                                          gchar **password, 
2004                                          gboolean *cancel, 
2005                                          gboolean *remember,
2006                                          ModestMainWindow *main_window)
2007 {
2008         g_return_if_fail(server_account_name);
2009         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2010         
2011         /* Initalize output parameters: */
2012         if (cancel)
2013                 *cancel = FALSE;
2014                 
2015         if (remember)
2016                 *remember = TRUE;
2017                 
2018 #ifdef MODEST_PLATFORM_MAEMO
2019         /* Maemo uses a different (awkward) button order,
2020          * It should probably just use gtk_alternative_dialog_button_order ().
2021          */
2022         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2023                                               NULL,
2024                                               GTK_DIALOG_MODAL,
2025                                               GTK_STOCK_OK,
2026                                               GTK_RESPONSE_ACCEPT,
2027                                               GTK_STOCK_CANCEL,
2028                                               GTK_RESPONSE_REJECT,
2029                                               NULL);
2030 #else
2031         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2032                                               NULL,
2033                                               GTK_DIALOG_MODAL,
2034                                               GTK_STOCK_CANCEL,
2035                                               GTK_RESPONSE_REJECT,
2036                                               GTK_STOCK_OK,
2037                                               GTK_RESPONSE_ACCEPT,
2038                                               NULL);
2039 #endif /* MODEST_PLATFORM_MAEMO */
2040
2041         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2042         
2043         gchar *server_name = modest_server_account_get_hostname (
2044                 modest_runtime_get_account_mgr(), server_account_name);
2045         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2046                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2047                 *cancel = TRUE;
2048                 return;
2049         }
2050         
2051         /* This causes a warning because the logical ID has no %s in it, 
2052          * though the translation does, but there is not much we can do about that: */
2053         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2054         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2055                             FALSE, FALSE, 0);
2056         g_free (txt);
2057         g_free (server_name);
2058         server_name = NULL;
2059
2060         /* username: */
2061         gchar *initial_username = modest_server_account_get_username (
2062                 modest_runtime_get_account_mgr(), server_account_name);
2063         
2064         GtkWidget *entry_username = gtk_entry_new ();
2065         if (initial_username)
2066                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2067         /* Dim this if a connection has ever succeeded with this username,
2068          * as per the UI spec: */
2069         const gboolean username_known = 
2070                 modest_server_account_get_username_has_succeeded(
2071                         modest_runtime_get_account_mgr(), server_account_name);
2072         gtk_widget_set_sensitive (entry_username, !username_known);
2073         
2074 #ifdef MODEST_PLATFORM_MAEMO
2075         /* Auto-capitalization is the default, so let's turn it off: */
2076         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2077         
2078         /* Create a size group to be used by all captions.
2079          * Note that HildonCaption does not create a default size group if we do not specify one.
2080          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2081         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2082         
2083         GtkWidget *caption = hildon_caption_new (sizegroup, 
2084                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2085         gtk_widget_show (entry_username);
2086         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2087                 FALSE, FALSE, MODEST_MARGIN_HALF);
2088         gtk_widget_show (caption);
2089 #else 
2090         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2091                             TRUE, FALSE, 0);
2092 #endif /* MODEST_PLATFORM_MAEMO */      
2093                             
2094         /* password: */
2095         GtkWidget *entry_password = gtk_entry_new ();
2096         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2097         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2098         
2099 #ifdef MODEST_PLATFORM_MAEMO
2100         /* Auto-capitalization is the default, so let's turn it off: */
2101         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2102                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2103         
2104         caption = hildon_caption_new (sizegroup, 
2105                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2106         gtk_widget_show (entry_password);
2107         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2108                 FALSE, FALSE, MODEST_MARGIN_HALF);
2109         gtk_widget_show (caption);
2110         g_object_unref (sizegroup);
2111 #else 
2112         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2113                             TRUE, FALSE, 0);
2114 #endif /* MODEST_PLATFORM_MAEMO */      
2115                                 
2116 /* This is not in the Maemo UI spec:
2117         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2118         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2119                             TRUE, FALSE, 0);
2120 */
2121
2122         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2123         
2124         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2125                 if (username) {
2126                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2127                         
2128                         modest_server_account_set_username (
2129                                  modest_runtime_get_account_mgr(), server_account_name, 
2130                                  *username);
2131                                  
2132                         const gboolean username_was_changed = 
2133                                 (strcmp (*username, initial_username) != 0);
2134                         if (username_was_changed) {
2135                                 /* To actually use a changed username, 
2136                                  * we must reset the connection, according to pvanhoof.
2137                                  * This _might_ be a sensible way to do that: */
2138                                  TnyDevice *device = modest_runtime_get_device();
2139                                  tny_device_force_offline (device);
2140                                  tny_device_force_online (device);
2141                         }
2142                 }
2143                         
2144                 if (password) {
2145                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2146                         
2147                         /* We do not save the password in the configuration, 
2148                          * because this function is only called for passwords that should 
2149                          * not be remembered:
2150                         modest_server_account_set_password (
2151                                  modest_runtime_get_account_mgr(), server_account_name, 
2152                                  *password);
2153                         */
2154                 }
2155                 
2156                 if (cancel)
2157                         *cancel   = FALSE;
2158                         
2159         } else {
2160                 if (username)
2161                         *username = NULL;
2162                         
2163                 if (password)
2164                         *password = NULL;
2165                         
2166                 if (cancel)
2167                         *cancel   = TRUE;
2168         }
2169
2170 /* This is not in the Maemo UI spec:
2171         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2172                 *remember = TRUE;
2173         else
2174                 *remember = FALSE;
2175 */
2176
2177         gtk_widget_destroy (dialog);
2178         
2179         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2180 }
2181
2182 void
2183 modest_ui_actions_on_cut (GtkAction *action,
2184                           ModestWindow *window)
2185 {
2186         GtkWidget *focused_widget;
2187
2188         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2189         if (GTK_IS_EDITABLE (focused_widget)) {
2190                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2191         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2192                 GtkTextBuffer *buffer;
2193                 GtkClipboard *clipboard;
2194
2195                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2196                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2197                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2198         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2199                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2200         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2201                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2202         }
2203 }
2204
2205 void
2206 modest_ui_actions_on_copy (GtkAction *action,
2207                            ModestWindow *window)
2208 {
2209         GtkClipboard *clipboard;
2210         GtkWidget *focused_widget;
2211
2212         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2213         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2214
2215         if (GTK_IS_LABEL (focused_widget)) {
2216                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2217         } else if (GTK_IS_EDITABLE (focused_widget)) {
2218                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2219         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2220                 GtkTextBuffer *buffer;
2221                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2222                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2223                 modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2224         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2225                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2226                 TnyIterator *iter = tny_list_create_iterator (header_list);
2227                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2228                 TnyFolder *folder = tny_header_get_folder (header);
2229                 TnyAccount *account = tny_folder_get_account (folder);
2230                 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2231                 /* If it's POP then ask */
2232                 gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2233                        MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2234                 g_object_unref (account);
2235                 g_object_unref (folder);
2236                 g_object_unref (header);
2237                 g_object_unref (iter);
2238                 
2239                 /* Check that the messages have been previously downloaded */
2240                 gboolean continue_download = TRUE;
2241                 if (ask)
2242                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
2243                 if (continue_download)
2244                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2245                 g_object_unref (header_list);
2246         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2247                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2248         }    
2249 }
2250
2251 void
2252 modest_ui_actions_on_undo (GtkAction *action,
2253                            ModestWindow *window)
2254 {
2255         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2256                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2257         } else {
2258                 g_return_if_reached ();
2259         }
2260 }
2261
2262 void
2263 modest_ui_actions_on_paste (GtkAction *action,
2264                             ModestWindow *window)
2265 {
2266         GtkWidget *focused_widget;
2267         ModestMailOperation *mail_op = NULL;
2268
2269         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2270         if (GTK_IS_EDITABLE (focused_widget)) {
2271                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2272         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2273                 GtkTextBuffer *buffer;
2274                 GtkClipboard *clipboard;
2275
2276                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2277                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2278                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2279         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2280                 ModestEmailClipboard *clipboard = NULL;
2281                 TnyFolder *src_folder = NULL;
2282                 TnyFolderStore *folder_store = NULL;
2283                 TnyList *data = NULL;           
2284                 gboolean delete = FALSE;
2285                 
2286                 /* Check clipboard source */
2287                 clipboard = modest_runtime_get_email_clipboard ();
2288                 if (modest_email_clipboard_cleared (clipboard)) 
2289                         return;
2290                 
2291                 /* Get elements to paste */
2292                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2293
2294                 /* Create a new mail operation */
2295                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2296                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2297                                                  mail_op);
2298                 
2299                 /* Get destination folder */
2300                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2301
2302                 /* transfer messages  */
2303                 if (data != NULL) {
2304                         modest_mail_operation_xfer_msgs (mail_op, 
2305                                                          data,
2306                                                          TNY_FOLDER (folder_store),
2307                                                          delete,
2308                                                          NULL,
2309                                                          NULL);
2310                         
2311                 } else if (src_folder != NULL) {                        
2312                         modest_mail_operation_xfer_folder (mail_op, 
2313                                                            src_folder,
2314                                                            folder_store,
2315                                                            delete);
2316                 }
2317
2318                 /* Free */
2319                 if (data != NULL) 
2320                         g_object_unref (data);
2321                 if (src_folder != NULL) 
2322                         g_object_unref (src_folder);
2323                 if (folder_store != NULL) 
2324                         g_object_unref (folder_store);
2325         }
2326 }
2327
2328 void
2329 modest_ui_actions_on_select_all (GtkAction *action,
2330                                  ModestWindow *window)
2331 {
2332         GtkWidget *focused_widget;
2333
2334         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2335         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2336                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2337         } else if (GTK_IS_LABEL (focused_widget)) {
2338                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2339         } else if (GTK_IS_EDITABLE (focused_widget)) {
2340                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2341         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2342                 GtkTextBuffer *buffer;
2343                 GtkTextIter start, end;
2344
2345                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2346                 gtk_text_buffer_get_start_iter (buffer, &start);
2347                 gtk_text_buffer_get_end_iter (buffer, &end);
2348                 gtk_text_buffer_select_range (buffer, &start, &end);
2349         }
2350         else if ((MODEST_IS_FOLDER_VIEW (focused_widget)) ||
2351                  (MODEST_IS_HEADER_VIEW (focused_widget))) {
2352                 
2353                 GtkTreeSelection *selection = NULL;
2354
2355                 /* Get header view */           
2356                 GtkWidget *header_view = focused_widget;
2357                 if (MODEST_IS_FOLDER_VIEW (focused_widget))
2358                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2359                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2360
2361                 /* Select all messages */
2362                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2363                 gtk_tree_selection_select_all (selection);
2364
2365                 /* Set focuse on header view */
2366                 gtk_widget_grab_focus (header_view);
2367
2368         } else if (GTK_IS_HTML (focused_widget)) {
2369                 gtk_html_select_all (GTK_HTML (focused_widget));
2370         }
2371 }
2372
2373 void
2374 modest_ui_actions_on_mark_as_read (GtkAction *action,
2375                                    ModestWindow *window)
2376 {       
2377         g_return_if_fail (MODEST_IS_WINDOW(window));
2378                 
2379         /* Mark each header as read */
2380         do_headers_action (window, headers_action_mark_as_read, NULL);
2381 }
2382
2383 void
2384 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2385                                      ModestWindow *window)
2386 {       
2387         g_return_if_fail (MODEST_IS_WINDOW(window));
2388                 
2389         /* Mark each header as read */
2390         do_headers_action (window, headers_action_mark_as_unread, NULL);
2391 }
2392
2393 void
2394 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2395                                   GtkRadioAction *selected,
2396                                   ModestWindow *window)
2397 {
2398         gint value;
2399
2400         value = gtk_radio_action_get_current_value (selected);
2401         if (MODEST_IS_WINDOW (window)) {
2402                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2403         }
2404 }
2405
2406 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2407                                                         GtkRadioAction *selected,
2408                                                         ModestWindow *window)
2409 {
2410         TnyHeaderFlags flags;
2411         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2412
2413         flags = gtk_radio_action_get_current_value (selected);
2414         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2415 }
2416
2417 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2418                                                            GtkRadioAction *selected,
2419                                                            ModestWindow *window)
2420 {
2421         gint file_format;
2422
2423         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2424
2425         file_format = gtk_radio_action_get_current_value (selected);
2426         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2427 }
2428
2429
2430 void     
2431 modest_ui_actions_on_zoom_plus (GtkAction *action,
2432                                 ModestWindow *window)
2433 {
2434         g_return_if_fail (MODEST_IS_WINDOW (window));
2435
2436         modest_window_zoom_plus (MODEST_WINDOW (window));
2437 }
2438
2439 void     
2440 modest_ui_actions_on_zoom_minus (GtkAction *action,
2441                                  ModestWindow *window)
2442 {
2443         g_return_if_fail (MODEST_IS_WINDOW (window));
2444
2445         modest_window_zoom_minus (MODEST_WINDOW (window));
2446 }
2447
2448 void     
2449 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2450                                            ModestWindow *window)
2451 {
2452         ModestWindowMgr *mgr;
2453         gboolean fullscreen, active;
2454         g_return_if_fail (MODEST_IS_WINDOW (window));
2455
2456         mgr = modest_runtime_get_window_mgr ();
2457
2458         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2459         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2460
2461         if (active != fullscreen) {
2462                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2463                 gtk_window_present (GTK_WINDOW (window));
2464         }
2465 }
2466
2467 void
2468 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2469                                         ModestWindow *window)
2470 {
2471         ModestWindowMgr *mgr;
2472         gboolean fullscreen;
2473
2474         g_return_if_fail (MODEST_IS_WINDOW (window));
2475
2476         mgr = modest_runtime_get_window_mgr ();
2477         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2478         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2479
2480         gtk_window_present (GTK_WINDOW (window));
2481 }
2482
2483 /* 
2484  * Used by modest_ui_actions_on_details to call do_headers_action 
2485  */
2486 static void
2487 headers_action_show_details (TnyHeader *header, 
2488                              ModestWindow *window,
2489                              gpointer user_data)
2490
2491 {
2492         GtkWidget *dialog;
2493         
2494         /* Create dialog */
2495         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2496
2497         /* Run dialog */
2498         gtk_widget_show_all (dialog);
2499         gtk_dialog_run (GTK_DIALOG (dialog));
2500
2501         gtk_widget_destroy (dialog);
2502 }
2503
2504 /*
2505  * Show the folder details in a ModestDetailsDialog widget
2506  */
2507 static void
2508 show_folder_details (TnyFolder *folder, 
2509                      GtkWindow *window)
2510 {
2511         GtkWidget *dialog;
2512         
2513         /* Create dialog */
2514         dialog = modest_details_dialog_new_with_folder (window, folder);
2515
2516         /* Run dialog */
2517         gtk_widget_show_all (dialog);
2518         gtk_dialog_run (GTK_DIALOG (dialog));
2519
2520         gtk_widget_destroy (dialog);
2521 }
2522
2523 /*
2524  * Show the header details in a ModestDetailsDialog widget
2525  */
2526 void     
2527 modest_ui_actions_on_details (GtkAction *action, 
2528                               ModestWindow *win)
2529 {
2530         TnyList * headers_list;
2531         TnyIterator *iter;
2532         TnyHeader *header;              
2533
2534         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2535                 TnyMsg *msg;
2536
2537                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2538                 if (!msg)
2539                         return;
2540                 g_object_unref (msg);           
2541
2542                 headers_list = get_selected_headers (win);
2543                 if (!headers_list)
2544                         return;
2545
2546                 iter = tny_list_create_iterator (headers_list);
2547
2548                 header = TNY_HEADER (tny_iterator_get_current (iter));
2549                 headers_action_show_details (header, win, NULL);
2550                 g_object_unref (header);
2551
2552                 g_object_unref (iter);
2553                 g_object_unref (headers_list);
2554
2555         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2556                 GtkWidget *folder_view, *header_view;
2557
2558                 /* Check which widget has the focus */
2559                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2560                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2561                 if (gtk_widget_is_focus (folder_view)) {
2562                         TnyFolderStore *folder_store
2563                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2564                         if (!folder_store) {
2565                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
2566                                 return; 
2567                         }
2568                         /* Show only when it's a folder */
2569                         /* This function should not be called for account items, 
2570                          * because we dim the menu item for them. */
2571                         if (TNY_IS_FOLDER (folder_store)) {
2572                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
2573                         }
2574
2575                         g_object_unref (folder_store);
2576
2577                 } else {
2578                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2579                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2580                         /* Show details of each header */
2581                         do_headers_action (win, headers_action_show_details, header_view);
2582                 }
2583         }
2584 }
2585
2586 void     
2587 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2588                                      ModestMsgEditWindow *window)
2589 {
2590         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2591
2592         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2593 }
2594
2595 void     
2596 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2597                                       ModestMsgEditWindow *window)
2598 {
2599         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2600
2601         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2602 }
2603
2604 void
2605 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2606                                        ModestMainWindow *main_window)
2607 {
2608         ModestConf *conf;
2609         
2610         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2611
2612         conf = modest_runtime_get_conf ();
2613         
2614         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2615                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2616         else
2617                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2618 }
2619
2620 void 
2621 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2622                                      ModestWindow *window)
2623 {
2624         gboolean active, fullscreen = FALSE;
2625         ModestWindowMgr *mgr;
2626
2627         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2628
2629         /* Check if we want to toggle the toolbar vuew in fullscreen
2630            or normal mode */
2631         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2632                      "ViewShowToolbarFullScreen")) {
2633                 fullscreen = TRUE;
2634         }
2635
2636         /* Toggle toolbar */
2637         mgr = modest_runtime_get_window_mgr ();
2638         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2639 }
2640
2641 void     
2642 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2643                                            ModestMsgEditWindow *window)
2644 {
2645         modest_msg_edit_window_select_font (window);
2646 }
2647
2648 void
2649 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2650                                                   const gchar *display_name,
2651                                                   GtkWindow *window)
2652 {
2653         /* Do not change the application name if the widget has not
2654            the focus. This callback could be called even if the folder
2655            view has not the focus, because the handled signal could be
2656            emitted when the folder view is redrawn */
2657         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2658                 if (display_name)
2659                         gtk_window_set_title (window, display_name);
2660                 else
2661                         gtk_window_set_title (window, " ");
2662         }
2663 }
2664
2665 void
2666 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2667 {
2668         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2669         modest_msg_edit_window_select_contacts (window);
2670 }
2671
2672 void
2673 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2674 {
2675         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2676         modest_msg_edit_window_check_names (window);
2677 }
2678
2679
2680 static GtkWidget*
2681 create_move_to_dialog (ModestWindow *win,
2682                        GtkWidget *folder_view,
2683                        GtkWidget **tree_view)
2684 {
2685         GtkWidget *dialog, *scroll;
2686
2687         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2688                                               GTK_WINDOW (win),
2689                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2690                                               GTK_STOCK_OK,
2691                                               GTK_RESPONSE_ACCEPT,
2692                                               GTK_STOCK_CANCEL,
2693                                               GTK_RESPONSE_REJECT,
2694                                               NULL);
2695
2696         /* Create scrolled window */
2697         scroll = gtk_scrolled_window_new (NULL, NULL);
2698         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2699                                          GTK_POLICY_AUTOMATIC,
2700                                          GTK_POLICY_AUTOMATIC);
2701
2702         /* Create folder view */
2703         *tree_view = modest_platform_create_folder_view (NULL);
2704
2705         /* It could happen that we're trying to move a message from a
2706            window (msg window for example) after the main window was
2707            closed, so we can not just get the model of the folder
2708            view */
2709         if (MODEST_IS_FOLDER_VIEW (folder_view))
2710                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2711                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2712         else
2713                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
2714                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
2715
2716         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2717
2718         /* Add scroll to dialog */
2719         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2720                             scroll, FALSE, FALSE, 0);
2721
2722         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2723
2724         /* Select INBOX or local account */
2725         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (*tree_view));
2726
2727         return dialog;
2728 }
2729
2730 /*
2731  * Returns TRUE if at least one of the headers of the list belongs to
2732  * a message that has been fully retrieved.
2733  */
2734 static gboolean
2735 has_retrieved_msgs (TnyList *list)
2736 {
2737         TnyIterator *iter;
2738         gboolean found = FALSE;
2739
2740         iter = tny_list_create_iterator (list);
2741         while (tny_iterator_is_done (iter) && !found) {
2742                 TnyHeader *header;
2743                 TnyHeaderFlags flags;
2744
2745                 header = TNY_HEADER (tny_iterator_get_current (iter));
2746                 flags = tny_header_get_flags (header);
2747                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2748                         found = TRUE;
2749
2750                 if (!found)
2751                         tny_iterator_next (iter);
2752         }
2753         g_object_unref (iter);
2754
2755         return found;
2756 }
2757
2758 /*
2759  * Shows a confirmation dialog to the user when we're moving messages
2760  * from a remote server to the local storage. Returns the dialog
2761  * response. If it's other kind of movement the it always returns
2762  * GTK_RESPONSE_OK
2763  */
2764 static gint
2765 msgs_move_to_confirmation (GtkWindow *win,
2766                            TnyFolder *dest_folder,
2767                            TnyList *headers)
2768 {
2769         gint response = GTK_RESPONSE_OK;
2770
2771         /* If the destination is a local folder */
2772         if (modest_tny_folder_is_local_folder (dest_folder)) {
2773                 TnyFolder *src_folder;
2774                 TnyIterator *iter;
2775                 TnyHeader *header;
2776
2777                 /* Get source folder */
2778                 iter = tny_list_create_iterator (headers);
2779                 header = TNY_HEADER (tny_iterator_get_current (iter));
2780                 src_folder = tny_header_get_folder (header);
2781                 g_object_unref (header);
2782                 g_object_unref (iter);
2783
2784                 /* If the source is a remote folder */
2785                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2786                         const gchar *message;
2787                         
2788                         if (has_retrieved_msgs (headers))
2789                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
2790                                                     tny_list_get_length (headers));
2791                         else 
2792                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
2793                                                     tny_list_get_length (headers));
2794
2795                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2796                                                                             (const gchar *) message);
2797                 }
2798                 g_object_unref (src_folder);
2799         }
2800         return response;
2801 }
2802
2803
2804 static void
2805 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2806 {
2807         ModestMsgViewWindow *self = NULL;
2808
2809         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2810         self = MODEST_MSG_VIEW_WINDOW (object);
2811
2812         /* If there are not more messages don't do anything. The
2813            viewer will show the same message */
2814         if (!modest_msg_view_window_select_first_message (self))
2815             return;
2816 }
2817
2818 void
2819 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
2820                                              gpointer user_data)
2821 {
2822         GObject *win = modest_mail_operation_get_source (mail_op);
2823
2824         /* TODO: show error message */
2825         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2826                                                 _("mail_in_ui_folder_move_target_error"));
2827         g_object_unref (win);
2828 }
2829
2830 /*
2831  * UI handler for the "Move to" action when invoked from the
2832  * ModestMainWindow
2833  */
2834 static void 
2835 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2836                                           ModestMainWindow *win)
2837 {
2838         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2839         GtkWidget *header_view = NULL;
2840         gint result;
2841         TnyFolderStore *folder_store = NULL;
2842         ModestMailOperation *mail_op = NULL;
2843
2844         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2845
2846         /* Get the folder view */
2847         folder_view = modest_main_window_get_child_widget (win,
2848                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2849
2850         /* Get header view */
2851         header_view = modest_main_window_get_child_widget (win,
2852                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2853
2854         /* Create and run the dialog */
2855         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2856         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
2857         result = gtk_dialog_run (GTK_DIALOG(dialog));
2858         g_object_ref (tree_view);
2859
2860         /* We do this to save an indentation level ;-) */
2861         if (result != GTK_RESPONSE_ACCEPT)
2862                 goto end;
2863
2864         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2865
2866         if (TNY_IS_ACCOUNT (folder_store))
2867                 goto end;
2868
2869         /* Get folder or messages to transfer */
2870         if (gtk_widget_is_focus (folder_view)) {
2871                 TnyFolderStore *src_folder;
2872                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2873
2874                 /* Clean folder on header view before moving it */
2875                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
2876
2877                 if (TNY_IS_FOLDER (src_folder)) {
2878                         mail_op = 
2879                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2880                                                                                G_OBJECT(win),
2881                                                                                modest_ui_actions_move_folder_error_handler,
2882                                                                                NULL);
2883                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2884
2885                         modest_mail_operation_xfer_folder (mail_op, 
2886                                                            TNY_FOLDER (src_folder),
2887                                                            folder_store,
2888                                                            TRUE);
2889                         /* Unref mail operation */
2890                         g_object_unref (G_OBJECT (mail_op));
2891                 }
2892
2893                 /* Frees */
2894                 g_object_unref (G_OBJECT (src_folder));
2895         } else {
2896                 if (gtk_widget_is_focus (header_view)) {
2897                         TnyList *headers;
2898                         gint response;
2899
2900                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2901
2902                         /* Ask for user confirmation */
2903                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2904                                                               TNY_FOLDER (folder_store), 
2905                                                               headers);
2906
2907                         /* Transfer messages */
2908                         if (response == GTK_RESPONSE_OK) {
2909                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2910                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2911                                                                  mail_op);
2912
2913                                 modest_mail_operation_xfer_msgs (mail_op, 
2914                                                                  headers,
2915                                                                  TNY_FOLDER (folder_store),
2916                                                                  TRUE,
2917                                                                  NULL,
2918                                                                  NULL);
2919
2920                                 g_object_unref (G_OBJECT (mail_op));
2921                         }
2922                         g_object_unref (headers);
2923                 }
2924         }
2925         g_object_unref (folder_store);
2926  end:
2927         gtk_widget_destroy (dialog);
2928 }
2929
2930
2931 /*
2932  * UI handler for the "Move to" action when invoked from the
2933  * ModestMsgViewWindow
2934  */
2935 static void 
2936 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2937                                               ModestMsgViewWindow *win)
2938 {
2939         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2940         gint result;
2941         ModestMainWindow *main_window;
2942         TnyHeader *header;
2943         TnyList *headers;
2944
2945         /* Get the folder view */
2946         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2947         if (main_window)
2948                 folder_view = modest_main_window_get_child_widget (main_window,
2949                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
2950         else
2951                 folder_view = NULL;
2952
2953         /* Create and run the dialog */
2954         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2955         result = gtk_dialog_run (GTK_DIALOG(dialog));
2956         g_object_ref (tree_view);
2957
2958         if (result == GTK_RESPONSE_ACCEPT) {
2959                 TnyFolderStore *folder_store;
2960                 gint response;
2961
2962                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2963
2964                 /* Create header list */
2965                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
2966                 headers = tny_simple_list_new ();
2967                 tny_list_prepend (headers, G_OBJECT (header));
2968                 g_object_unref (header);
2969
2970                 /* Ask user for confirmation. MSG-NOT404 */
2971                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2972                                                       TNY_FOLDER (folder_store), 
2973                                                       headers);
2974
2975                 /* Transfer current msg */
2976                 if (response == GTK_RESPONSE_OK) {
2977                         ModestMailOperation *mail_op;
2978
2979                         /* Create mail op */
2980                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2981                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2982                                                          mail_op);
2983                         
2984                         /* Transfer messages */
2985                         modest_mail_operation_xfer_msgs (mail_op, 
2986                                                          headers,
2987                                                          TNY_FOLDER (folder_store),
2988                                                          TRUE,
2989                                                          transfer_msgs_from_viewer_cb,
2990                                                          NULL);
2991                         g_object_unref (G_OBJECT (mail_op));
2992                 }
2993                 g_object_unref (headers);
2994                 g_object_unref (folder_store);
2995         }
2996         gtk_widget_destroy (dialog);
2997 }
2998
2999 void 
3000 modest_ui_actions_on_move_to (GtkAction *action, 
3001                               ModestWindow *win)
3002 {
3003         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3004                           MODEST_IS_MSG_VIEW_WINDOW (win));
3005
3006         if (MODEST_IS_MAIN_WINDOW (win)) 
3007                 modest_ui_actions_on_main_window_move_to (action, 
3008                                                           MODEST_MAIN_WINDOW (win));
3009         else
3010                 modest_ui_actions_on_msg_view_window_move_to (action, 
3011                                                               MODEST_MSG_VIEW_WINDOW (win));
3012 }
3013
3014 /*
3015  * Calls #HeadersFunc for each header already selected in the main
3016  * window or the message currently being shown in the msg view window
3017  */
3018 static void
3019 do_headers_action (ModestWindow *win, 
3020                    HeadersFunc func,
3021                    gpointer user_data)
3022 {
3023         TnyList *headers_list;
3024         TnyIterator *iter;
3025         TnyHeader *header;
3026         TnyFolder *folder;
3027
3028         /* Get headers */
3029         headers_list = get_selected_headers (win);
3030         if (!headers_list)
3031                 return;
3032
3033         /* Get the folder */
3034         iter = tny_list_create_iterator (headers_list);
3035         header = TNY_HEADER (tny_iterator_get_current (iter));
3036         folder = tny_header_get_folder (header);
3037         g_object_unref (header);
3038
3039         /* Call the function for each header */
3040         while (!tny_iterator_is_done (iter)) {
3041                 header = TNY_HEADER (tny_iterator_get_current (iter));
3042                 func (header, win, user_data);
3043                 g_object_unref (header);
3044                 tny_iterator_next (iter);
3045         }
3046
3047         /* Trick: do a poke status in order to speed up the signaling
3048            of observers */
3049         tny_folder_poke_status (folder);
3050
3051         /* Frees */
3052         g_object_unref (folder);
3053         g_object_unref (iter);
3054         g_object_unref (headers_list);
3055 }
3056
3057 void 
3058 modest_ui_actions_view_attachment (GtkAction *action,
3059                                    ModestWindow *window)
3060 {
3061         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3062                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3063         } else {
3064                 /* not supported window for this action */
3065                 g_return_if_reached ();
3066         }
3067 }
3068
3069 void
3070 modest_ui_actions_save_attachments (GtkAction *action,
3071                                     ModestWindow *window)
3072 {
3073         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3074                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3075         } else {
3076                 /* not supported window for this action */
3077                 g_return_if_reached ();
3078         }
3079 }
3080
3081 void
3082 modest_ui_actions_remove_attachments (GtkAction *action,
3083                                       ModestWindow *window)
3084 {
3085         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3086                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3087         } else {
3088                 /* not supported window for this action */
3089                 g_return_if_reached ();
3090         }
3091 }
3092
3093 void 
3094 modest_ui_actions_on_settings (GtkAction *action, 
3095                                ModestWindow *win)
3096 {
3097         GtkWidget *dialog;
3098
3099         dialog = modest_platform_get_global_settings_dialog ();
3100         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3101         gtk_widget_show (dialog);
3102
3103         gtk_dialog_run (GTK_DIALOG (dialog));
3104
3105         gtk_widget_destroy (dialog);
3106 }
3107
3108 void 
3109 modest_ui_actions_on_help (GtkAction *action, 
3110                            ModestWindow *win)
3111 {
3112         const gchar *help_id = NULL;
3113
3114         if (MODEST_IS_MAIN_WINDOW (win)) {
3115                 const gchar *action_name;
3116                 action_name = gtk_action_get_name (action);
3117
3118                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3119                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3120                         GtkWidget *folder_view;
3121                         TnyFolderStore *folder_store;
3122                         /* Get selected folder */
3123                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3124                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3125                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3126
3127                         /* Switch help_id */
3128                         if (TNY_IS_FOLDER (folder_store)) {
3129                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
3130                                 case TNY_FOLDER_TYPE_NORMAL:
3131                                         help_id = "applications_email_userfolder";
3132                                         break;
3133                                 case TNY_FOLDER_TYPE_INBOX:
3134                                         help_id = "applications_email_inbox";
3135                                         break;
3136                                 case TNY_FOLDER_TYPE_OUTBOX:
3137                                         help_id = "applications_email_outbox";
3138                                         break;
3139                                 case TNY_FOLDER_TYPE_SENT:
3140                                         help_id = "applications_email_sent";
3141                                         break;
3142                                 case TNY_FOLDER_TYPE_DRAFTS:
3143                                         help_id = "applications_email_drafts";
3144                                         break;
3145                                 case TNY_FOLDER_TYPE_ARCHIVE:
3146                                         help_id = "applications_email_archive";
3147                                         break;
3148                                 default:
3149                                         help_id = NULL;
3150                                 }
3151                         }
3152                         g_object_unref (folder_store);
3153                 } else {
3154                         help_id = "applications_email_mainview";        
3155                 }
3156         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3157                 help_id = "applications_email_viewer";
3158         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3159                 help_id = "applications_email_editor";
3160
3161         modest_platform_show_help (GTK_WINDOW (win), help_id);
3162 }
3163
3164 void 
3165 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3166                                             ModestWindow *window)
3167 {
3168         ModestMailOperation *mail_op;
3169         TnyList *headers;
3170
3171         /* Get headers */
3172         headers = get_selected_headers (window);
3173         if (!headers)
3174                 return;
3175
3176         /* Create mail operation */
3177         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3178                                                                  G_OBJECT (window),
3179                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3180                                                                  NULL);
3181         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3182         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3183
3184         /* Frees */
3185         g_object_unref (headers);
3186         g_object_unref (mail_op);
3187 }
3188
3189 void
3190 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3191                                           ModestWindow *window)
3192 {
3193         g_return_if_fail (MODEST_IS_WINDOW (window));
3194
3195         /* Update dimmed */     
3196         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3197 }
3198
3199 void
3200 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3201                                           ModestWindow *window)
3202 {
3203         g_return_if_fail (MODEST_IS_WINDOW (window));
3204
3205         /* Update dimmed */     
3206         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3207 }
3208
3209 void
3210 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3211                                           ModestWindow *window)
3212 {
3213         g_return_if_fail (MODEST_IS_WINDOW (window));
3214
3215         /* Update dimmed */     
3216         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3217 }
3218
3219 void
3220 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3221                                           ModestWindow *window)
3222 {
3223         g_return_if_fail (MODEST_IS_WINDOW (window));
3224
3225         /* Update dimmed */     
3226         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3227 }
3228
3229 void
3230 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3231                                           ModestWindow *window)
3232 {
3233         g_return_if_fail (MODEST_IS_WINDOW (window));
3234
3235         /* Update dimmed */     
3236         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3237 }
3238
3239 void
3240 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3241                                                  ModestWindow *window)
3242 {
3243         g_return_if_fail (MODEST_IS_WINDOW (window));
3244
3245         /* Update dimmed */     
3246         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3247 }
3248
3249 void
3250 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3251                                                      ModestWindow *window)
3252 {
3253         g_return_if_fail (MODEST_IS_WINDOW (window));
3254
3255         /* Update dimmed */     
3256         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3257 }
3258
3259 void
3260 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3261                                                      ModestWindow *window)
3262 {
3263         g_return_if_fail (MODEST_IS_WINDOW (window));
3264
3265         /* Update dimmed */     
3266         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3267 }
3268
3269 void
3270 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3271 {
3272         g_return_if_fail (MODEST_IS_WINDOW (window));
3273
3274         /* Update dimmed */     
3275         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3276 }
3277
3278 void
3279 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3280 {
3281         g_return_if_fail (MODEST_IS_WINDOW (window));
3282
3283         modest_platform_show_search_messages (GTK_WINDOW (window));
3284 }
3285
3286 void     
3287 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3288 {
3289         g_return_if_fail (MODEST_IS_WINDOW (win));
3290         modest_platform_show_addressbook (GTK_WINDOW (win));
3291 }
3292
3293
3294 void
3295 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3296                                           ModestWindow *window)
3297 {
3298         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3299
3300         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3301 }
3302
3303 static void 
3304 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3305                                    ModestMailOperationState *state,
3306                                    gpointer user_data)
3307 {
3308         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3309
3310         /* Set send/receive operation finished */       
3311         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3312                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3313         
3314 }
3315
3316