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