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