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