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