2f0eb7e3fae5f692f2c63b9d713d0a5bf24d7420
[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 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51
52 #ifdef MODEST_PLATFORM_MAEMO
53 #include "maemo/modest-osso-state-saving.h"
54 #include "maemo/modest-maemo-utils.h"
55 #include "maemo/modest-hildon-includes.h"
56 #endif /* MODEST_PLATFORM_MAEMO */
57
58 #include "widgets/modest-ui-constants.h"
59 #include <widgets/modest-main-window.h>
60 #include <widgets/modest-msg-view-window.h>
61 #include <widgets/modest-account-view-window.h>
62 #include <widgets/modest-details-dialog.h>
63 #include <widgets/modest-attachments-view.h>
64 #include "widgets/modest-folder-view.h"
65 #include "widgets/modest-global-settings-dialog.h"
66 #include "modest-connection-specific-smtp-window.h"
67 #include "modest-account-mgr-helpers.h"
68 #include "modest-mail-operation.h"
69 #include "modest-text-utils.h"
70
71 #ifdef MODEST_HAVE_EASYSETUP
72 #include "easysetup/modest-easysetup-wizard.h"
73 #endif /* MODEST_HAVE_EASYSETUP */
74
75 #include <modest-widget-memory.h>
76 #include <tny-error.h>
77 #include <tny-simple-list.h>
78 #include <tny-msg-view.h>
79 #include <tny-device.h>
80 #include <tny-merge-folder.h>
81
82 #include <gtkhtml/gtkhtml.h>
83
84 typedef struct _GetMsgAsyncHelper {     
85         ModestWindow *window;
86         ModestMailOperation *mail_op;
87         TnyIterator *iter;
88         guint num_ops;
89         GFunc func;     
90         gpointer user_data;
91 } GetMsgAsyncHelper;
92
93 typedef enum _ReplyForwardAction {
94         ACTION_REPLY,
95         ACTION_REPLY_TO_ALL,
96         ACTION_FORWARD
97 } ReplyForwardAction;
98
99 typedef struct _ReplyForwardHelper {
100         guint reply_forward_type;
101         ReplyForwardAction action;
102         gchar *account_name;
103         GtkWidget *parent_window;
104 } ReplyForwardHelper;
105
106 typedef struct _MoveToHelper {
107         ModestMailOperation *mail_op;
108         TnyFolder *folder;
109 } MoveToHelper;
110
111 typedef struct _PasteAsAttachmentHelper {
112         ModestMsgEditWindow *window;
113         GtkWidget *banner;
114 } PasteAsAttachmentHelper;
115
116
117 /*
118  * The do_headers_action uses this kind of functions to perform some
119  * action to each member of a list of headers
120  */
121 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
122
123 static void     do_headers_action     (ModestWindow *win, 
124                                        HeadersFunc func,
125                                        gpointer user_data);
126
127 static void     open_msg_cb            (ModestMailOperation *mail_op, 
128                                         TnyHeader *header, 
129                                         TnyMsg *msg,
130                                         gpointer user_data);
131
132 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
133                                         TnyHeader *header, 
134                                         TnyMsg *msg,
135                                         gpointer user_data);
136
137 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
138
139 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
140                                         TnyFolder *folder, 
141                                         gpointer user_data);
142
143 static void     _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
144                                                    ModestMailOperationState *state,
145                                                    gpointer user_data);
146
147 static gint header_list_count_uncached_msgs (TnyList *header_list);
148 static gboolean connect_to_get_msg (
149                                                 GtkWindow *win,
150                                                 gint num_of_uncached_msgs);
151
152 static gboolean remote_folder_is_pop (const TnyFolderStore *folder);
153
154 static gboolean msgs_already_deleted_from_server ( TnyList *headers,
155                                                    const TnyFolderStore *src_folder);
156
157
158 /*
159  * This function checks whether a TnyFolderStore is a pop account
160  */
161 static gboolean
162 remote_folder_is_pop (const TnyFolderStore *folder)
163 {
164         const gchar *proto = NULL;
165         TnyAccount *account = NULL;
166
167         g_return_val_if_fail (TNY_IS_FOLDER_STORE(folder), FALSE);
168
169         if (TNY_IS_ACCOUNT (folder)) {
170                 account = TNY_ACCOUNT(folder);
171                 g_object_ref(account);
172         } else if (TNY_IS_FOLDER (folder)) {
173                 account = tny_folder_get_account(TNY_FOLDER(folder));
174         }
175
176         proto = tny_account_get_proto(account);
177         g_object_unref (account);
178
179         return proto &&
180           (modest_protocol_info_get_transport_store_protocol (proto) == MODEST_PROTOCOL_STORE_POP);
181 }
182
183 /*
184  * This functions checks whether if a list of messages are already
185  * deleted from the server: that is, if the server is a POP account
186  * and all messages are already cached.
187  */
188 static gboolean
189 msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_folder)
190 {
191         g_return_val_if_fail (TNY_IS_FOLDER_STORE(src_folder), FALSE);
192         g_return_val_if_fail (TNY_IS_LIST(headers), FALSE);
193
194         gboolean src_is_pop = remote_folder_is_pop (src_folder);
195         gint uncached_msgs = header_list_count_uncached_msgs (headers);
196
197         return (src_is_pop && !uncached_msgs);
198 }
199
200 /* Show the account creation wizard dialog.
201  * returns: TRUE if an account was created. FALSE if the user cancelled.
202  */
203 gboolean
204 modest_run_account_setup_wizard (ModestWindow *win)
205 {
206         gboolean result = FALSE;
207         GtkDialog *wizard;
208         
209         wizard = modest_window_mgr_get_easysetup_dialog
210                 (modest_runtime_get_window_mgr());
211         if (wizard) {
212                 /* old wizard is active already; present it and
213                  * act as if the user cancelled the non-existing
214                  * new one
215                  */
216                 printf ("wizard already active\n");
217                 return FALSE;
218         } else {
219                 /* there is no such wizard yet */
220                 wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ());
221                 modest_window_mgr_set_easysetup_dialog
222                         (modest_runtime_get_window_mgr(), GTK_DIALOG(wizard));
223         } 
224
225         
226         /* always present a main window in the background 
227          * we do it here, so we cannot end up with to wizards (as this
228          * function might be called in modest_window_mgr_get_main_window as well */
229         if (!win) 
230                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr());
231
232         /* make sure the mainwindow is visible */
233         gtk_widget_show_all (GTK_WIDGET(win));
234         gtk_window_present (GTK_WINDOW(win));
235
236         
237         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
238
239         /* Don't make this a modal window, because secondary windows will then 
240          * be unusable, freezing the UI: */
241         /* gtk_window_set_modal (GTK_WINDOW (wizard), TRUE); */
242         
243         gint dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
244         if (dialog_response == GTK_RESPONSE_CANCEL)
245                 result = FALSE;
246         else {
247                 /* Check whether an account was created: */
248                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
249         }
250         
251         gtk_widget_destroy (GTK_WIDGET (wizard));
252
253         /* clear it from the window mgr */
254         modest_window_mgr_set_easysetup_dialog
255                 (modest_runtime_get_window_mgr(), NULL);
256         
257         return result;
258 }
259
260
261 void   
262 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
263 {
264         GtkWidget *about;
265         const gchar *authors[] = {
266                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
267                 NULL
268         };
269         about = gtk_about_dialog_new ();
270         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
271         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
272         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
273                                         _("Copyright (c) 2006, Nokia Corporation\n"
274                                           "All rights reserved."));
275         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
276                                        _("a modest e-mail client\n\n"
277                                          "design and implementation: Dirk-Jan C. Binnema\n"
278                                          "contributions from the fine people at KC and Ig\n"
279                                          "uses the tinymail email framework written by Philip van Hoof"));
280         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
281         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
282         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
283         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
284         
285         gtk_dialog_run (GTK_DIALOG (about));
286         gtk_widget_destroy(about);
287 }
288
289 /*
290  * Gets the list of currently selected messages. If the win is the
291  * main window, then it returns a newly allocated list of the headers
292  * selected in the header view. If win is the msg view window, then
293  * the value returned is a list with just a single header.
294  *
295  * The caller of this funcion must free the list.
296  */
297 static TnyList *
298 get_selected_headers (ModestWindow *win)
299 {
300         if (MODEST_IS_MAIN_WINDOW(win)) {
301                 GtkWidget *header_view;         
302                 
303                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
304                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
305                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
306                 
307         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
308                 /* for MsgViewWindows, we simply return a list with one element */
309                 TnyHeader *header;
310                 TnyList *list = NULL;
311                 
312                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
313                 if (header != NULL) {
314                         list = tny_simple_list_new ();
315                         tny_list_prepend (list, G_OBJECT(header));
316                         g_object_unref (G_OBJECT(header));
317                 }
318
319                 return list;
320
321         } else
322                 return NULL;
323 }
324
325 static void
326 headers_action_mark_as_read (TnyHeader *header,
327                              ModestWindow *win,
328                              gpointer user_data)
329 {
330         TnyHeaderFlags flags;
331
332         g_return_if_fail (TNY_IS_HEADER(header));
333
334         flags = tny_header_get_flags (header);
335         if (flags & TNY_HEADER_FLAG_SEEN) return;
336         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
337 }
338
339 static void
340 headers_action_mark_as_unread (TnyHeader *header,
341                                ModestWindow *win,
342                                gpointer user_data)
343 {
344         TnyHeaderFlags flags;
345
346         g_return_if_fail (TNY_IS_HEADER(header));
347
348         flags = tny_header_get_flags (header);
349         if (flags & TNY_HEADER_FLAG_SEEN)  {
350                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
351         }
352 }
353
354 /** A convenience method, because deleting a message is 
355  * otherwise complicated, and it's best to change it in one place 
356  * when we change it.
357  */
358 void modest_do_message_delete (TnyHeader *header, ModestWindow *win)
359 {
360         ModestMailOperation *mail_op = NULL;
361         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
362                 win ? G_OBJECT(win) : NULL);
363         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
364                                          mail_op);
365         
366         /* Always delete. TODO: Move to trash still not supported */
367         modest_mail_operation_remove_msg (mail_op, header, FALSE);
368         g_object_unref (G_OBJECT (mail_op));
369 }
370
371 /** A convenience method, because deleting a message is 
372  * otherwise complicated, and it's best to change it in one place 
373  * when we change it.
374  */
375 void modest_do_messages_delete (TnyList *headers, ModestWindow *win)
376 {
377         ModestMailOperation *mail_op = NULL;
378         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, 
379                 win ? G_OBJECT(win) : NULL);
380         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
381                                          mail_op);
382         
383         /* Always delete. TODO: Move to trash still not supported */
384         modest_mail_operation_remove_msgs (mail_op, headers, FALSE);
385         g_object_unref (G_OBJECT (mail_op));
386 }
387
388 /* static void */
389 /* headers_action_delete (TnyHeader *header, */
390 /*                     ModestWindow *win, */
391 /*                     gpointer user_data) */
392 /* { */
393 /*      modest_do_message_delete (header, win); */
394
395 /* } */
396
397 /** After deleing a message that is currently visible in a window, 
398  * show the next message from the list, or close the window if there are no more messages.
399  **/
400 void modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
401 {
402         /* Close msg view window or select next */
403         if (modest_msg_view_window_last_message_selected (win) &&
404                 modest_msg_view_window_first_message_selected (win)) {
405                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (win));
406         } else {
407                 if (!modest_msg_view_window_select_next_message (win)) {
408                         gboolean ret_value;
409                         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
410                 }
411         }
412 }
413
414 void
415 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
416 {
417         TnyList *header_list = NULL;
418         TnyIterator *iter = NULL;
419         TnyHeader *header = NULL;
420         gchar *message = NULL;
421         gchar *desc = NULL;
422         gint response;
423         ModestWindowMgr *mgr;
424         GtkWidget *header_view = NULL;
425
426         g_return_if_fail (MODEST_IS_WINDOW(win));
427         
428         /* Check first if the header view has the focus */
429         if (MODEST_IS_MAIN_WINDOW (win)) {
430                 header_view = 
431                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
432                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
433                 if (!gtk_widget_is_focus (header_view))
434                         return;
435         }
436         
437         /* Get the headers, either from the header view (if win is the main window),
438          * or from the message view window: */
439         header_list = get_selected_headers (win);
440         if (!header_list) return;
441                         
442         /* Check if any of the headers are already opened, or in the process of being opened */
443         if (MODEST_IS_MAIN_WINDOW (win)) {
444                 gboolean found;
445                 iter = tny_list_create_iterator (header_list);
446                 found = FALSE;
447                 mgr = modest_runtime_get_window_mgr ();
448                 while (!tny_iterator_is_done (iter) && !found) {
449                         header = TNY_HEADER (tny_iterator_get_current (iter));
450                         if (header) {
451                                 found =  modest_window_mgr_find_registered_header (mgr, header, NULL);
452                                 g_object_unref (header);
453                         }
454
455                         tny_iterator_next (iter);
456                 }
457                 g_object_unref (iter);
458
459                 if (found) {
460                         gchar *num, *msg;
461
462                         num = g_strdup_printf ("%d", tny_list_get_length (header_list));
463                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
464
465                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
466                         
467                         g_free (msg);
468                         g_free (num);
469                         g_object_unref (header_list);
470                         return;
471                 }
472         }
473
474         /* Select message */
475         if (tny_list_get_length(header_list) == 1) {
476                 iter = tny_list_create_iterator (header_list);
477                 header = TNY_HEADER (tny_iterator_get_current (iter));
478                 if (header) {
479                         desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
480                         g_object_unref (header);
481                 }
482
483                 g_object_unref (iter);
484         }
485         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
486                                            tny_list_get_length(header_list)), desc);
487
488         /* Confirmation dialog */
489         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
490                                                             message);
491         
492
493         if (response == GTK_RESPONSE_OK) {      
494                 ModestWindow *main_window = NULL;
495                 ModestWindowMgr *mgr = NULL;
496                 GtkTreeModel *model = NULL;
497                 GtkTreeSelection *sel = NULL;
498                 GList *sel_list = NULL, *tmp = NULL;
499                 GtkTreeRowReference *next_row_reference = NULL;
500                 GtkTreeRowReference *prev_row_reference = NULL;
501                 GtkTreePath *next_path = NULL;
502                 GtkTreePath *prev_path = NULL;
503                 GError *err = NULL;
504
505                 /* Find last selected row */                    
506                 if (MODEST_IS_MAIN_WINDOW (win)) {
507                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
508                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
509                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
510                         for (tmp=sel_list; tmp; tmp=tmp->next) {
511                                 if (tmp->next == NULL) {
512                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
513                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
514
515                                         gtk_tree_path_prev (prev_path);
516                                         gtk_tree_path_next (next_path);
517
518                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
519                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
520                                 }
521                         }
522                 }
523                 
524                 /* Disable window dimming management */
525                 modest_window_disable_dimming (MODEST_WINDOW(win));
526
527                 /* Remove each header. If it's a view window header_view == NULL */
528                 modest_do_messages_delete (header_list, win);
529                 
530                 /* Enable window dimming management */
531                 if (sel != NULL) {
532                         gtk_tree_selection_unselect_all (sel);
533                 }
534                 modest_window_enable_dimming (MODEST_WINDOW(win));
535                 
536                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
537                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
538                         
539                         /* Get main window */
540                         mgr = modest_runtime_get_window_mgr ();
541                         main_window = modest_window_mgr_get_main_window (mgr);
542                 }
543                 else {                  
544                         /* Move cursor to next row */
545                         main_window = win; 
546
547                         /* Select next or previous row */
548                         if (gtk_tree_row_reference_valid (next_row_reference)) {
549 /*                              next_path = gtk_tree_row_reference_get_path (row_reference); */
550                                 gtk_tree_selection_select_path (sel, next_path);
551                         }
552                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
553                                 gtk_tree_selection_select_path (sel, prev_path);
554                         }
555
556                         /* Free */
557                         if (next_row_reference != NULL) 
558                                 gtk_tree_row_reference_free (next_row_reference);
559                         if (next_path != NULL) 
560                                 gtk_tree_path_free (next_path);                         
561                         if (prev_row_reference != NULL) 
562                                 gtk_tree_row_reference_free (prev_row_reference);
563                         if (prev_path != NULL) 
564                                 gtk_tree_path_free (prev_path);                         
565                 }
566
567                 if (err != NULL) {
568                         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, err->code, err->message);
569                         g_error_free(err);
570                 }
571                 
572                 /* Update toolbar dimming state */
573                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
574
575                 /* Free */
576                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
577                 g_list_free (sel_list);
578         }
579
580         /* Free*/
581         g_free(message);
582         g_free(desc);
583         g_object_unref (header_list);
584 }
585
586
587
588
589 /* delete either message or folder, based on where we are */
590 void
591 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
592 {
593         g_return_if_fail (MODEST_IS_WINDOW(win));
594         
595         /* Check first if the header view has the focus */
596         if (MODEST_IS_MAIN_WINDOW (win)) {
597                 GtkWidget *w;
598                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
599                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
600                 if (gtk_widget_is_focus (w)) {
601                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
602                         return;
603                 }
604         }
605         modest_ui_actions_on_delete_message (action, win);
606 }
607
608
609
610 void
611 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
612 {       
613         ModestWindowMgr *mgr = NULL;
614         
615 #ifdef MODEST_PLATFORM_MAEMO
616         modest_osso_save_state();
617 #endif /* MODEST_PLATFORM_MAEMO */
618
619         g_debug ("closing down, clearing %d item(s) from operation queue",
620                  modest_mail_operation_queue_num_elements
621                  (modest_runtime_get_mail_operation_queue()));
622
623         /* cancel all outstanding operations */
624         modest_mail_operation_queue_cancel_all 
625                 (modest_runtime_get_mail_operation_queue());
626         
627         g_debug ("queue has been cleared");
628
629
630         /* Check if there are opened editing windows */ 
631         mgr = modest_runtime_get_window_mgr ();
632         modest_window_mgr_close_all_windows (mgr);
633
634         /* note: when modest-tny-account-store is finalized,
635            it will automatically set all network connections
636            to offline */
637
638 /*      gtk_main_quit (); */
639 }
640
641 void
642 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
643 {
644         gboolean ret_value;
645
646         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
647
648 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
649 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
650 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
651 /*              gboolean ret_value; */
652 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
653 /*      } else if (MODEST_IS_WINDOW (win)) { */
654 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
655 /*      } else { */
656 /*              g_return_if_reached (); */
657 /*      } */
658 }
659
660 void
661 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
662 {
663         GtkClipboard *clipboard = NULL;
664         gchar *selection = NULL;
665
666         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
667         selection = gtk_clipboard_wait_for_text (clipboard);
668
669         /* Question: why is the clipboard being used here? 
670          * It doesn't really make a lot of sense. */
671
672         if (selection)
673         {
674                 modest_address_book_add_address (selection);
675                 g_free (selection);
676         }
677 }
678
679 void
680 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
681 {
682         /* This is currently only implemented for Maemo */
683 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
684         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
685                 modest_run_account_setup_wizard (win);
686                 return;
687         } else  {
688                 /* Show the list of accounts: */
689                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
690                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
691                 
692                 /* The accounts dialog must be modal  */
693                 gtk_window_set_modal (GTK_WINDOW (account_win), TRUE);
694                 modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); 
695         }
696 #else
697         GtkWidget *dialog, *label;
698         
699         /* Create the widgets */
700         
701         dialog = gtk_dialog_new_with_buttons ("Message",
702                                               GTK_WINDOW(win),
703                                               GTK_DIALOG_DESTROY_WITH_PARENT,
704                                               GTK_STOCK_OK,
705                                               GTK_RESPONSE_NONE,
706                                               NULL);
707         label = gtk_label_new ("Hello World!");
708         
709         /* Ensure that the dialog box is destroyed when the user responds. */
710         
711         g_signal_connect_swapped (dialog, "response", 
712                                   G_CALLBACK (gtk_widget_destroy),
713                                   dialog);
714         
715         /* Add the label, and show everything we've added to the dialog. */
716         
717         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
718                            label);
719         gtk_widget_show_all (dialog);
720 #endif /* MODEST_PLATFORM_MAEMO */
721 }
722
723 static void
724 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
725 {
726         /* Save any changes. */
727         modest_connection_specific_smtp_window_save_server_accounts (
728                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window));
729         gtk_widget_destroy (GTK_WIDGET (window));
730 }
731
732
733
734 void
735 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
736 {
737         /* This is currently only implemented for Maemo,
738          * because it requires an API (libconic) to detect different connection 
739          * possiblities.
740          */
741 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
742         
743         /* Create the window if necessary: */
744         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
745         modest_connection_specific_smtp_window_fill_with_connections (
746                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
747                 modest_runtime_get_account_mgr());
748
749         /* Show the window: */  
750         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
751         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
752         gtk_widget_show (specific_window);
753     
754         /* Save changes when the window is hidden: */
755         g_signal_connect (specific_window, "hide", 
756                 G_CALLBACK (on_smtp_servers_window_hide), win);
757 #endif /* MODEST_PLATFORM_MAEMO */
758 }
759
760 void
761 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
762 {
763         ModestWindow *msg_win = NULL;
764         TnyMsg *msg = NULL;
765         TnyFolder *folder = NULL;
766         gchar *account_name = NULL;
767         gchar *from_str = NULL;
768 /*      GError *err = NULL; */
769         TnyAccount *account = NULL;
770         ModestWindowMgr *mgr;
771         gchar *signature = NULL, *blank_and_signature = NULL;
772
773         /* if there are no accounts yet, just show the wizard */
774         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
775                         const gboolean created = modest_run_account_setup_wizard (win);
776                         if (!created)
777                                 return;
778         }
779         
780         account_name = g_strdup (modest_window_get_active_account (win));
781         if (!account_name)
782                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
783         if (!account_name) {
784                 g_printerr ("modest: no account found\n");
785                 goto cleanup;
786         }
787         
788         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
789                                                                        account_name,
790                                                                        TNY_ACCOUNT_TYPE_STORE);
791         if (!account) {
792                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
793                 goto cleanup;
794         }
795
796         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
797         if (!from_str) {
798                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
799                 goto cleanup;
800         }
801
802         gboolean use_signature = FALSE;
803         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr (), account_name, &use_signature);
804
805         if (use_signature) {
806                 blank_and_signature = g_strconcat ("\n", signature, NULL);
807         } else {
808                 blank_and_signature = g_strdup ("");
809         }
810
811         g_free (signature);
812
813         msg = modest_tny_msg_new ("", from_str, "", "", "", blank_and_signature, NULL);
814         if (!msg) {
815                 g_printerr ("modest: failed to create new msg\n");
816                 goto cleanup;
817         }
818         
819         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
820         if (!folder) {
821                 g_printerr ("modest: failed to find Drafts folder\n");
822                 goto cleanup;
823         }
824         
825         
826         /* Create and register edit window */
827         /* This is destroyed by TODO. */
828         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
829         mgr = modest_runtime_get_window_mgr ();
830         modest_window_mgr_register_window (mgr, msg_win);
831
832         if (win)
833                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
834                                               GTK_WINDOW (win));
835         gtk_widget_show_all (GTK_WIDGET (msg_win));
836
837 cleanup:
838         g_free (account_name);
839         g_free (from_str);
840         g_free (blank_and_signature);
841         if (msg_win)
842                 g_object_unref (msg_win);
843         if (account)
844                 g_object_unref (G_OBJECT(account));
845         if (msg)
846                 g_object_unref (G_OBJECT(msg));
847         if (folder)
848                 g_object_unref (G_OBJECT(folder));
849 }
850
851 gboolean 
852 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
853                                        TnyHeader *header,
854                                        TnyMsg *msg)
855 {
856         ModestMailOperationStatus status;
857
858         /* If there is no message or the operation was not successful */
859         status = modest_mail_operation_get_status (mail_op);
860         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
861
862                 /* Remove the header from the preregistered uids */
863                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
864                                                      header);
865
866                 return FALSE;
867         }
868
869         return TRUE;
870 }
871
872 static void
873 open_msg_cb (ModestMailOperation *mail_op, TnyHeader *header,  TnyMsg *msg, gpointer user_data)
874 {
875         ModestWindowMgr *mgr = NULL;
876         ModestWindow *parent_win = NULL;
877         ModestWindow *win = NULL;
878         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
879         gchar *account = NULL;
880         TnyFolder *folder;
881         
882         /* Do nothing if there was any problem with the mail
883            operation. The error will be shown by the error_handler of
884            the mail operation */
885         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
886                 return;
887
888         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
889         folder = tny_header_get_folder (header);
890
891         /* Mark header as read */
892         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
893
894         /* Get account */
895         account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
896         if (!account)
897                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
898         
899         /* Gets folder type (OUTBOX headers will be opened in edit window */
900         if (modest_tny_folder_is_local_folder (folder))
901                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
902
903         /* If the header is in the drafts folder then open the editor,
904            else the message view window */
905         if ((folder_type == TNY_FOLDER_TYPE_DRAFTS) ||
906             (folder_type == TNY_FOLDER_TYPE_OUTBOX)) {
907                 /* we cannot edit without a valid account... */
908                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
909                         const gboolean created = modest_run_account_setup_wizard(parent_win);
910                         if (!created)
911                                 goto cleanup;
912                 }
913                 win = modest_msg_edit_window_new (msg, account, TRUE);
914
915
916                 /* Show banner */
917                 modest_platform_information_banner (NULL, NULL, _("mail_ib_opening_draft_message"));
918
919         } else {
920                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
921                 
922                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
923                         GtkWidget *header_view;
924                         GtkTreeSelection *sel;
925                         GList *sel_list = NULL;
926                         GtkTreeModel *model;
927                         
928                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
929                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
930
931                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
932                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
933
934                         if (sel_list != NULL) {
935                                 GtkTreeRowReference *row_reference;
936
937                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
938                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
939                                 g_list_free (sel_list);
940                                 
941                                 win = modest_msg_view_window_new_with_header_model (
942                                                 msg, account, (const gchar*) uid,
943                                                 model, row_reference);
944                                 gtk_tree_row_reference_free (row_reference);
945                         } else {
946                                 win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
947                         }
948                 } else {
949                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
950                 }
951                 g_free (uid);
952         }
953         
954         /* Register and show new window */
955         if (win != NULL) {
956                 mgr = modest_runtime_get_window_mgr ();
957                 modest_window_mgr_register_window (mgr, win);
958                 g_object_unref (win);
959                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
960                 gtk_widget_show_all (GTK_WIDGET(win));
961         }
962
963         /* Update toolbar dimming state */
964         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
965                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
966         }
967
968 cleanup:
969         /* Free */
970         g_free(account);
971         g_object_unref (parent_win);
972         g_object_unref (folder);
973 }
974
975 void
976 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
977                                                gpointer user_data)
978 {
979         const GError *error;
980         GObject *win = modest_mail_operation_get_source (mail_op);
981
982         error = modest_mail_operation_get_error (mail_op);
983 /*      printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message); */
984  
985         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
986
987                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
988                                                         error->message);
989         } else {
990                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
991                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
992         }
993
994         if (win)
995                 g_object_unref (win);
996 }
997
998 /*
999  * This function is used by both modest_ui_actions_on_open and
1000  * modest_ui_actions_on_header_activated. This way we always do the
1001  * same when trying to open messages.
1002  */
1003 static void
1004 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
1005 {
1006         ModestWindowMgr *mgr = NULL;
1007         TnyIterator *iter = NULL;
1008         ModestMailOperation *mail_op = NULL;
1009         TnyList *not_opened_headers = NULL;
1010         TnyHeaderFlags flags = 0;
1011                 
1012         g_return_if_fail (headers != NULL);
1013
1014         /* Check that only one message is selected for opening */
1015         if (tny_list_get_length (headers) != 1) {
1016                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1017                                                         _("mcen_ib_select_one_message"));
1018                 return;
1019         }
1020
1021
1022         /* Look if we already have a message view for each header. If
1023            true, then remove the header from the list of headers to
1024            open */
1025         mgr = modest_runtime_get_window_mgr ();
1026         iter = tny_list_create_iterator (headers);
1027         not_opened_headers = tny_simple_list_new ();
1028         
1029         while (!tny_iterator_is_done (iter)) {
1030
1031                 ModestWindow *window = NULL;
1032                 TnyHeader *header = NULL;
1033                 gboolean found = FALSE;
1034                 
1035                 header = TNY_HEADER (tny_iterator_get_current (iter));
1036                 if (header)
1037                         flags = tny_header_get_flags (header);
1038
1039                 window = NULL;
1040                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1041                 
1042                 /* Do not open again the message and present the
1043                    window to the user */
1044                 if (found) {
1045                         if (window)
1046                                 gtk_window_present (GTK_WINDOW (window));
1047                         else
1048                                 /* the header has been registered already, we don't do
1049                                  * anything but wait for the window to come up*/
1050                                 g_debug ("header %p already registered, waiting for window", header);
1051                 } else {
1052                         tny_list_append (not_opened_headers, G_OBJECT (header));
1053                 }
1054
1055                 if (header)
1056                         g_object_unref (header);
1057
1058                 tny_iterator_next (iter);
1059         }
1060         g_object_unref (iter);
1061         iter = NULL;
1062         
1063         /* If some messages would have to be downloaded, ask the user to 
1064          * make a connection. It's generally easier to do this here (in the mainloop) 
1065          * than later in a thread:
1066          */
1067         if (tny_list_get_length (not_opened_headers) > 0) {
1068                 TnyIterator *iter;
1069                 gboolean found = FALSE;
1070
1071                 iter = tny_list_create_iterator (not_opened_headers);
1072                 while (!tny_iterator_is_done (iter) && !found) {
1073                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1074                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1075                                 found = TRUE;
1076                         else
1077                                 tny_iterator_next (iter);
1078
1079                         g_object_unref (header);
1080                 }
1081                 g_object_unref (iter);
1082
1083                 if (found && !modest_platform_connect_and_wait (GTK_WINDOW (win), NULL)) {
1084                         g_object_unref (not_opened_headers);
1085                         return;                 
1086                 }
1087         }
1088         
1089         /* Register the headers before actually creating the windows: */
1090         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
1091         while (!tny_iterator_is_done (iter_not_opened)) {
1092                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1093                 if (header) {
1094                         modest_window_mgr_register_header (mgr, header);
1095                         g_object_unref (header);
1096                 }
1097                 
1098                 tny_iterator_next (iter_not_opened);
1099         }
1100         g_object_unref (iter_not_opened);
1101         iter_not_opened = NULL;
1102         
1103         /* Open each message */
1104         if (tny_list_get_length (not_opened_headers) > 0) {
1105                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1106                                                                          G_OBJECT (win), 
1107                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1108                                                                          NULL);
1109                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1110                 if (tny_list_get_length (not_opened_headers) > 1) {
1111                         modest_mail_operation_get_msgs_full (mail_op, 
1112                                                              not_opened_headers, 
1113                                                              open_msg_cb, 
1114                                                              NULL, 
1115                                                              NULL);
1116                 } else {
1117                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
1118                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1119                         modest_mail_operation_get_msg (mail_op, header, open_msg_cb, NULL);
1120                         g_object_unref (header);
1121                         g_object_unref (iter);
1122                 }
1123                 g_object_unref (mail_op);
1124         }
1125
1126         /* Clean */
1127         if (not_opened_headers != NULL)
1128                 g_object_unref (not_opened_headers);
1129 }
1130
1131 void
1132 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1133 {
1134         TnyList *headers;
1135
1136         /* Get headers */
1137         headers = get_selected_headers (win);
1138         if (!headers)
1139                 return;
1140
1141         /* Open them */
1142         _modest_ui_actions_open (headers, win);
1143
1144         g_object_unref(headers);
1145 }
1146
1147
1148 static void
1149 free_reply_forward_helper (gpointer data)
1150 {
1151         ReplyForwardHelper *helper;
1152
1153         helper = (ReplyForwardHelper *) data;
1154         g_free (helper->account_name);
1155         g_slice_free (ReplyForwardHelper, helper);
1156 }
1157
1158 static void
1159 reply_forward_cb (ModestMailOperation *mail_op,  TnyHeader *header, TnyMsg *msg,
1160                   gpointer user_data)
1161 {
1162         TnyMsg *new_msg;
1163         ReplyForwardHelper *rf_helper;
1164         ModestWindow *msg_win = NULL;
1165         ModestEditType edit_type;
1166         gchar *from = NULL;
1167         TnyAccount *account = NULL;
1168         ModestWindowMgr *mgr = NULL;
1169         gchar *signature = NULL;
1170
1171         /* If there was any error. The mail operation could be NULL,
1172            this means that we already have the message downloaded and
1173            that we didn't do a mail operation to retrieve it */
1174         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1175                 return;
1176                         
1177         g_return_if_fail (user_data != NULL);
1178         rf_helper = (ReplyForwardHelper *) user_data;
1179
1180         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1181                                                    rf_helper->account_name);
1182         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1183                                          rf_helper->account_name,
1184                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1185                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1186                                                            rf_helper->account_name,
1187                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1188         }
1189
1190         /* Create reply mail */
1191         switch (rf_helper->action) {
1192         case ACTION_REPLY:
1193                 new_msg = 
1194                         modest_tny_msg_create_reply_msg (msg, header, from, signature,
1195                                                          rf_helper->reply_forward_type,
1196                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1197                 break;
1198         case ACTION_REPLY_TO_ALL:
1199                 new_msg = 
1200                         modest_tny_msg_create_reply_msg (msg, header, from, signature, rf_helper->reply_forward_type,
1201                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1202                 edit_type = MODEST_EDIT_TYPE_REPLY;
1203                 break;
1204         case ACTION_FORWARD:
1205                 new_msg = 
1206                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1207                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1208                 break;
1209         default:
1210                 g_return_if_reached ();
1211                 return;
1212         }
1213
1214         g_free (signature);
1215
1216         if (!new_msg) {
1217                 g_printerr ("modest: failed to create message\n");
1218                 goto cleanup;
1219         }
1220
1221         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1222                                                                        rf_helper->account_name,
1223                                                                        TNY_ACCOUNT_TYPE_STORE);
1224         if (!account) {
1225                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1226                 goto cleanup;
1227         }
1228
1229         /* Create and register the windows */
1230         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1231         mgr = modest_runtime_get_window_mgr ();
1232         modest_window_mgr_register_window (mgr, msg_win);
1233
1234         if (rf_helper->parent_window != NULL) {
1235                 gdouble parent_zoom;
1236
1237                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1238                 modest_window_set_zoom (msg_win, parent_zoom);
1239         }
1240
1241         /* Show edit window */
1242         gtk_widget_show_all (GTK_WIDGET (msg_win));
1243
1244 cleanup:
1245         if (msg_win)
1246                 g_object_unref (msg_win);
1247         if (new_msg)
1248                 g_object_unref (G_OBJECT (new_msg));
1249         if (account)
1250                 g_object_unref (G_OBJECT (account));
1251 /*      g_object_unref (msg); */
1252         free_reply_forward_helper (rf_helper);
1253 }
1254
1255 /* Checks a list of headers. If any of them are not currently
1256  * downloaded (CACHED) then returns TRUE else returns FALSE.
1257  */
1258 static gint
1259 header_list_count_uncached_msgs (TnyList *header_list)
1260 {
1261         TnyIterator *iter;
1262         gint uncached_messages = 0;
1263
1264         iter = tny_list_create_iterator (header_list);
1265         while (!tny_iterator_is_done (iter)) {
1266                 TnyHeader *header;
1267
1268                 header = TNY_HEADER (tny_iterator_get_current (iter));
1269                 if (header) {
1270                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1271                                 uncached_messages ++;
1272                         g_object_unref (header);
1273                 }
1274
1275                 tny_iterator_next (iter);
1276         }
1277         g_object_unref (iter);
1278
1279         return uncached_messages;
1280 }
1281
1282 /* Returns FALSE if the user does not want to download the
1283  * messages. Returns TRUE if the user allowed the download.
1284  */
1285 static gboolean
1286 connect_to_get_msg (GtkWindow *win,
1287                     gint num_of_uncached_msgs)
1288 {
1289         /* Allways download if we are online. */
1290         if (tny_device_is_online (modest_runtime_get_device ()))
1291                 return TRUE;
1292
1293         /* If offline, then ask for user permission to download the messages */
1294         GtkResponseType response;
1295         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1296                         ngettext("mcen_nc_get_msg",
1297                         "mcen_nc_get_msgs",
1298                         num_of_uncached_msgs));
1299         if (response == GTK_RESPONSE_CANCEL)
1300                 return FALSE;
1301
1302         return modest_platform_connect_and_wait(win, NULL);     
1303 }
1304
1305 /*
1306  * Common code for the reply and forward actions
1307  */
1308 static void
1309 reply_forward (ReplyForwardAction action, ModestWindow *win)
1310 {
1311         ModestMailOperation *mail_op = NULL;
1312         TnyList *header_list = NULL;
1313         ReplyForwardHelper *rf_helper = NULL;
1314         guint reply_forward_type;
1315         gboolean continue_download = TRUE;
1316         gboolean do_retrieve = TRUE;
1317         
1318         g_return_if_fail (MODEST_IS_WINDOW(win));
1319
1320         /* we need an account when editing */
1321         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1322                 const gboolean created = modest_run_account_setup_wizard (win);
1323                 if (!created)
1324                         return;
1325         }
1326         
1327         header_list = get_selected_headers (win);
1328         if (!header_list)
1329                 return;
1330
1331         reply_forward_type = 
1332                 modest_conf_get_int (modest_runtime_get_conf (),
1333                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1334                                      NULL);
1335
1336         /* check if we need to download msg before asking about it */
1337         do_retrieve = (action == ACTION_FORWARD) ||
1338                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1339
1340         if (do_retrieve){
1341                 gint num_of_unc_msgs;
1342                 /* check that the messages have been previously downloaded */
1343                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
1344                 /* If there are any uncached message ask the user
1345                  * whether he/she wants to download them. */
1346                 if (num_of_unc_msgs)
1347                         continue_download = connect_to_get_msg (
1348                                                                 GTK_WINDOW (win),
1349                                                                 num_of_unc_msgs);
1350         }
1351
1352         if (!continue_download) {
1353                 g_object_unref (header_list);
1354                 return;
1355         }
1356         
1357         /* We assume that we can only select messages of the
1358            same folder and that we reply all of them from the
1359            same account. In fact the interface currently only
1360            allows single selection */
1361         
1362         /* Fill helpers */
1363         rf_helper = g_slice_new0 (ReplyForwardHelper);
1364         rf_helper->reply_forward_type = reply_forward_type;
1365         rf_helper->action = action;
1366         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1367         
1368         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1369                 rf_helper->parent_window = GTK_WIDGET (win);
1370         if (!rf_helper->account_name)
1371                 rf_helper->account_name =
1372                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1373
1374         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1375                 TnyMsg *msg;
1376                 TnyHeader *header;
1377                 /* Get header and message. Do not free them here, the
1378                    reply_forward_cb must do it */
1379                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1380                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1381                 if (!msg || !header) {
1382                         if (msg)
1383                                 g_object_unref (msg);
1384                         g_printerr ("modest: no message found\n");
1385                         return;
1386                 } else {
1387                         reply_forward_cb (NULL, header, msg, rf_helper);
1388                 }
1389                 if (header)
1390                         g_object_unref (header);
1391         } else {
1392                 TnyHeader *header;
1393                 TnyIterator *iter;
1394
1395                 /* Only reply/forward to one message */
1396                 iter = tny_list_create_iterator (header_list);
1397                 header = TNY_HEADER (tny_iterator_get_current (iter));
1398                 g_object_unref (iter);
1399
1400                 if (header) {
1401                         /* Retrieve messages */
1402                         if (do_retrieve) {
1403                                 mail_op = modest_mail_operation_new_with_error_handling (
1404                                         MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1405                                         G_OBJECT(win),
1406                                         modest_ui_actions_get_msgs_full_error_handler, 
1407                                         NULL);
1408                                 modest_mail_operation_queue_add (
1409                                         modest_runtime_get_mail_operation_queue (), mail_op);
1410                                 
1411                                 modest_mail_operation_get_msg (mail_op,
1412                                                                header,
1413                                                                reply_forward_cb,
1414                                                                rf_helper);
1415                                 /* Clean */
1416                                 g_object_unref(mail_op);
1417                         } else {
1418                                 /* we put a ref here to prevent double unref as the reply
1419                                  * forward callback unrefs the header at its end */
1420                                 reply_forward_cb (NULL, header, NULL, rf_helper);
1421                         }
1422
1423
1424                         g_object_unref (header);
1425                 }
1426
1427         }
1428
1429         /* Free */
1430         g_object_unref (header_list);
1431 }
1432
1433 void
1434 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1435 {
1436         g_return_if_fail (MODEST_IS_WINDOW(win));
1437
1438         reply_forward (ACTION_REPLY, win);
1439 }
1440
1441 void
1442 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1443 {
1444         g_return_if_fail (MODEST_IS_WINDOW(win));
1445
1446         reply_forward (ACTION_FORWARD, win);
1447 }
1448
1449 void
1450 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1451 {
1452         g_return_if_fail (MODEST_IS_WINDOW(win));
1453
1454         reply_forward (ACTION_REPLY_TO_ALL, win);
1455 }
1456
1457 void 
1458 modest_ui_actions_on_next (GtkAction *action, 
1459                            ModestWindow *window)
1460 {
1461         if (MODEST_IS_MAIN_WINDOW (window)) {
1462                 GtkWidget *header_view;
1463
1464                 header_view = modest_main_window_get_child_widget (
1465                                 MODEST_MAIN_WINDOW(window),
1466                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1467                 if (!header_view)
1468                         return;
1469         
1470                 modest_header_view_select_next (
1471                                 MODEST_HEADER_VIEW(header_view)); 
1472         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1473                 modest_msg_view_window_select_next_message (
1474                                 MODEST_MSG_VIEW_WINDOW (window));
1475         } else {
1476                 g_return_if_reached ();
1477         }
1478 }
1479
1480 void 
1481 modest_ui_actions_on_prev (GtkAction *action, 
1482                            ModestWindow *window)
1483 {
1484         g_return_if_fail (MODEST_IS_WINDOW(window));
1485
1486         if (MODEST_IS_MAIN_WINDOW (window)) {
1487                 GtkWidget *header_view;
1488                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1489                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1490                 if (!header_view)
1491                         return;
1492                 
1493                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1494         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1495                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1496         } else {
1497                 g_return_if_reached ();
1498         }
1499 }
1500
1501 void 
1502 modest_ui_actions_on_sort (GtkAction *action, 
1503                            ModestWindow *window)
1504 {
1505         g_return_if_fail (MODEST_IS_WINDOW(window));
1506
1507         if (MODEST_IS_MAIN_WINDOW (window)) {
1508                 GtkWidget *header_view;
1509                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1510                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1511                 if (!header_view) {
1512                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1513
1514                         return;
1515                 }
1516
1517                 /* Show sorting dialog */
1518                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1519         }
1520 }
1521
1522 static void
1523 new_messages_arrived (ModestMailOperation *self, 
1524                       TnyList *new_headers,
1525                       gpointer user_data)
1526 {
1527         ModestMainWindow *win = NULL;
1528         GtkWidget *folder_view = NULL;
1529         TnyFolderStore *folder = NULL;
1530         gboolean folder_empty = FALSE;
1531
1532         g_return_if_fail (MODEST_IS_MAIN_WINDOW (user_data));
1533         win = MODEST_MAIN_WINDOW (user_data);
1534
1535         /* Don't do anything if there are not new headers, this could
1536            happen if there was any problem with the mail operation */
1537         if (!new_headers)
1538                 return;
1539
1540         /* Set contents style of headers view */
1541         if (modest_main_window_get_contents_style (win) == MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY) {
1542                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1543                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1544                 folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));             
1545                 
1546
1547                 folder_empty = (tny_folder_get_all_count (TNY_FOLDER (folder)) == 0);
1548                 
1549                 if (!folder_empty)
1550                         modest_main_window_set_contents_style (win,
1551                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1552         }       
1553
1554         /* Notify new messages have been downloaded */
1555         if ((new_headers != NULL) && (tny_list_get_length (new_headers) > 0)) {
1556                 TnyIterator *iter = tny_list_create_iterator (new_headers);
1557                 do {
1558                         TnyHeader *header =  NULL;
1559
1560                         header = TNY_HEADER (tny_iterator_get_current (iter));
1561                         modest_platform_on_new_header_received (header);
1562                         g_object_unref (header);
1563
1564                         tny_iterator_next (iter);
1565                 } while (!tny_iterator_is_done (iter));
1566                 g_object_unref (iter);
1567         }
1568 }
1569
1570 /*
1571  * This function performs the send & receive required actions. The
1572  * window is used to create the mail operation. Typically it should
1573  * always be the main window, but we pass it as argument in order to
1574  * be more flexible.
1575  */
1576 void
1577 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1578 {
1579         gchar *acc_name = NULL;
1580         ModestMailOperation *mail_op;
1581         TnyAccount *store_account = NULL;
1582
1583         /* If no account name was provided then get the current account, and if
1584            there is no current account then pick the default one: */
1585         if (!account_name) {
1586                 acc_name = g_strdup (modest_window_get_active_account(win));
1587                 if (!acc_name)
1588                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1589                 if (!acc_name) {
1590                         g_printerr ("modest: cannot get default account\n");
1591                         return;
1592                 }
1593         } else {
1594                 acc_name = g_strdup (account_name);
1595         }
1596
1597
1598         /* Ensure that we have a connection available */
1599         store_account =
1600                 modest_tny_account_store_get_server_account (modest_runtime_get_account_store (),
1601                                                              acc_name,
1602                                                              TNY_ACCOUNT_TYPE_STORE);
1603         if (!modest_platform_connect_and_wait (NULL, TNY_ACCOUNT (store_account))) {
1604                 g_object_unref (store_account);
1605                 return;
1606         }
1607         g_object_unref (store_account);
1608
1609         /* Set send/receive operation in progress */    
1610         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1611
1612         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1613                                                                  G_OBJECT (win),
1614                                                                  modest_ui_actions_send_receive_error_handler,
1615                                                                  NULL);
1616
1617         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1618                           G_CALLBACK (_on_send_receive_progress_changed), 
1619                           win);
1620
1621         /* Send & receive. */
1622         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1623         /* Receive and then send. The operation is tagged initially as
1624            a receive operation because the account update performs a
1625            receive and then a send. The operation changes its type
1626            internally, so the progress objects will receive the proper
1627            progress information */
1628         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1629         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, win);
1630         g_object_unref (G_OBJECT (mail_op));
1631         
1632         /* Free */
1633         g_free (acc_name);
1634 }
1635
1636
1637 static void
1638 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1639                                   ModestWindow *win)
1640 {
1641         TnyTransportAccount *transport_account;
1642         TnySendQueue *send_queue = NULL;
1643         GError *error = NULL;
1644
1645         /* Get transport account */
1646         transport_account =
1647                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1648                                       (modest_runtime_get_account_store(),
1649                                        account_name,
1650                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1651         if (!transport_account) {
1652                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1653                 goto frees;
1654         }
1655
1656         /* Get send queue*/
1657         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1658         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1659                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1660                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1661                              "modest: could not find send queue for account\n");
1662         } else {
1663                 /* Keeep messages in outbox folder */
1664                 tny_send_queue_cancel (send_queue, FALSE, &error);
1665         }       
1666
1667  frees:
1668         if (transport_account != NULL) 
1669                 g_object_unref (G_OBJECT (transport_account));
1670 }
1671
1672 static void
1673 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1674 {
1675         GSList *account_names, *iter;
1676
1677         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1678                                                           TRUE);
1679
1680         iter = account_names;
1681         while (iter) {                  
1682                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1683                 iter = g_slist_next (iter);
1684         }
1685
1686         modest_account_mgr_free_account_names (account_names);
1687         account_names = NULL;
1688 }
1689
1690 void
1691 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1692
1693 {
1694         /* Check if accounts exist */
1695         gboolean accounts_exist = 
1696                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1697         
1698         /* If not, allow the user to create an account before trying to send/receive. */
1699         if (!accounts_exist)
1700                 modest_ui_actions_on_accounts (NULL, win);
1701         
1702         /* Cancel all sending operaitons */     
1703         modest_ui_actions_cancel_send_all (win);
1704 }
1705
1706 /*
1707  * Refreshes all accounts. This function will be used by automatic
1708  * updates
1709  */
1710 void
1711 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1712 {
1713         GSList *account_names, *iter;
1714
1715         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1716                                                           TRUE);
1717
1718         iter = account_names;
1719         while (iter) {                  
1720                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1721                 iter = g_slist_next (iter);
1722         }
1723
1724         modest_account_mgr_free_account_names (account_names);
1725         account_names = NULL;
1726 }
1727
1728 void 
1729 modest_do_refresh_current_folder(ModestWindow *win)
1730 {
1731         /* Refresh currently selected folder. Note that if we only
1732            want to retreive the headers, then the refresh only will
1733            invoke a poke_status over all folders, i.e., only the
1734            total/unread count will be updated */
1735         if (MODEST_IS_MAIN_WINDOW (win)) {
1736                 GtkWidget *header_view, *folder_view;
1737                 TnyFolderStore *folder_store;
1738
1739                 /* Get folder and header view */
1740                 folder_view = 
1741                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1742                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1743                 if (!folder_view)
1744                         return;
1745
1746                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1747
1748                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1749                         header_view = 
1750                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1751                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1752                 
1753                         /* We do not need to set the contents style
1754                            because it hasn't changed. We also do not
1755                            need to save the widget status. Just force
1756                            a refresh */
1757                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1758                                                        TNY_FOLDER (folder_store),
1759                                                        folder_refreshed_cb,
1760                                                        MODEST_MAIN_WINDOW (win));
1761                 }
1762                 
1763                 if (folder_store)
1764                         g_object_unref (folder_store);
1765         }
1766 }
1767
1768
1769 /*
1770  * Handler of the click on Send&Receive button in the main toolbar
1771  */
1772 void
1773 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
1774 {
1775         /* Check if accounts exist */
1776         gboolean accounts_exist = 
1777                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1778         
1779         /* If not, allow the user to create an account before trying to send/receive. */
1780         if (!accounts_exist)
1781                 modest_ui_actions_on_accounts (NULL, win);
1782
1783         modest_do_refresh_current_folder (win);
1784         
1785         /* Refresh the active account */
1786         modest_ui_actions_do_send_receive (NULL, win);
1787 }
1788
1789
1790 void
1791 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1792 {
1793         ModestConf *conf;
1794         GtkWidget *header_view;
1795         
1796         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1797
1798         header_view = modest_main_window_get_child_widget (main_window,
1799                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1800         if (!header_view)
1801                 return;
1802
1803         conf = modest_runtime_get_conf ();
1804         
1805         /* what is saved/restored is depending on the style; thus; we save with
1806          * old style, then update the style, and restore for this new style
1807          */
1808         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1809         
1810         if (modest_header_view_get_style
1811             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1812                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1813                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1814         else
1815                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1816                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1817
1818         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1819                                       MODEST_CONF_HEADER_VIEW_KEY);
1820 }
1821
1822
1823 void 
1824 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1825                                       TnyHeader *header,
1826                                       ModestMainWindow *main_window)
1827 {
1828         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1829         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1830         
1831         /* in the case the folder is empty, show the empty folder message and focus
1832          * folder view */
1833         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
1834                 if (modest_header_view_is_empty (header_view)) {
1835                         TnyFolder *folder = modest_header_view_get_folder (header_view);
1836                         GtkWidget *folder_view = 
1837                                 modest_main_window_get_child_widget (main_window,
1838                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
1839                         if (folder != NULL) 
1840                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
1841                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
1842                         return;
1843                 }
1844         }
1845         /* If no header has been selected then exit */
1846         if (!header)
1847                 return;
1848
1849         /* Update focus */
1850         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1851             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1852
1853         /* Update toolbar dimming state */
1854         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1855 }
1856
1857 void
1858 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1859                                        TnyHeader *header,
1860                                        ModestMainWindow *main_window)
1861 {
1862         TnyList *headers;
1863
1864         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1865         
1866         if (!header)
1867                 return;
1868
1869
1870 /*      headers = tny_simple_list_new (); */
1871 /*      tny_list_prepend (headers, G_OBJECT (header)); */
1872         headers = modest_header_view_get_selected_headers (header_view);
1873
1874         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1875
1876         g_object_unref (headers);
1877 }
1878
1879 static void
1880 set_active_account_from_tny_account (TnyAccount *account,
1881                                      ModestWindow *window)
1882 {
1883         const gchar *server_acc_name = tny_account_get_id (account);
1884         
1885         /* We need the TnyAccount provided by the
1886            account store because that is the one that
1887            knows the name of the Modest account */
1888         TnyAccount *modest_server_account = modest_server_account = 
1889                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1890                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1891                                                              server_acc_name);
1892         if (!modest_server_account) {
1893                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
1894                 return;
1895         }
1896
1897         /* Update active account, but only if it's not a pseudo-account */
1898         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
1899             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
1900                 const gchar *modest_acc_name = 
1901                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1902                 if (modest_acc_name)
1903                         modest_window_set_active_account (window, modest_acc_name);
1904         }
1905         
1906         g_object_unref (modest_server_account);
1907 }
1908
1909
1910 static void
1911 folder_refreshed_cb (ModestMailOperation *mail_op, 
1912                      TnyFolder *folder, 
1913                      gpointer user_data)
1914 {
1915         ModestMainWindow *win = NULL;
1916         GtkWidget *header_view;
1917         gboolean folder_empty = FALSE;
1918         gboolean all_marked_as_deleted = FALSE;
1919
1920         g_return_if_fail (TNY_IS_FOLDER (folder));
1921
1922         win = MODEST_MAIN_WINDOW (user_data);
1923         header_view = 
1924                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1925
1926         if (header_view) {
1927                 TnyFolder *current_folder;
1928
1929                 current_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
1930                 if (current_folder != NULL && folder != current_folder) {
1931                         g_object_unref (current_folder);
1932                         return;
1933                 }
1934                 g_object_unref (current_folder);
1935         }
1936
1937         /* Check if folder is empty and set headers view contents style */
1938         folder_empty = (tny_folder_get_all_count (folder) == 0);
1939         all_marked_as_deleted = modest_header_view_is_empty (MODEST_HEADER_VIEW(header_view));
1940         if (folder_empty || all_marked_as_deleted)
1941                 modest_main_window_set_contents_style (win,
1942                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1943 }
1944
1945 void 
1946 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1947                                                TnyFolderStore *folder_store, 
1948                                                gboolean selected,
1949                                                ModestMainWindow *main_window)
1950 {
1951         ModestConf *conf;
1952         GtkWidget *header_view;
1953
1954         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1955
1956         header_view = modest_main_window_get_child_widget(main_window,
1957                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1958         if (!header_view)
1959                 return;
1960         
1961         conf = modest_runtime_get_conf ();
1962
1963         if (TNY_IS_ACCOUNT (folder_store)) {
1964                 if (selected) {
1965                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1966                         
1967                         /* Show account details */
1968                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1969                 }
1970         } else {
1971                 if (TNY_IS_FOLDER (folder_store) && selected) {
1972                         
1973                         /* Update the active account */
1974                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1975                         if (account) {
1976                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1977                                 g_object_unref (account);
1978                                 account = NULL;
1979                         }
1980
1981                         /* Set the header style by default, it could
1982                            be changed later by the refresh callback to
1983                            empty */
1984                         modest_main_window_set_contents_style (main_window, 
1985                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1986
1987                         /* Set folder on header view. This function
1988                            will call tny_folder_refresh_async so we
1989                            pass a callback that will be called when
1990                            finished. We use that callback to set the
1991                            empty view if there are no messages */
1992                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1993                                                        TNY_FOLDER (folder_store),
1994                                                        folder_refreshed_cb,
1995                                                        main_window);
1996                         
1997                         /* Restore configuration. We need to do this
1998                            *after* the set_folder because the widget
1999                            memory asks the header view about its
2000                            folder  */
2001                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2002                                                       G_OBJECT(header_view),
2003                                                       MODEST_CONF_HEADER_VIEW_KEY);
2004                 } else {
2005                         /* Update the active account */
2006                         //modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
2007                         /* Save only if we're seeing headers */
2008                         if (modest_main_window_get_contents_style (main_window) ==
2009                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2010                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2011                                                            MODEST_CONF_HEADER_VIEW_KEY);
2012                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2013                 }
2014         }
2015
2016         /* Update toolbar dimming state */
2017         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2018 }
2019
2020 void 
2021 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2022                                      ModestWindow *win)
2023 {
2024         GtkWidget *dialog;
2025         gchar *txt, *item;
2026         gboolean online;
2027
2028         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2029         
2030         online = tny_device_is_online (modest_runtime_get_device());
2031
2032         if (online) {
2033                 /* already online -- the item is simply not there... */
2034                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2035                                                  GTK_DIALOG_MODAL,
2036                                                  GTK_MESSAGE_WARNING,
2037                                                  GTK_BUTTONS_NONE,
2038                                                  _("The %s you selected cannot be found"),
2039                                                  item);
2040                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2041                 gtk_dialog_run (GTK_DIALOG(dialog));
2042         } else {
2043                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2044                                                       GTK_WINDOW (win),
2045                                                       GTK_DIALOG_MODAL,
2046                                                       _("mcen_bd_dialog_cancel"),
2047                                                       GTK_RESPONSE_REJECT,
2048                                                       _("mcen_bd_dialog_ok"),
2049                                                       GTK_RESPONSE_ACCEPT,
2050                                                       NULL);
2051                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2052                                          "Do you want to get online?"), item);
2053                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2054                                     gtk_label_new (txt), FALSE, FALSE, 0);
2055                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2056                 g_free (txt);
2057
2058                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2059                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2060                         /* TODO: Comment about why is this commented out: */
2061                         /* modest_platform_connect_and_wait (); */
2062                 }
2063         }
2064         gtk_widget_destroy (dialog);
2065 }
2066
2067 void
2068 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2069                                      ModestWindow *win)
2070 {
2071         /* g_message ("%s %s", __FUNCTION__, link); */
2072 }       
2073
2074
2075 void
2076 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2077                                         ModestWindow *win)
2078 {
2079         modest_platform_activate_uri (link);
2080 }
2081
2082 void
2083 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2084                                           ModestWindow *win)
2085 {
2086         modest_platform_show_uri_popup (link);
2087 }
2088
2089 void
2090 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2091                                              ModestWindow *win)
2092 {
2093         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2094 }
2095
2096 void
2097 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2098                                           const gchar *address,
2099                                           ModestWindow *win)
2100 {
2101         /* g_message ("%s %s", __FUNCTION__, address); */
2102 }
2103
2104 void
2105 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2106 {
2107         TnyTransportAccount *transport_account;
2108         ModestMailOperation *mail_operation;
2109         MsgData *data;
2110         gchar *account_name, *from;
2111         ModestAccountMgr *account_mgr;
2112         gchar *info_text = NULL;
2113
2114         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2115         
2116         data = modest_msg_edit_window_get_msg_data (edit_window);
2117
2118         account_mgr = modest_runtime_get_account_mgr();
2119         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2120         if (!account_name) 
2121                 account_name = modest_account_mgr_get_default_account (account_mgr);
2122         if (!account_name) {
2123                 g_printerr ("modest: no account found\n");
2124                 modest_msg_edit_window_free_msg_data (edit_window, data);
2125                 return;
2126         }
2127
2128         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2129                 account_name = g_strdup (data->account_name);
2130         }
2131
2132         transport_account =
2133                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2134                                       (modest_runtime_get_account_store(),
2135                                        account_name,
2136                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2137         if (!transport_account) {
2138                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2139                 g_free (account_name);
2140                 modest_msg_edit_window_free_msg_data (edit_window, data);
2141                 return;
2142         }
2143         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2144
2145         /* Create the mail operation */         
2146         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
2147         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2148
2149         modest_mail_operation_save_to_drafts (mail_operation,
2150                                               transport_account,
2151                                               data->draft_msg,
2152                                               edit_window,
2153                                               from,
2154                                               data->to, 
2155                                               data->cc, 
2156                                               data->bcc,
2157                                               data->subject, 
2158                                               data->plain_body, 
2159                                               data->html_body,
2160                                               data->attachments,
2161                                               data->priority_flags);
2162         /* Frees */
2163         g_free (from);
2164         g_free (account_name);
2165         g_object_unref (G_OBJECT (transport_account));
2166         g_object_unref (G_OBJECT (mail_operation));
2167
2168         modest_msg_edit_window_free_msg_data (edit_window, data);
2169
2170         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2171         modest_platform_information_banner (NULL, NULL, info_text);
2172         g_free (info_text);
2173 }
2174
2175 /* For instance, when clicking the Send toolbar button when editing a message: */
2176 void
2177 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2178 {
2179         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
2180
2181         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2182                 return;
2183         
2184         /* Offer the connection dialog, if necessary: */        
2185         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
2186                 return;
2187         
2188         /* FIXME: Code added just for testing. The final version will
2189            use the send queue provided by tinymail and some
2190            classifier */
2191         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2192         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2193         if (!account_name) 
2194                 account_name = modest_account_mgr_get_default_account (account_mgr);
2195                 
2196         if (!account_name) {
2197                 /* Run account setup wizard */
2198                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2199                 if (!created)
2200                         return;
2201         }
2202         
2203         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2204
2205         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2206                 account_name = g_strdup (data->account_name);
2207         }
2208         
2209         /* Get the currently-active transport account for this modest account: */
2210         TnyTransportAccount *transport_account =
2211                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
2212                                       (modest_runtime_get_account_store(),
2213                                        account_name));
2214         if (!transport_account) {
2215                 /* Run account setup wizard */
2216                 const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window));
2217                 if (!created)
2218                         return;
2219         }
2220         
2221         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2222
2223         /* Create the mail operation */
2224         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2225         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2226
2227         modest_mail_operation_send_new_mail (mail_operation,
2228                                              transport_account,
2229                                              data->draft_msg,
2230                                              from,
2231                                              data->to, 
2232                                              data->cc, 
2233                                              data->bcc,
2234                                              data->subject, 
2235                                              data->plain_body, 
2236                                              data->html_body,
2237                                              data->attachments,
2238                                              data->priority_flags);
2239                                              
2240         /* Free data: */
2241         g_free (from);
2242         g_free (account_name);
2243         g_object_unref (G_OBJECT (transport_account));
2244         g_object_unref (G_OBJECT (mail_operation));
2245
2246         modest_msg_edit_window_free_msg_data (edit_window, data);
2247         modest_msg_edit_window_set_sent (edit_window, TRUE);
2248
2249         /* Save settings and close the window: */
2250         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2251 }
2252
2253 void 
2254 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2255                                   ModestMsgEditWindow *window)
2256 {
2257         ModestMsgEditFormatState *format_state = NULL;
2258
2259         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2260         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2261
2262         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2263                 return;
2264
2265         format_state = modest_msg_edit_window_get_format_state (window);
2266         g_return_if_fail (format_state != NULL);
2267
2268         format_state->bold = gtk_toggle_action_get_active (action);
2269         modest_msg_edit_window_set_format_state (window, format_state);
2270         g_free (format_state);
2271         
2272 }
2273
2274 void 
2275 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2276                                      ModestMsgEditWindow *window)
2277 {
2278         ModestMsgEditFormatState *format_state = NULL;
2279
2280         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2281         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2282
2283         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2284                 return;
2285
2286         format_state = modest_msg_edit_window_get_format_state (window);
2287         g_return_if_fail (format_state != NULL);
2288
2289         format_state->italics = gtk_toggle_action_get_active (action);
2290         modest_msg_edit_window_set_format_state (window, format_state);
2291         g_free (format_state);
2292         
2293 }
2294
2295 void 
2296 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2297                                      ModestMsgEditWindow *window)
2298 {
2299         ModestMsgEditFormatState *format_state = NULL;
2300
2301         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2302         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2303
2304         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2305                 return;
2306
2307         format_state = modest_msg_edit_window_get_format_state (window);
2308         g_return_if_fail (format_state != NULL);
2309
2310         format_state->bullet = gtk_toggle_action_get_active (action);
2311         modest_msg_edit_window_set_format_state (window, format_state);
2312         g_free (format_state);
2313         
2314 }
2315
2316 void 
2317 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2318                                      GtkRadioAction *selected,
2319                                      ModestMsgEditWindow *window)
2320 {
2321         ModestMsgEditFormatState *format_state = NULL;
2322         GtkJustification value;
2323
2324         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2325
2326         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2327                 return;
2328
2329         value = gtk_radio_action_get_current_value (selected);
2330
2331         format_state = modest_msg_edit_window_get_format_state (window);
2332         g_return_if_fail (format_state != NULL);
2333
2334         format_state->justification = value;
2335         modest_msg_edit_window_set_format_state (window, format_state);
2336         g_free (format_state);
2337 }
2338
2339 void 
2340 modest_ui_actions_on_select_editor_color (GtkAction *action,
2341                                           ModestMsgEditWindow *window)
2342 {
2343         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2344         g_return_if_fail (GTK_IS_ACTION (action));
2345
2346         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2347                 return;
2348
2349         modest_msg_edit_window_select_color (window);
2350 }
2351
2352 void 
2353 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2354                                                      ModestMsgEditWindow *window)
2355 {
2356         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2357         g_return_if_fail (GTK_IS_ACTION (action));
2358
2359         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2360                 return;
2361
2362         modest_msg_edit_window_select_background_color (window);
2363 }
2364
2365 void 
2366 modest_ui_actions_on_insert_image (GtkAction *action,
2367                                    ModestMsgEditWindow *window)
2368 {
2369         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2370         g_return_if_fail (GTK_IS_ACTION (action));
2371
2372         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2373                 return;
2374
2375         modest_msg_edit_window_insert_image (window);
2376 }
2377
2378 void 
2379 modest_ui_actions_on_attach_file (GtkAction *action,
2380                                   ModestMsgEditWindow *window)
2381 {
2382         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2383         g_return_if_fail (GTK_IS_ACTION (action));
2384
2385         modest_msg_edit_window_offer_attach_file (window);
2386 }
2387
2388 void 
2389 modest_ui_actions_on_remove_attachments (GtkAction *action,
2390                                          ModestMsgEditWindow *window)
2391 {
2392         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2393         g_return_if_fail (GTK_IS_ACTION (action));
2394
2395         modest_msg_edit_window_remove_attachments (window, NULL);
2396 }
2397
2398 static void
2399 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2400                                             gpointer user_data)
2401 {
2402         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2403         const GError *error = modest_mail_operation_get_error (mail_op);
2404
2405         if(error)
2406         {
2407                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2408                                                     modest_mail_operation_get_error (mail_op)->message);
2409         }
2410 }
2411
2412 static void
2413 modest_ui_actions_create_folder(GtkWidget *parent_window,
2414                                 GtkWidget *folder_view)
2415 {
2416         TnyFolderStore *parent_folder;
2417
2418         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2419         
2420         if (parent_folder) {
2421                 gboolean finished = FALSE;
2422                 gint result;
2423                 gchar *folder_name = NULL, *suggested_name = NULL;
2424                 const gchar *proto_str = NULL;
2425                 TnyAccount *account;
2426
2427                 if (TNY_IS_ACCOUNT (parent_folder))
2428                         account = g_object_ref (parent_folder);
2429                 else
2430                         account = tny_folder_get_account (TNY_FOLDER (parent_folder));
2431                 proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2432
2433                 if (proto_str && modest_protocol_info_get_transport_store_protocol (proto_str) ==
2434                     MODEST_PROTOCOL_STORE_POP) {
2435                         finished = TRUE;
2436                         hildon_banner_show_information (NULL, NULL, _("mail_in_ui_folder_create_error"));
2437                 }
2438                 g_object_unref (account);
2439
2440                 /* Run the new folder dialog */
2441                 while (!finished) {
2442                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2443                                                                         parent_folder,
2444                                                                         suggested_name,
2445                                                                         &folder_name);
2446
2447                         g_free (suggested_name);
2448                         suggested_name = NULL;
2449
2450                         if (result == GTK_RESPONSE_REJECT) {
2451                                 finished = TRUE;
2452                         } else {
2453                                 ModestMailOperation *mail_op;
2454                                 TnyFolder *new_folder = NULL;
2455
2456                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2457                                                                                           G_OBJECT(parent_window),
2458                                                                                           modest_ui_actions_new_folder_error_handler,
2459                                                                                           parent_window);
2460
2461                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2462                                                                  mail_op);
2463                                 new_folder = modest_mail_operation_create_folder (mail_op,
2464                                                                                   parent_folder,
2465                                                                                   (const gchar *) folder_name);
2466                                 if (new_folder) {
2467                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2468                                                                           new_folder, TRUE);
2469
2470                                         g_object_unref (new_folder);
2471                                         finished = TRUE;
2472                                 }
2473                                 g_object_unref (mail_op);
2474                         }
2475
2476                         suggested_name = folder_name;
2477                         folder_name = NULL;
2478                 }
2479
2480                 g_object_unref (parent_folder);
2481         }
2482 }
2483
2484 void 
2485 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2486 {
2487         GtkWidget *folder_view;
2488         
2489         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2490
2491         folder_view = modest_main_window_get_child_widget (main_window,
2492                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2493         if (!folder_view)
2494                 return;
2495
2496         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2497 }
2498
2499 static void
2500 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2501                                                gpointer user_data)
2502 {
2503         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2504         const GError *error = NULL;
2505         const gchar *message = NULL;
2506         
2507         /* Get error message */
2508         error = modest_mail_operation_get_error (mail_op);
2509         if (!error)
2510                 g_return_if_reached ();
2511
2512         switch (error->code) {
2513         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2514                 message = _CS("ckdg_ib_folder_already_exists");
2515                 break;
2516         default:
2517                 g_return_if_reached ();
2518         }
2519
2520         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2521 }
2522
2523 void 
2524 modest_ui_actions_on_rename_folder (GtkAction *action,
2525                                      ModestMainWindow *main_window)
2526 {
2527         TnyFolderStore *folder;
2528         GtkWidget *folder_view;
2529         GtkWidget *header_view; 
2530
2531         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2532
2533         folder_view = modest_main_window_get_child_widget (main_window,
2534                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2535         if (!folder_view)
2536                 return;
2537
2538         header_view = modest_main_window_get_child_widget (main_window,
2539                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2540         
2541         if (!header_view)
2542                 return;
2543
2544         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2545
2546         if (!folder)
2547                 return;
2548
2549         if (TNY_IS_FOLDER (folder)) {
2550                 gchar *folder_name;
2551                 gint response;
2552                 const gchar *current_name;
2553                 TnyFolderStore *parent;
2554                 gboolean do_rename = TRUE;
2555
2556                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2557                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2558                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2559                                                                      parent, current_name, 
2560                                                                      &folder_name);
2561                 g_object_unref (parent);
2562
2563                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2564                         do_rename = FALSE;
2565                 } else if (modest_platform_is_network_folderstore(folder) &&
2566                            !tny_device_is_online (modest_runtime_get_device())) {
2567                         TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2568                         do_rename = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2569                         g_object_unref(account);
2570                 }
2571
2572                 if (do_rename) {
2573                         ModestMailOperation *mail_op;
2574                         GtkTreeSelection *sel = NULL;
2575
2576                         mail_op = 
2577                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2578                                                                                G_OBJECT(main_window),
2579                                                                                modest_ui_actions_rename_folder_error_handler,
2580                                                                                main_window);
2581
2582                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2583                                                          mail_op);
2584
2585                         /* Clear the headers view */
2586                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2587                         gtk_tree_selection_unselect_all (sel);
2588
2589                         /* Select *after* the changes */
2590                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2591                                                           TNY_FOLDER(folder), TRUE);
2592
2593                         /* Actually rename the folder */
2594                         modest_mail_operation_rename_folder (mail_op,
2595                                                              TNY_FOLDER (folder),
2596                                                              (const gchar *) folder_name);
2597
2598                         g_object_unref (mail_op);
2599                         g_free (folder_name);
2600                 }
2601         }
2602         g_object_unref (folder);
2603 }
2604
2605 static void
2606 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2607                                                gpointer user_data)
2608 {
2609         GObject *win = modest_mail_operation_get_source (mail_op);
2610
2611         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2612                                                 _("mail_in_ui_folder_delete_error"));
2613         g_object_unref (win);
2614 }
2615
2616 static void
2617 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2618 {
2619         TnyFolderStore *folder;
2620         GtkWidget *folder_view;
2621         gint response;
2622         gchar *message;
2623         gboolean do_delete = TRUE;
2624
2625         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2626
2627         folder_view = modest_main_window_get_child_widget (main_window,
2628                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2629         if (!folder_view)
2630                 return;
2631
2632         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2633
2634         /* Show an error if it's an account */
2635         if (!TNY_IS_FOLDER (folder)) {
2636                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2637                                                         _("mail_in_ui_folder_delete_error"));
2638                 g_object_unref (G_OBJECT (folder));
2639                 return ;
2640         }
2641
2642         /* Ask the user */      
2643         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2644                                     tny_folder_get_name (TNY_FOLDER (folder)));
2645         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2646                                                             (const gchar *) message);
2647         g_free (message);
2648
2649         if (response != GTK_RESPONSE_OK) {
2650                 do_delete = FALSE;
2651         } else if (modest_platform_is_network_folderstore(folder) &&
2652                    !tny_device_is_online (modest_runtime_get_device())) {
2653                 TnyAccount *account = tny_folder_get_account(TNY_FOLDER(folder));
2654                 do_delete = modest_platform_connect_and_wait(GTK_WINDOW(main_window), account);
2655                 g_object_unref(account);
2656         }
2657
2658         if (do_delete) {
2659                 ModestMailOperation *mail_op;
2660                 GtkTreeSelection *sel;
2661
2662                 /* Unselect the folder before deleting it to free the headers */
2663                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2664                 gtk_tree_selection_unselect_all (sel);
2665
2666                 /* Create the mail operation */
2667                 mail_op =
2668                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2669                                                                        G_OBJECT(main_window),
2670                                                                        modest_ui_actions_delete_folder_error_handler,
2671                                                                        NULL);
2672
2673                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2674                                                  mail_op);
2675                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2676                 g_object_unref (G_OBJECT (mail_op));
2677         }
2678
2679         g_object_unref (G_OBJECT (folder));
2680 }
2681
2682 void 
2683 modest_ui_actions_on_delete_folder (GtkAction *action,
2684                                      ModestMainWindow *main_window)
2685 {
2686         GtkWidget *folder_view;
2687         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2688
2689         delete_folder (main_window, FALSE);
2690         folder_view = modest_main_window_get_child_widget (main_window,
2691                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2692         if (!folder_view)
2693                 return;
2694         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
2695 }
2696
2697 void 
2698 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2699 {
2700         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2701         
2702         delete_folder (main_window, TRUE);
2703 }
2704
2705
2706 static void
2707 show_error (GtkWidget *parent_widget, const gchar* text)
2708 {
2709         hildon_banner_show_information(parent_widget, NULL, text);
2710         
2711 #if 0
2712         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2713         /*
2714           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2715           (GtkDialogFlags)0,
2716           GTK_MESSAGE_ERROR,
2717           GTK_BUTTONS_OK,
2718           text ));
2719         */
2720                  
2721         gtk_dialog_run (dialog);
2722         gtk_widget_destroy (GTK_WIDGET (dialog));
2723 #endif
2724 }
2725
2726 void
2727 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2728                                          const gchar* server_account_name,
2729                                          gchar **username,
2730                                          gchar **password, 
2731                                          gboolean *cancel, 
2732                                          gboolean *remember,
2733                                          ModestMainWindow *main_window)
2734 {
2735         g_return_if_fail(server_account_name);
2736         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2737         
2738         /* Initalize output parameters: */
2739         if (cancel)
2740                 *cancel = FALSE;
2741                 
2742         if (remember)
2743                 *remember = TRUE;
2744                 
2745 #ifdef MODEST_PLATFORM_MAEMO
2746         /* Maemo uses a different (awkward) button order,
2747          * It should probably just use gtk_alternative_dialog_button_order ().
2748          */
2749         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2750                                               NULL,
2751                                               GTK_DIALOG_MODAL,
2752                                               _("mcen_bd_dialog_ok"),
2753                                               GTK_RESPONSE_ACCEPT,
2754                                               _("mcen_bd_dialog_cancel"),
2755                                               GTK_RESPONSE_REJECT,
2756                                               NULL);
2757 #else
2758         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2759                                               NULL,
2760                                               GTK_DIALOG_MODAL,
2761                                               GTK_STOCK_CANCEL,
2762                                               GTK_RESPONSE_REJECT,
2763                                               GTK_STOCK_OK,
2764                                               GTK_RESPONSE_ACCEPT,
2765                                               NULL);
2766 #endif /* MODEST_PLATFORM_MAEMO */
2767
2768         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2769         
2770         gchar *server_name = modest_server_account_get_hostname (
2771                 modest_runtime_get_account_mgr(), server_account_name);
2772         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2773                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2774                 *cancel = TRUE;
2775                 return;
2776         }
2777         
2778         /* This causes a warning because the logical ID has no %s in it, 
2779          * though the translation does, but there is not much we can do about that: */
2780         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2781         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2782                             FALSE, FALSE, 0);
2783         g_free (txt);
2784         g_free (server_name);
2785         server_name = NULL;
2786
2787         /* username: */
2788         gchar *initial_username = modest_server_account_get_username (
2789                 modest_runtime_get_account_mgr(), server_account_name);
2790         
2791         GtkWidget *entry_username = gtk_entry_new ();
2792         if (initial_username)
2793                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2794         /* Dim this if a connection has ever succeeded with this username,
2795          * as per the UI spec: */
2796         const gboolean username_known = 
2797                 modest_server_account_get_username_has_succeeded(
2798                         modest_runtime_get_account_mgr(), server_account_name);
2799         gtk_widget_set_sensitive (entry_username, !username_known);
2800         
2801 #ifdef MODEST_PLATFORM_MAEMO
2802         /* Auto-capitalization is the default, so let's turn it off: */
2803         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2804         
2805         /* Create a size group to be used by all captions.
2806          * Note that HildonCaption does not create a default size group if we do not specify one.
2807          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2808         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2809         
2810         GtkWidget *caption = hildon_caption_new (sizegroup, 
2811                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2812         gtk_widget_show (entry_username);
2813         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2814                 FALSE, FALSE, MODEST_MARGIN_HALF);
2815         gtk_widget_show (caption);
2816 #else 
2817         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2818                             TRUE, FALSE, 0);
2819 #endif /* MODEST_PLATFORM_MAEMO */      
2820                             
2821         /* password: */
2822         GtkWidget *entry_password = gtk_entry_new ();
2823         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2824         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2825         
2826 #ifdef MODEST_PLATFORM_MAEMO
2827         /* Auto-capitalization is the default, so let's turn it off: */
2828         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2829                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2830         
2831         caption = hildon_caption_new (sizegroup, 
2832                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2833         gtk_widget_show (entry_password);
2834         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2835                 FALSE, FALSE, MODEST_MARGIN_HALF);
2836         gtk_widget_show (caption);
2837         g_object_unref (sizegroup);
2838 #else 
2839         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2840                             TRUE, FALSE, 0);
2841 #endif /* MODEST_PLATFORM_MAEMO */      
2842                                 
2843 /* This is not in the Maemo UI spec:
2844         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2845         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2846                             TRUE, FALSE, 0);
2847 */
2848
2849         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2850         
2851         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2852                 if (username) {
2853                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2854                         
2855                         modest_server_account_set_username (
2856                                  modest_runtime_get_account_mgr(), server_account_name, 
2857                                  *username);
2858                                  
2859                         const gboolean username_was_changed = 
2860                                 (strcmp (*username, initial_username) != 0);
2861                         if (username_was_changed) {
2862                                 g_warning ("%s: tinymail does not yet support changing the "
2863                                         "username in the get_password() callback.\n", __FUNCTION__);
2864                         }
2865                 }
2866                         
2867                 if (password) {
2868                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2869                         
2870                         /* We do not save the password in the configuration, 
2871                          * because this function is only called for passwords that should 
2872                          * not be remembered:
2873                         modest_server_account_set_password (
2874                                  modest_runtime_get_account_mgr(), server_account_name, 
2875                                  *password);
2876                         */
2877                 }
2878                 
2879                 if (cancel)
2880                         *cancel   = FALSE;
2881                         
2882         } else {
2883                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2884                 
2885                 if (username)
2886                         *username = NULL;
2887                         
2888                 if (password)
2889                         *password = NULL;
2890                         
2891                 if (cancel)
2892                         *cancel   = TRUE;
2893         }
2894
2895 /* This is not in the Maemo UI spec:
2896         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2897                 *remember = TRUE;
2898         else
2899                 *remember = FALSE;
2900 */
2901
2902         gtk_widget_destroy (dialog);
2903         
2904         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2905 }
2906
2907 void
2908 modest_ui_actions_on_cut (GtkAction *action,
2909                           ModestWindow *window)
2910 {
2911         GtkWidget *focused_widget;
2912         GtkClipboard *clipboard;
2913
2914         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2915         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2916         if (GTK_IS_EDITABLE (focused_widget)) {
2917                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2918                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2919                 gtk_clipboard_store (clipboard);
2920         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2921                 GtkTextBuffer *buffer;
2922
2923                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2924                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2925                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2926                 gtk_clipboard_store (clipboard);
2927         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2928                 TnyList *header_list = modest_header_view_get_selected_headers (
2929                                 MODEST_HEADER_VIEW (focused_widget));
2930                 gboolean continue_download = FALSE;
2931                 gint num_of_unc_msgs;
2932
2933                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2934
2935                 if (num_of_unc_msgs)
2936                         continue_download = connect_to_get_msg(
2937                                                                 GTK_WINDOW (window),
2938                                                                 num_of_unc_msgs);
2939
2940                 if (num_of_unc_msgs == 0 || continue_download) {
2941 /*                      modest_platform_information_banner (
2942                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
2943                         modest_header_view_cut_selection (
2944                                         MODEST_HEADER_VIEW (focused_widget));
2945                 }
2946
2947                 g_object_unref (header_list);
2948         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2949                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2950         }
2951 }
2952
2953 void
2954 modest_ui_actions_on_copy (GtkAction *action,
2955                            ModestWindow *window)
2956 {
2957         GtkClipboard *clipboard;
2958         GtkWidget *focused_widget;
2959         gboolean copied = TRUE;
2960
2961         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2962         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2963
2964         if (GTK_IS_LABEL (focused_widget)) {
2965                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2966                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2967                 gtk_clipboard_store (clipboard);
2968         } else if (GTK_IS_EDITABLE (focused_widget)) {
2969                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2970                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2971                 gtk_clipboard_store (clipboard);
2972         } else if (GTK_IS_HTML (focused_widget)) {
2973                 gtk_html_copy (GTK_HTML (focused_widget));
2974                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2975                 gtk_clipboard_store (clipboard);
2976         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2977                 GtkTextBuffer *buffer;
2978                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2979                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2980                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2981                 gtk_clipboard_store (clipboard);
2982         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2983                 TnyList *header_list = modest_header_view_get_selected_headers (
2984                                 MODEST_HEADER_VIEW (focused_widget));
2985                 gboolean continue_download = FALSE;
2986                 gint num_of_unc_msgs;
2987
2988                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
2989
2990                 if (num_of_unc_msgs)
2991                         continue_download = connect_to_get_msg(
2992                                                                 GTK_WINDOW (window),
2993                                                                 num_of_unc_msgs);
2994
2995                 if (num_of_unc_msgs == 0 || continue_download) {
2996                         modest_platform_information_banner (
2997                                         NULL, NULL, _CS("mcen_ib_getting_items"));
2998                         modest_header_view_copy_selection (
2999                                         MODEST_HEADER_VIEW (focused_widget));
3000                 } else
3001                         copied = FALSE;
3002
3003                 g_object_unref (header_list);
3004
3005         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3006                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3007         }
3008
3009         /* Show information banner if there was a copy to clipboard */
3010         if(copied)
3011                 modest_platform_information_banner (
3012                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3013 }
3014
3015 void
3016 modest_ui_actions_on_undo (GtkAction *action,
3017                            ModestWindow *window)
3018 {
3019         ModestEmailClipboard *clipboard = NULL;
3020
3021         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3022                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3023         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3024                 /* Clear clipboard source */
3025                 clipboard = modest_runtime_get_email_clipboard ();
3026                 modest_email_clipboard_clear (clipboard);               
3027         }
3028         else {
3029                 g_return_if_reached ();
3030         }
3031 }
3032
3033 void
3034 modest_ui_actions_on_redo (GtkAction *action,
3035                            ModestWindow *window)
3036 {
3037         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3038                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3039         }
3040         else {
3041                 g_return_if_reached ();
3042         }
3043 }
3044
3045
3046 static void
3047 paste_msgs_cb (const GObject *object, gpointer user_data)
3048 {
3049         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
3050         g_return_if_fail (GTK_IS_WIDGET (user_data));
3051         
3052         /* destroy information note */
3053         gtk_widget_destroy (GTK_WIDGET(user_data));
3054 }
3055
3056
3057 static void
3058 paste_as_attachment_free (gpointer data)
3059 {
3060         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3061
3062         gtk_widget_destroy (helper->banner);
3063         g_object_unref (helper->banner);
3064         g_free (helper);
3065 }
3066
3067 static void
3068 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3069                             TnyHeader *header,
3070                             TnyMsg *msg,
3071                             gpointer userdata)
3072 {
3073         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3074         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3075
3076         if (msg == NULL)
3077                 return;
3078
3079         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3080         
3081 }
3082
3083 void
3084 modest_ui_actions_on_paste (GtkAction *action,
3085                             ModestWindow *window)
3086 {
3087         GtkWidget *focused_widget = NULL;
3088         GtkWidget *inf_note = NULL;
3089         ModestMailOperation *mail_op = NULL;
3090
3091         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3092         if (GTK_IS_EDITABLE (focused_widget)) {
3093                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3094         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3095                 ModestEmailClipboard *e_clipboard = NULL;
3096                 e_clipboard = modest_runtime_get_email_clipboard ();
3097                 if (modest_email_clipboard_cleared (e_clipboard)) {
3098                         GtkTextBuffer *buffer;
3099                         GtkClipboard *clipboard;
3100
3101                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3102                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3103                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3104                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3105                         ModestMailOperation *mail_op;
3106                         TnyFolder *src_folder;
3107                         TnyList *data;
3108                         gboolean delete;
3109                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3110                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3111                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3112                                                                            _CS("ckct_nw_pasting"));
3113                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3114                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3115                                                              G_OBJECT (window));
3116                         if (helper->banner != NULL) {
3117                                 g_object_ref (G_OBJECT (helper->banner));
3118                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3119                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3120                         }
3121
3122                         if (data != NULL) {
3123                                 modest_mail_operation_get_msgs_full (mail_op, 
3124                                                                      data,
3125                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3126                                                                      helper,
3127                                                                      paste_as_attachment_free);
3128                         }
3129                 }
3130         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3131                 ModestEmailClipboard *clipboard = NULL;
3132                 TnyFolder *src_folder = NULL;
3133                 TnyFolderStore *folder_store = NULL;
3134                 TnyList *data = NULL;           
3135                 gboolean delete = FALSE;
3136                 
3137                 /* Check clipboard source */
3138                 clipboard = modest_runtime_get_email_clipboard ();
3139                 if (modest_email_clipboard_cleared (clipboard)) 
3140                         return;
3141                 
3142                 /* Get elements to paste */
3143                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3144
3145                 /* Create a new mail operation */
3146                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
3147                 
3148                 /* Get destination folder */
3149                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3150
3151                 /* transfer messages  */
3152                 if (data != NULL) {
3153                         gint response = 0;
3154
3155                         /* Ask for user confirmation */
3156                         response = msgs_move_to_confirmation (GTK_WINDOW (window), 
3157                                                               TNY_FOLDER (folder_store), 
3158                                                               delete,
3159                                                               data);
3160                         
3161                         if (response == GTK_RESPONSE_OK) {
3162                                 /* Launch notification */
3163                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3164                                                                              _CS("ckct_nw_pasting"));
3165                                 if (inf_note != NULL)  {
3166                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3167                                         gtk_widget_show (GTK_WIDGET(inf_note));
3168                                 }
3169
3170                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3171                                 modest_mail_operation_xfer_msgs (mail_op, 
3172                                                                  data,
3173                                                                  TNY_FOLDER (folder_store),
3174                                                                  delete,
3175                                                                  paste_msgs_cb,
3176                                                                  inf_note);                             
3177                         } else {
3178                                 g_object_unref (mail_op);
3179                         }
3180                         
3181                 } else if (src_folder != NULL) {                        
3182                         /* Launch notification */
3183                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3184                                                                      _CS("ckct_nw_pasting"));
3185                         if (inf_note != NULL)  {
3186                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3187                                 gtk_widget_show (GTK_WIDGET(inf_note));
3188                         }
3189                         
3190                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3191                         modest_mail_operation_xfer_folder (mail_op, 
3192                                                            src_folder,
3193                                                            folder_store,
3194                                                            delete,
3195                                                            paste_msgs_cb,
3196                                                            inf_note);
3197                 }
3198
3199                 /* Free */
3200                 if (data != NULL) 
3201                         g_object_unref (data);
3202                 if (src_folder != NULL) 
3203                         g_object_unref (src_folder);
3204                 if (folder_store != NULL) 
3205                         g_object_unref (folder_store);
3206         }
3207 }
3208
3209
3210 void
3211 modest_ui_actions_on_select_all (GtkAction *action,
3212                                  ModestWindow *window)
3213 {
3214         GtkWidget *focused_widget;
3215
3216         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3217         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3218                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3219         } else if (GTK_IS_LABEL (focused_widget)) {
3220                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3221         } else if (GTK_IS_EDITABLE (focused_widget)) {
3222                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3223         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3224                 GtkTextBuffer *buffer;
3225                 GtkTextIter start, end;
3226
3227                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3228                 gtk_text_buffer_get_start_iter (buffer, &start);
3229                 gtk_text_buffer_get_end_iter (buffer, &end);
3230                 gtk_text_buffer_select_range (buffer, &start, &end);
3231         } else if (GTK_IS_HTML (focused_widget)) {
3232                 gtk_html_select_all (GTK_HTML (focused_widget));
3233         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3234                 GtkWidget *header_view = focused_widget;
3235                 GtkTreeSelection *selection = NULL;
3236                 
3237                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3238                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3239                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3240                 }
3241                                 
3242                 /* Disable window dimming management */
3243                 modest_window_disable_dimming (MODEST_WINDOW(window));
3244                 
3245                 /* Select all messages */
3246                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3247                 gtk_tree_selection_select_all (selection);
3248
3249                 /* Set focuse on header view */
3250                 gtk_widget_grab_focus (header_view);
3251
3252
3253                 /* Enable window dimming management */
3254                 modest_window_enable_dimming (MODEST_WINDOW(window));
3255                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3256         }
3257
3258 }
3259
3260 void
3261 modest_ui_actions_on_mark_as_read (GtkAction *action,
3262                                    ModestWindow *window)
3263 {       
3264         g_return_if_fail (MODEST_IS_WINDOW(window));
3265                 
3266         /* Mark each header as read */
3267         do_headers_action (window, headers_action_mark_as_read, NULL);
3268 }
3269
3270 void
3271 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3272                                      ModestWindow *window)
3273 {       
3274         g_return_if_fail (MODEST_IS_WINDOW(window));
3275                 
3276         /* Mark each header as read */
3277         do_headers_action (window, headers_action_mark_as_unread, NULL);
3278 }
3279
3280 void
3281 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3282                                   GtkRadioAction *selected,
3283                                   ModestWindow *window)
3284 {
3285         gint value;
3286
3287         value = gtk_radio_action_get_current_value (selected);
3288         if (MODEST_IS_WINDOW (window)) {
3289                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3290         }
3291 }
3292
3293 void     
3294 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3295                                                GtkRadioAction *selected,
3296                                                ModestWindow *window)
3297 {
3298         TnyHeaderFlags flags;
3299         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3300
3301         flags = gtk_radio_action_get_current_value (selected);
3302         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3303 }
3304
3305 void     
3306 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3307                                                   GtkRadioAction *selected,
3308                                                   ModestWindow *window)
3309 {
3310         gint file_format;
3311
3312         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3313
3314         file_format = gtk_radio_action_get_current_value (selected);
3315         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3316 }
3317
3318
3319 void     
3320 modest_ui_actions_on_zoom_plus (GtkAction *action,
3321                                 ModestWindow *window)
3322 {
3323         g_return_if_fail (MODEST_IS_WINDOW (window));
3324
3325         modest_window_zoom_plus (MODEST_WINDOW (window));
3326 }
3327
3328 void     
3329 modest_ui_actions_on_zoom_minus (GtkAction *action,
3330                                  ModestWindow *window)
3331 {
3332         g_return_if_fail (MODEST_IS_WINDOW (window));
3333
3334         modest_window_zoom_minus (MODEST_WINDOW (window));
3335 }
3336
3337 void     
3338 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3339                                            ModestWindow *window)
3340 {
3341         ModestWindowMgr *mgr;
3342         gboolean fullscreen, active;
3343         g_return_if_fail (MODEST_IS_WINDOW (window));
3344
3345         mgr = modest_runtime_get_window_mgr ();
3346
3347         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3348         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3349
3350         if (active != fullscreen) {
3351                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3352                 gtk_window_present (GTK_WINDOW (window));
3353         }
3354 }
3355
3356 void
3357 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3358                                         ModestWindow *window)
3359 {
3360         ModestWindowMgr *mgr;
3361         gboolean fullscreen;
3362
3363         g_return_if_fail (MODEST_IS_WINDOW (window));
3364
3365         mgr = modest_runtime_get_window_mgr ();
3366         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3367         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3368
3369         gtk_window_present (GTK_WINDOW (window));
3370 }
3371
3372 /* 
3373  * Used by modest_ui_actions_on_details to call do_headers_action 
3374  */
3375 static void
3376 headers_action_show_details (TnyHeader *header, 
3377                              ModestWindow *window,
3378                              gpointer user_data)
3379
3380 {
3381         GtkWidget *dialog;
3382         
3383         /* Create dialog */
3384         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3385
3386         /* Run dialog */
3387         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3388         gtk_widget_show_all (dialog);
3389         gtk_dialog_run (GTK_DIALOG (dialog));
3390
3391         gtk_widget_destroy (dialog);
3392 }
3393
3394 /*
3395  * Show the folder details in a ModestDetailsDialog widget
3396  */
3397 static void
3398 show_folder_details (TnyFolder *folder, 
3399                      GtkWindow *window)
3400 {
3401         GtkWidget *dialog;
3402         
3403         /* Create dialog */
3404         dialog = modest_details_dialog_new_with_folder (window, folder);
3405
3406         /* Run dialog */
3407         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3408         gtk_widget_show_all (dialog);
3409         gtk_dialog_run (GTK_DIALOG (dialog));
3410
3411         gtk_widget_destroy (dialog);
3412 }
3413
3414 /*
3415  * Show the header details in a ModestDetailsDialog widget
3416  */
3417 void     
3418 modest_ui_actions_on_details (GtkAction *action, 
3419                               ModestWindow *win)
3420 {
3421         TnyList * headers_list;
3422         TnyIterator *iter;
3423         TnyHeader *header;              
3424
3425         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3426                 TnyMsg *msg;
3427
3428                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3429                 if (!msg)
3430                         return;
3431                 g_object_unref (msg);           
3432
3433                 headers_list = get_selected_headers (win);
3434                 if (!headers_list)
3435                         return;
3436
3437                 iter = tny_list_create_iterator (headers_list);
3438
3439                 header = TNY_HEADER (tny_iterator_get_current (iter));
3440                 if (header) {
3441                         headers_action_show_details (header, win, NULL);
3442                         g_object_unref (header);
3443                 }
3444
3445                 g_object_unref (iter);
3446                 g_object_unref (headers_list);
3447
3448         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3449                 GtkWidget *folder_view, *header_view;
3450
3451                 /* Check which widget has the focus */
3452                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3453                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3454                 if (gtk_widget_is_focus (folder_view)) {
3455                         TnyFolderStore *folder_store
3456                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3457                         if (!folder_store) {
3458                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3459                                 return; 
3460                         }
3461                         /* Show only when it's a folder */
3462                         /* This function should not be called for account items, 
3463                          * because we dim the menu item for them. */
3464                         if (TNY_IS_FOLDER (folder_store)) {
3465                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3466                         }
3467
3468                         g_object_unref (folder_store);
3469
3470                 } else {
3471                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3472                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3473                         /* Show details of each header */
3474                         do_headers_action (win, headers_action_show_details, header_view);
3475                 }
3476         }
3477 }
3478
3479 void     
3480 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3481                                      ModestMsgEditWindow *window)
3482 {
3483         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3484
3485         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3486 }
3487
3488 void     
3489 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3490                                       ModestMsgEditWindow *window)
3491 {
3492         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3493
3494         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3495 }
3496
3497 void
3498 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3499                                        ModestMainWindow *main_window)
3500 {
3501         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3502
3503         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3504                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3505         else
3506                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3507 }
3508
3509 void 
3510 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3511                                      ModestWindow *window)
3512 {
3513         gboolean active, fullscreen = FALSE;
3514         ModestWindowMgr *mgr;
3515
3516         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3517
3518         /* Check if we want to toggle the toolbar vuew in fullscreen
3519            or normal mode */
3520         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3521                      "ViewShowToolbarFullScreen")) {
3522                 fullscreen = TRUE;
3523         }
3524
3525         /* Toggle toolbar */
3526         mgr = modest_runtime_get_window_mgr ();
3527         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3528 }
3529
3530 void     
3531 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3532                                            ModestMsgEditWindow *window)
3533 {
3534         modest_msg_edit_window_select_font (window);
3535 }
3536
3537 void
3538 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3539                                                   const gchar *display_name,
3540                                                   GtkWindow *window)
3541 {
3542         /* Do not change the application name if the widget has not
3543            the focus. This callback could be called even if the folder
3544            view has not the focus, because the handled signal could be
3545            emitted when the folder view is redrawn */
3546         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3547                 if (display_name)
3548                         gtk_window_set_title (window, display_name);
3549                 else
3550                         gtk_window_set_title (window, " ");
3551         }
3552 }
3553
3554 void
3555 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3556 {
3557         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3558         modest_msg_edit_window_select_contacts (window);
3559 }
3560
3561 void
3562 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3563 {
3564         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3565         modest_msg_edit_window_check_names (window, FALSE);
3566 }
3567
3568 static void
3569 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3570 {
3571         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3572                                          GTK_WIDGET (user_data));
3573 }
3574
3575 /*
3576  * This function is used to track changes in the selection of the
3577  * folder view that is inside the "move to" dialog to enable/disable
3578  * the OK button because we do not want the user to select a disallowed
3579  * destination for a folder.
3580  * The user also not desired to be able to use NEW button on items where
3581  * folder creation is not possibel.
3582  */
3583 static void
3584 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
3585                                             TnyFolderStore *folder_store,
3586                                             gboolean selected,
3587                                             gpointer user_data)
3588 {
3589         GtkWidget *dialog = NULL;
3590         GtkWidget *ok_button = NULL, *new_button = NULL;
3591         GList *children = NULL;
3592         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
3593         gboolean moving_folder = FALSE;
3594         gboolean is_local_account = TRUE;
3595         GtkWidget *folder_view = NULL;
3596         ModestTnyFolderRules rules;
3597
3598         if (!selected)
3599                 return;
3600
3601         /* Get the OK button */
3602         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
3603         if (!dialog)
3604                 return;
3605
3606         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
3607         ok_button = GTK_WIDGET (children->next->next->data);
3608         new_button = GTK_WIDGET (children->next->data);
3609         g_list_free (children);
3610
3611         /* check if folder_store is an remote account */
3612         if (TNY_IS_ACCOUNT (folder_store)) {
3613                 TnyAccount *local_account = NULL;
3614                 ModestTnyAccountStore *account_store = NULL;
3615
3616                 account_store = modest_runtime_get_account_store ();
3617                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
3618
3619                 if ((gpointer) local_account != (gpointer) folder_store) {
3620                         is_local_account = FALSE;
3621                         /* New button should be dimmed on remote
3622                            account root */
3623                         new_sensitive = FALSE;
3624                 }
3625                 g_object_unref (local_account);
3626         }
3627
3628         /* Check the target folder rules */
3629         if (TNY_IS_FOLDER (folder_store)) {
3630                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
3631                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
3632                         ok_sensitive = FALSE;
3633                         new_sensitive = FALSE;
3634                         goto end;
3635                 }
3636         }
3637
3638         /* Check if we're moving a folder */
3639         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3640                 /* Get the widgets */
3641                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
3642                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3643                 if (gtk_widget_is_focus (folder_view))
3644                         moving_folder = TRUE;
3645         }
3646
3647         if (moving_folder) {
3648                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
3649
3650                 /* Get the folder to move */
3651                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3652                 
3653                 /* Check that we're not moving to the same folder */
3654                 if (TNY_IS_FOLDER (moved_folder)) {
3655                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
3656                         if (parent == folder_store)
3657                                 ok_sensitive = FALSE;
3658                         g_object_unref (parent);
3659                 } 
3660
3661                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
3662                         /* Do not allow to move to an account unless it's the
3663                            local folders account */
3664                         if (!is_local_account)
3665                                 ok_sensitive = FALSE;
3666                 } 
3667
3668                 if (ok_sensitive && (moved_folder == folder_store)) {
3669                         /* Do not allow to move to itself */
3670                         ok_sensitive = FALSE;
3671                 }
3672                 g_object_unref (moved_folder);
3673         } else {
3674                 TnyHeader *header = NULL;
3675                 TnyFolder *src_folder = NULL;
3676
3677                 /* Moving a message */
3678                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
3679                         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (user_data));
3680                         src_folder = tny_header_get_folder (header);
3681                         g_object_unref (header);
3682                 } else {
3683                         src_folder = 
3684                                 TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
3685                 }
3686
3687                 /* Do not allow to move the msg to the same folder */
3688                 /* Do not allow to move the msg to an account */
3689                 if ((gpointer) src_folder == (gpointer) folder_store ||
3690                     TNY_IS_ACCOUNT (folder_store))
3691                         ok_sensitive = FALSE;
3692                 g_object_unref (src_folder);
3693         }
3694
3695  end:
3696         /* Set sensitivity of the OK button */
3697         gtk_widget_set_sensitive (ok_button, ok_sensitive);
3698         /* Set sensitivity of the NEW button */
3699         gtk_widget_set_sensitive (new_button, new_sensitive);
3700 }
3701
3702 static GtkWidget*
3703 create_move_to_dialog (GtkWindow *win,
3704                        GtkWidget *folder_view,
3705                        GtkWidget **tree_view)
3706 {
3707         GtkWidget *dialog, *scroll;
3708         GtkWidget *new_button;
3709
3710         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3711                                               GTK_WINDOW (win),
3712                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3713                                               NULL);
3714
3715         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3716         /* We do this manually so GTK+ does not associate a response ID for
3717          * the button. */
3718         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
3719         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3720         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
3721
3722         /* Create scrolled window */
3723         scroll = gtk_scrolled_window_new (NULL, NULL);
3724         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3725                                          GTK_POLICY_AUTOMATIC,
3726                                          GTK_POLICY_AUTOMATIC);
3727
3728         /* Create folder view */
3729         *tree_view = modest_platform_create_folder_view (NULL);
3730
3731         /* Track changes in the selection to
3732          * disable the OK button whenever "Move to" is not possible
3733          * disbale NEW button whenever New is not possible */
3734         g_signal_connect (*tree_view,
3735                           "folder_selection_changed",
3736                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
3737                           win);
3738
3739         /* Listen to clicks on New button */
3740         g_signal_connect (G_OBJECT (new_button), 
3741                           "clicked", 
3742                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
3743                           *tree_view);
3744
3745         /* It could happen that we're trying to move a message from a
3746            window (msg window for example) after the main window was
3747            closed, so we can not just get the model of the folder
3748            view */
3749         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
3750                 const gchar *visible_id = NULL;
3751
3752                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
3753                                                MODEST_FOLDER_VIEW(*tree_view));
3754
3755                 visible_id = 
3756                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
3757
3758                 /* Show the same account than the one that is shown in the main window */
3759                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
3760                                                                              visible_id);
3761         } else {
3762                 const gchar *active_account_name = NULL;
3763                 ModestAccountMgr *mgr = NULL;
3764                 ModestAccountData *acc_data = NULL;
3765
3766                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3767                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3768
3769                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
3770                 mgr = modest_runtime_get_account_mgr ();
3771                 acc_data = modest_account_mgr_get_account_data (mgr, active_account_name);
3772
3773                 /* Set the new visible & active account */
3774                 if (acc_data && acc_data->store_account) { 
3775                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
3776                                                                                      acc_data->store_account->account_name);
3777                         modest_account_mgr_free_account_data (mgr, acc_data);
3778                 }
3779         }
3780
3781         /* Hide special folders */
3782         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3783         
3784         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3785
3786         /* Add scroll to dialog */
3787         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3788                             scroll, TRUE, TRUE, 0);
3789
3790         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3791         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3792
3793         return dialog;
3794 }
3795
3796 /*
3797  * Returns TRUE if at least one of the headers of the list belongs to
3798  * a message that has been fully retrieved.
3799  */
3800 #if 0 /* no longer in use. delete in 2007.10 */
3801 static gboolean
3802 has_retrieved_msgs (TnyList *list)
3803 {
3804         TnyIterator *iter;
3805         gboolean found = FALSE;
3806
3807         iter = tny_list_create_iterator (list);
3808         while (!tny_iterator_is_done (iter) && !found) {
3809                 TnyHeader *header;
3810                 TnyHeaderFlags flags = 0;
3811
3812                 header = TNY_HEADER (tny_iterator_get_current (iter));
3813                 if (header) {
3814                         flags = tny_header_get_flags (header);
3815                         if (flags & TNY_HEADER_FLAG_CACHED)
3816 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
3817                                 found = TRUE;
3818
3819                         g_object_unref (header);
3820                 }
3821
3822                 if (!found)
3823                         tny_iterator_next (iter);
3824         }
3825         g_object_unref (iter);
3826
3827         return found;
3828 }
3829 #endif /* 0 */
3830
3831
3832 /*
3833  * Shows a confirmation dialog to the user when we're moving messages
3834  * from a remote server to the local storage. Returns the dialog
3835  * response. If it's other kind of movement then it always returns
3836  * GTK_RESPONSE_OK
3837  *
3838  * This one is used by the next functions:
3839  *      modest_ui_actions_on_paste                      - commented out
3840  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
3841  */
3842 gint
3843 msgs_move_to_confirmation (GtkWindow *win,
3844                            TnyFolder *dest_folder,
3845                            gboolean delete,
3846                            TnyList *headers)
3847 {
3848         gint response = GTK_RESPONSE_OK;
3849
3850         /* return with OK if the destination is a remote folder */
3851         if (modest_tny_folder_is_remote_folder (dest_folder))
3852                 return GTK_RESPONSE_OK;
3853
3854         TnyFolder *src_folder = NULL;
3855         TnyIterator *iter = NULL;
3856         TnyHeader *header = NULL;
3857
3858         /* Get source folder */
3859         iter = tny_list_create_iterator (headers);
3860         header = TNY_HEADER (tny_iterator_get_current (iter));
3861         if (header) {
3862                 src_folder = tny_header_get_folder (header);
3863                 g_object_unref (header);
3864         }
3865         g_object_unref (iter);
3866
3867         /* if no src_folder, message may be an attahcment */
3868         if (src_folder == NULL) 
3869                 return GTK_RESPONSE_CANCEL;
3870
3871         /* If the source is a local or MMC folder */
3872         if (!modest_tny_folder_is_remote_folder (src_folder)) {
3873                 g_object_unref (src_folder);
3874                 return GTK_RESPONSE_OK;
3875         }
3876         g_object_unref (src_folder);
3877
3878         /* now if offline we ask the user */
3879         if(connect_to_get_msg(  GTK_WINDOW (win),
3880                                         tny_list_get_length (headers)))
3881                 response = GTK_RESPONSE_OK;
3882         else
3883                 response = GTK_RESPONSE_CANCEL;
3884
3885         return response;
3886 }
3887
3888
3889
3890 static void
3891 move_to_cb (const GObject *object, gpointer user_data)
3892 {
3893         ModestMsgViewWindow *self = NULL;
3894         g_return_if_fail (GTK_IS_WIDGET (user_data));
3895         g_return_if_fail (MODEST_IS_WINDOW (object));
3896
3897         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
3898                 self = MODEST_MSG_VIEW_WINDOW (object);
3899
3900                 if (!modest_msg_view_window_select_next_message (self))
3901                         if (!modest_msg_view_window_select_previous_message (self))
3902                                 /* No more messages to view, so close this window */
3903                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3904         }
3905         gtk_widget_destroy (GTK_WIDGET(user_data));
3906 }
3907
3908 void
3909 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3910                                              gpointer user_data)
3911 {
3912         ModestMainWindow *main_window = NULL;
3913         GtkWidget *folder_view = NULL;
3914         GObject *win = modest_mail_operation_get_source (mail_op);
3915         const GError *error = NULL;
3916         const gchar *message = NULL;
3917         
3918         /* Get error message */
3919         error = modest_mail_operation_get_error (mail_op);
3920         if (error != NULL && error->message != NULL) {
3921                 message = error->message;
3922         } else {
3923                 message = _("mail_in_ui_folder_move_target_error");
3924         }
3925         
3926         /* Disable next automatic folder selection */
3927         if (MODEST_IS_MAIN_WINDOW (user_data)) {
3928                 main_window = MODEST_MAIN_WINDOW(user_data);
3929                 folder_view = modest_main_window_get_child_widget (main_window,
3930                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
3931                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));             
3932         }
3933
3934         /* Show notification dialog */
3935         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3936         g_object_unref (win);
3937 }
3938
3939 void
3940 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3941                                               gpointer user_data)
3942 {
3943         GObject *win = modest_mail_operation_get_source (mail_op);
3944         const GError *error = modest_mail_operation_get_error (mail_op);
3945
3946         g_return_if_fail (error != NULL);
3947         if (error->message != NULL)             
3948                 g_printerr ("modest: %s\n", error->message);
3949         else
3950                 g_printerr ("modest: unkonw error on send&receive operation");
3951
3952         /* Show error message */
3953 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3954 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3955 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3956 /*      else  */
3957 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3958 /*                                                      _CS("sfil_ib_unable_to_send")); */
3959         g_object_unref (win);
3960 }
3961
3962 static void
3963 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3964                        TnyHeader *header, 
3965                        TnyMsg *msg, 
3966                        gpointer user_data)
3967 {
3968         TnyList *parts;
3969         TnyIterator *iter;
3970         gint pending_purges = 0;
3971         gboolean some_purged = FALSE;
3972         ModestWindow *win = MODEST_WINDOW (user_data);
3973         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3974
3975         /* If there was any error */
3976         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3977                 modest_window_mgr_unregister_header (mgr, header);
3978                 return;
3979         }
3980
3981         /* Once the message has been retrieved for purging, we check if
3982          * it's all ok for purging */
3983
3984         parts = tny_simple_list_new ();
3985         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3986         iter = tny_list_create_iterator (parts);
3987
3988         while (!tny_iterator_is_done (iter)) {
3989                 TnyMimePart *part;
3990                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3991                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3992                         if (tny_mime_part_is_purged (part))
3993                                 some_purged = TRUE;
3994                         else
3995                                 pending_purges++;
3996                 }
3997
3998                 if (part)
3999                         g_object_unref (part);
4000
4001                 tny_iterator_next (iter);
4002         }
4003
4004         if (pending_purges>0) {
4005                 gint response;
4006                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4007
4008                 if (response == GTK_RESPONSE_OK) {
4009                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4010                         tny_iterator_first (iter);
4011                         while (!tny_iterator_is_done (iter)) {
4012                                 TnyMimePart *part;
4013                                 
4014                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4015                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4016                                         tny_mime_part_set_purged (part);
4017
4018                                 if (part)
4019                                         g_object_unref (part);
4020
4021                                 tny_iterator_next (iter);
4022                         }
4023                         
4024                         tny_msg_rewrite_cache (msg);
4025                 }
4026         } else {
4027                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
4028         }
4029
4030         /* remove attachments */
4031         tny_iterator_first (iter);
4032         while (!tny_iterator_is_done (iter)) {
4033                 TnyMimePart *part;
4034                         
4035                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4036                 if (part) {
4037                         /* One for the reference given by tny_iterator_get_current(): */
4038                         g_object_unref (part);
4039
4040                         /* TODO: Is this meant to remove the attachment by doing another unref()? 
4041                          * Otherwise, this seems useless. */
4042                 }
4043
4044                 tny_iterator_next (iter);
4045         }
4046         modest_window_mgr_unregister_header (mgr, header);
4047
4048         g_object_unref (iter);
4049         g_object_unref (parts);
4050 }
4051
4052 static void
4053 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4054                                                      ModestMainWindow *win)
4055 {
4056         GtkWidget *header_view;
4057         TnyList *header_list;
4058         TnyIterator *iter;
4059         TnyHeader *header;
4060         TnyHeaderFlags flags;
4061         ModestWindow *msg_view_window =  NULL;
4062         gboolean found;
4063
4064         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4065
4066         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4067                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4068
4069         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4070
4071         if (tny_list_get_length (header_list) == 1) {
4072                 iter = tny_list_create_iterator (header_list);
4073                 header = TNY_HEADER (tny_iterator_get_current (iter));
4074                 g_object_unref (iter);
4075         } else {
4076                 return;
4077         }
4078
4079         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4080                                                           header, &msg_view_window);
4081         flags = tny_header_get_flags (header);
4082         if (!(flags & TNY_HEADER_FLAG_CACHED))
4083                 return;
4084         if (found) {
4085                 if (msg_view_window != NULL) 
4086                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4087                 else {
4088                         /* do nothing; uid was registered before, so window is probably on it's way */
4089                         g_warning ("debug: header %p has already been registered", header);
4090                 }
4091         } else {
4092                 ModestMailOperation *mail_op = NULL;
4093                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
4094                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4095                                                                          G_OBJECT (win),
4096                                                                          modest_ui_actions_get_msgs_full_error_handler,
4097                                                                          NULL);
4098                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4099                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4100                 
4101                 g_object_unref (mail_op);
4102         }
4103         if (header)
4104                 g_object_unref (header);
4105         if (header_list)
4106                 g_object_unref (header_list);
4107 }
4108
4109 /**
4110  * Utility function that transfer messages from both the main window
4111  * and the msg view window when using the "Move to" dialog
4112  */
4113 static void
4114 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
4115                                               ModestWindow *win)
4116 {
4117         TnyList *headers = NULL;
4118         TnyAccount *dst_account = NULL;
4119         const gchar *proto_str = NULL;
4120         gboolean dst_is_pop = FALSE;
4121
4122         if (!TNY_IS_FOLDER (dst_folder)) {
4123                 modest_platform_information_banner (GTK_WIDGET (win),
4124                                                     NULL,
4125                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
4126                 return;
4127         }
4128
4129         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4130         proto_str = tny_account_get_proto (dst_account);
4131
4132         /* tinymail will return NULL for local folders it seems */
4133         dst_is_pop = proto_str &&
4134                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4135                  MODEST_PROTOCOL_STORE_POP);
4136
4137         g_object_unref (dst_account);
4138
4139         /* Get selected headers */
4140         headers = get_selected_headers (MODEST_WINDOW (win));
4141
4142         if (dst_is_pop) {
4143                 modest_platform_information_banner (GTK_WIDGET (win),
4144                                                     NULL,
4145                                                     ngettext("mail_in_ui_folder_move_target_error",
4146                                                              "mail_in_ui_folder_move_targets_error",
4147                                                              tny_list_get_length (headers)));
4148                 g_object_unref (headers);
4149                 return;
4150         }
4151
4152         GtkWidget *inf_note;
4153         inf_note = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4154                                                      _CS("ckct_nw_pasting"));
4155         if (inf_note != NULL)  {
4156                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4157                 gtk_widget_show (GTK_WIDGET(inf_note));
4158         }
4159
4160         ModestMailOperation *mail_op = 
4161                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4162                                                                G_OBJECT(win),
4163                                                                modest_ui_actions_move_folder_error_handler,
4164                                                                NULL);
4165         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4166                                          mail_op);
4167
4168         modest_mail_operation_xfer_msgs (mail_op, 
4169                                          headers,
4170                                          TNY_FOLDER (dst_folder),
4171                                          TRUE,
4172                                          move_to_cb,
4173                                          inf_note);
4174
4175         g_object_unref (G_OBJECT (mail_op));
4176         g_object_unref (headers);
4177 }
4178
4179 /*
4180  * UI handler for the "Move to" action when invoked from the
4181  * ModestMainWindow
4182  */
4183 static void 
4184 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4185                                           GtkWidget *folder_view,
4186                                           TnyFolderStore *dst_folder,
4187                                           ModestMainWindow *win)
4188 {
4189         ModestHeaderView *header_view = NULL;
4190         ModestMailOperation *mail_op = NULL;
4191         TnyFolderStore *src_folder;
4192         gboolean online = (tny_device_is_online (modest_runtime_get_device()));
4193
4194         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4195
4196         /* Get the source folder */
4197         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4198
4199         /* Get header view */
4200         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4201
4202         /* Get folder or messages to transfer */
4203         if (gtk_widget_is_focus (folder_view)) {
4204                 GtkTreeSelection *sel;
4205                 gboolean do_xfer = TRUE;
4206
4207                 /* Allow only to transfer folders to the local root folder */
4208                 if (TNY_IS_ACCOUNT (dst_folder) && 
4209                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder)) {
4210                         do_xfer = FALSE;
4211                 } else if (!TNY_IS_FOLDER (src_folder)) {
4212                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4213                         do_xfer = FALSE;
4214                 } else if (!online && modest_platform_is_network_folderstore(src_folder)) {
4215                         guint num_headers = tny_folder_get_all_count(TNY_FOLDER(src_folder));
4216                         if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4217                                 do_xfer = FALSE;
4218                         }
4219                 }
4220
4221                 if (do_xfer) {
4222                         GtkWidget *inf_note;
4223                         inf_note = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4224                                                                      _CS("ckct_nw_pasting"));
4225                         if (inf_note != NULL)  {
4226                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4227                                 gtk_widget_show (GTK_WIDGET(inf_note));
4228                         }
4229                         /* Clean folder on header view before moving it */
4230                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4231                         gtk_tree_selection_unselect_all (sel);
4232
4233                         mail_op =
4234                           modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
4235                                                                          G_OBJECT(win),
4236                                                                          modest_ui_actions_move_folder_error_handler,
4237                                                                          win);
4238                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4239                                                          mail_op);
4240
4241                         /* Select *after* the changes */
4242                         /* TODO: this function hangs UI after transfer */ 
4243 /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4244 /*                                                        TNY_FOLDER (src_folder), TRUE); */
4245                         
4246                         modest_mail_operation_xfer_folder (mail_op,
4247                                                            TNY_FOLDER (src_folder),
4248                                                            dst_folder,
4249                                                            TRUE, move_to_cb, inf_note);
4250                         /* Unref mail operation */
4251                         g_object_unref (G_OBJECT (mail_op));
4252                 }
4253         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4254                 gboolean do_xfer = TRUE;
4255                 /* Ask for confirmation if the source folder is remote and we're not connected */
4256                 if (!online && modest_platform_is_network_folderstore(src_folder)) {
4257                         TnyList *headers = modest_header_view_get_selected_headers(header_view);
4258                         if (!msgs_already_deleted_from_server(headers, src_folder)) {
4259                                 guint num_headers = tny_list_get_length(headers);
4260                                 if (!connect_to_get_msg(GTK_WINDOW(win), num_headers)) {
4261                                         do_xfer = FALSE;
4262                                 }
4263                         }
4264                         g_object_unref(headers);
4265                 }
4266                 if (do_xfer) /* Transfer messages */
4267                         modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4268         }
4269
4270     if (src_folder)
4271         g_object_unref (src_folder);
4272 }
4273
4274
4275 /*
4276  * UI handler for the "Move to" action when invoked from the
4277  * ModestMsgViewWindow
4278  */
4279 static void 
4280 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
4281                                               TnyFolderStore *dst_folder,
4282                                               ModestMsgViewWindow *win)
4283 {
4284         TnyHeader *header = NULL;
4285         TnyFolderStore *src_folder;
4286
4287         /* Create header list */
4288         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
4289         src_folder = TNY_FOLDER_STORE(tny_header_get_folder(header));
4290         g_object_unref (header);
4291
4292         /* Transfer the message if online or confirmed by the user */
4293         if (tny_device_is_online (modest_runtime_get_device()) || remote_folder_is_pop(src_folder) ||
4294             (modest_platform_is_network_folderstore(src_folder) && connect_to_get_msg(GTK_WINDOW(win), 1))) {
4295                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
4296         }
4297
4298         g_object_unref (src_folder);
4299 }
4300
4301 void 
4302 modest_ui_actions_on_move_to (GtkAction *action, 
4303                               ModestWindow *win)
4304 {
4305         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
4306         gint result = 0;
4307         TnyFolderStore *dst_folder = NULL;
4308         ModestMainWindow *main_window;
4309
4310         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
4311                           MODEST_IS_MSG_VIEW_WINDOW (win));
4312
4313         /* Get the main window if exists */
4314         if (MODEST_IS_MAIN_WINDOW (win))
4315                 main_window = MODEST_MAIN_WINDOW (win);
4316         else
4317                 main_window = 
4318                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
4319
4320         /* Get the folder view widget if exists */
4321         if (main_window)
4322                 folder_view = modest_main_window_get_child_widget (main_window,
4323                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4324         else
4325                 folder_view = NULL;
4326
4327         /* Create and run the dialog */
4328         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
4329         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
4330         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4331         result = gtk_dialog_run (GTK_DIALOG(dialog));
4332         g_object_ref (tree_view);
4333         gtk_widget_destroy (dialog);
4334
4335         if (result != GTK_RESPONSE_ACCEPT)
4336                 return;
4337
4338         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
4339         /* Do window specific stuff */
4340         if (MODEST_IS_MAIN_WINDOW (win)) {
4341                 modest_ui_actions_on_main_window_move_to (action,
4342                                                           folder_view,
4343                                                           dst_folder,
4344                                                           MODEST_MAIN_WINDOW (win));
4345         } else {
4346                 modest_ui_actions_on_msg_view_window_move_to (action,
4347                                                               dst_folder,
4348                                                               MODEST_MSG_VIEW_WINDOW (win));
4349         }
4350
4351         if (dst_folder)
4352                 g_object_unref (dst_folder);
4353 }
4354
4355 /*
4356  * Calls #HeadersFunc for each header already selected in the main
4357  * window or the message currently being shown in the msg view window
4358  */
4359 static void
4360 do_headers_action (ModestWindow *win, 
4361                    HeadersFunc func,
4362                    gpointer user_data)
4363 {
4364         TnyList *headers_list = NULL;
4365         TnyIterator *iter = NULL;
4366         TnyHeader *header = NULL;
4367         TnyFolder *folder = NULL;
4368
4369         /* Get headers */
4370         headers_list = get_selected_headers (win);
4371         if (!headers_list)
4372                 return;
4373
4374         /* Get the folder */
4375         iter = tny_list_create_iterator (headers_list);
4376         header = TNY_HEADER (tny_iterator_get_current (iter));
4377         if (header) {
4378                 folder = tny_header_get_folder (header);
4379                 g_object_unref (header);
4380         }
4381
4382         /* Call the function for each header */
4383         while (!tny_iterator_is_done (iter)) {
4384                 header = TNY_HEADER (tny_iterator_get_current (iter));
4385                 func (header, win, user_data);
4386                 g_object_unref (header);
4387                 tny_iterator_next (iter);
4388         }
4389
4390         /* Trick: do a poke status in order to speed up the signaling
4391            of observers */
4392         tny_folder_poke_status (folder);
4393
4394         /* Frees */
4395         g_object_unref (folder);
4396         g_object_unref (iter);
4397         g_object_unref (headers_list);
4398 }
4399
4400 void 
4401 modest_ui_actions_view_attachment (GtkAction *action,
4402                                    ModestWindow *window)
4403 {
4404         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4405                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
4406         } else {
4407                 /* not supported window for this action */
4408                 g_return_if_reached ();
4409         }
4410 }
4411
4412 void
4413 modest_ui_actions_save_attachments (GtkAction *action,
4414                                     ModestWindow *window)
4415 {
4416         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4417                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
4418         } else {
4419                 /* not supported window for this action */
4420                 g_return_if_reached ();
4421         }
4422 }
4423
4424 void
4425 modest_ui_actions_remove_attachments (GtkAction *action,
4426                                       ModestWindow *window)
4427 {
4428         if (MODEST_IS_MAIN_WINDOW (window)) {
4429                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
4430         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4431                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
4432         } else {
4433                 /* not supported window for this action */
4434                 g_return_if_reached ();
4435         }
4436 }
4437
4438 void 
4439 modest_ui_actions_on_settings (GtkAction *action, 
4440                                ModestWindow *win)
4441 {
4442         GtkWidget *dialog;
4443
4444         dialog = modest_platform_get_global_settings_dialog ();
4445         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
4446         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4447         gtk_widget_show_all (dialog);
4448
4449         gtk_dialog_run (GTK_DIALOG (dialog));
4450
4451         gtk_widget_destroy (dialog);
4452 }
4453
4454 void 
4455 modest_ui_actions_on_help (GtkAction *action, 
4456                            ModestWindow *win)
4457 {
4458         const gchar *help_id = NULL;
4459
4460         if (MODEST_IS_MAIN_WINDOW (win)) {
4461                 GtkWidget *folder_view;
4462                 TnyFolderStore *folder_store;
4463                 
4464                 /* Get selected folder */
4465                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4466                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4467                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4468
4469                 /* Switch help_id */
4470                 if (TNY_IS_FOLDER (folder_store)) {
4471                         switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
4472                         case TNY_FOLDER_TYPE_NORMAL:
4473                                 help_id = "applications_email_managefolders";
4474                                 break;
4475                         case TNY_FOLDER_TYPE_INBOX:
4476                                 help_id = "applications_email_inbox";
4477                                 break;
4478                         case TNY_FOLDER_TYPE_OUTBOX:
4479                                 help_id = "applications_email_outbox";
4480                                 break;
4481                         case TNY_FOLDER_TYPE_SENT:
4482                                 help_id = "applications_email_sent";
4483                                 break;
4484                         case TNY_FOLDER_TYPE_DRAFTS:
4485                                 help_id = "applications_email_drafts";
4486                                 break;
4487                         case TNY_FOLDER_TYPE_ARCHIVE:
4488                                 help_id = "applications_email_managefolders";
4489                                 break;
4490                         default:
4491                                 help_id = "applications_email_managefolders";
4492                         }
4493                 } else {
4494                         help_id = "applications_email_mainview";
4495                 }
4496                 g_object_unref (folder_store);
4497         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4498                 help_id = "applications_email_viewer";
4499         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
4500                 help_id = "applications_email_editor";
4501
4502         modest_platform_show_help (GTK_WINDOW (win), help_id);
4503 }
4504
4505 void 
4506 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
4507                                             ModestWindow *window)
4508 {
4509         ModestMailOperation *mail_op;
4510         TnyList *headers;
4511
4512         /* Get headers */
4513         headers = get_selected_headers (window);
4514         if (!headers)
4515                 return;
4516
4517         /* Create mail operation */
4518         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
4519                                                                  G_OBJECT (window),
4520                                                                  modest_ui_actions_get_msgs_full_error_handler, 
4521                                                                  NULL);
4522         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4523         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
4524
4525         /* Frees */
4526         g_object_unref (headers);
4527         g_object_unref (mail_op);
4528 }
4529
4530 void
4531 modest_ui_actions_on_email_menu_activated (GtkAction *action,
4532                                           ModestWindow *window)
4533 {
4534         g_return_if_fail (MODEST_IS_WINDOW (window));
4535         
4536         /* Update dimmed */     
4537         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4538 }
4539
4540 void
4541 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
4542                                           ModestWindow *window)
4543 {
4544         g_return_if_fail (MODEST_IS_WINDOW (window));
4545
4546         /* Update dimmed */     
4547         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4548 }
4549
4550 void
4551 modest_ui_actions_on_view_menu_activated (GtkAction *action,
4552                                           ModestWindow *window)
4553 {
4554         g_return_if_fail (MODEST_IS_WINDOW (window));
4555
4556         /* Update dimmed */     
4557         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4558 }
4559
4560 void
4561 modest_ui_actions_on_format_menu_activated (GtkAction *action,
4562                                             ModestWindow *window)
4563 {
4564         g_return_if_fail (MODEST_IS_WINDOW (window));
4565
4566         /* Update dimmed */     
4567         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4568 }
4569
4570 void
4571 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4572                                           ModestWindow *window)
4573 {
4574         g_return_if_fail (MODEST_IS_WINDOW (window));
4575
4576         /* Update dimmed */     
4577         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4578 }
4579
4580 void
4581 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4582                                           ModestWindow *window)
4583 {
4584         g_return_if_fail (MODEST_IS_WINDOW (window));
4585
4586         /* Update dimmed */     
4587         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4588 }
4589
4590 void
4591 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4592                                                  ModestWindow *window)
4593 {
4594         g_return_if_fail (MODEST_IS_WINDOW (window));
4595
4596         /* Update dimmed */     
4597         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4598 }
4599
4600 void
4601 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4602                                                      ModestWindow *window)
4603 {
4604         g_return_if_fail (MODEST_IS_WINDOW (window));
4605
4606         /* Update dimmed */     
4607         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4608 }
4609
4610 void
4611 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4612                                                      ModestWindow *window)
4613 {
4614         g_return_if_fail (MODEST_IS_WINDOW (window));
4615
4616         /* Update dimmed */     
4617         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4618 }
4619
4620 void
4621 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4622 {
4623         g_return_if_fail (MODEST_IS_WINDOW (window));
4624
4625         /* Update dimmed */     
4626         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4627 }
4628
4629 void
4630 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4631 {
4632         g_return_if_fail (MODEST_IS_WINDOW (window));
4633
4634         modest_platform_show_search_messages (GTK_WINDOW (window));
4635 }
4636
4637 void     
4638 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4639 {
4640         g_return_if_fail (MODEST_IS_WINDOW (win));
4641         modest_platform_show_addressbook (GTK_WINDOW (win));
4642 }
4643
4644
4645 void
4646 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4647                                           ModestWindow *window)
4648 {
4649         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4650
4651         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4652 }
4653
4654 static void 
4655 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4656                                    ModestMailOperationState *state,
4657                                    gpointer user_data)
4658 {
4659         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4660
4661         /* Set send/receive operation finished */       
4662         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4663                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4664         
4665 }
4666
4667
4668 void 
4669 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
4670                                                 TnyHeader *header, 
4671                                                 TnyMsg *msg, 
4672                                                 GError *err, 
4673                                                 gpointer user_data)
4674 {
4675         const gchar* server_name = NULL;
4676         TnyTransportAccount *server_account;
4677         gchar *message = NULL;
4678
4679         /* Don't show anything if the user cancelled something */
4680         if (err->code == TNY_TRANSPORT_ACCOUNT_ERROR_SEND_USER_CANCEL)
4681                 return;
4682
4683         /* Get the server name: */
4684         server_account = 
4685                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
4686         if (server_account) {
4687                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
4688                         
4689                 g_object_unref (server_account);
4690                 server_account = NULL;
4691         }
4692         
4693         g_return_if_fail (server_name);
4694
4695         /* Show the appropriate message text for the GError: */
4696         switch (err->code) {
4697         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_HOST_LOOKUP_FAILED:
4698                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4699                 break;
4700         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_SERVICE_UNAVAILABLE:
4701                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
4702                 break;
4703         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND_AUTHENTICATION_NOT_SUPPORTED:
4704                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
4705                 break;
4706         case TNY_TRANSPORT_ACCOUNT_ERROR_SEND:
4707                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
4708                 break;
4709         default:
4710                 g_return_if_reached ();
4711         }
4712         
4713         /* TODO if the username or the password where not defined we
4714            should show the Accounts Settings dialog or the Connection
4715            specific SMTP server window */
4716
4717         modest_platform_run_information_dialog (NULL, message);
4718         g_free (message);
4719 }
4720
4721 void
4722 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
4723                                                 gchar *msg_id, 
4724                                                 guint status,
4725                                                 gpointer user_data)
4726 {
4727         ModestMainWindow *main_window = NULL;
4728         ModestWindowMgr *mgr = NULL;
4729         GtkWidget *folder_view = NULL, *header_view = NULL;
4730         TnyFolderStore *selected_folder = NULL;
4731         TnyFolderType folder_type;
4732
4733         mgr = modest_runtime_get_window_mgr ();
4734         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr));
4735
4736         if (!main_window)
4737                 return;
4738
4739         /* Check if selected folder is OUTBOX */
4740         folder_view = modest_main_window_get_child_widget (main_window,
4741                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4742         header_view = modest_main_window_get_child_widget (main_window,
4743                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4744
4745         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4746         if (!TNY_IS_FOLDER (selected_folder)) 
4747                 goto frees;
4748
4749         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
4750 #if GTK_CHECK_VERSION(2, 8, 0) 
4751         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
4752         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
4753                 GtkTreeViewColumn *tree_column;
4754
4755                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
4756                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
4757                 gtk_tree_view_column_queue_resize (tree_column);
4758         }
4759 #else
4760         gtk_widget_queue_draw (header_view);
4761 #endif          
4762         
4763         /* Free */
4764  frees:
4765         if (selected_folder != NULL)
4766                 g_object_unref (selected_folder);
4767 }