* set the local folders name to the device name if it exists,
[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 <string.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-msg.h>
38 #include <modest-tny-account.h>
39
40 #include "modest-ui-actions.h"
41
42 #include "modest-tny-platform-factory.h"
43
44 #include <widgets/modest-main-window.h>
45 #include <widgets/modest-msg-view-window.h>
46 #include <widgets/modest-account-view-window.h>
47
48 #include "modest-account-mgr-helpers.h"
49 #include "modest-mail-operation.h"
50 #include <modest-widget-memory.h>
51 #include <tny-error.h>
52 #include <tny-simple-list.h>
53 #include <tny-msg-view.h>
54 #include <tny-device.h>
55
56
57 typedef struct _GetMsgAsyncHelper {
58         ModestWindow *window;
59         TnyIterator *iter;
60         GFunc func;
61         gpointer user_data;
62 } GetMsgAsyncHelper;
63
64 typedef enum _ReplyForwardAction {
65         ACTION_REPLY,
66         ACTION_REPLY_TO_ALL,
67         ACTION_FORWARD
68 } ReplyForwardAction;
69
70 typedef struct _ReplyForwardHelper {
71 guint reply_forward_type;
72         ReplyForwardAction action;
73         gchar *account_name;
74 } ReplyForwardHelper;
75
76
77 static void     reply_forward_func     (gpointer data, gpointer user_data);
78 static void     read_msg_func          (gpointer data, gpointer user_data);
79 static void     get_msg_cb             (TnyFolder *folder, TnyMsg *msg, GError **err, 
80                                         gpointer user_data);
81 static void     reply_forward          (GtkWidget *widget, ReplyForwardAction action,
82                                         ModestWindow *win);
83 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
84
85
86 void   
87 modest_ui_actions_on_about (GtkWidget *widget, ModestWindow *win)
88 {
89         GtkWidget *about;
90         const gchar *authors[] = {
91                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
92                 NULL
93         };
94         about = gtk_about_dialog_new ();
95         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
96         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
97         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
98                                         _("Copyright (c) 2006, Nokia Corporation\n"
99                                           "All rights reserved."));
100         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
101                                        _("a modest e-mail client\n\n"
102                                          "design and implementation: Dirk-Jan C. Binnema\n"
103                                          "contributions from the fine people at KernelConcepts and Igalia\n"
104                                          "uses the tinymail email framework written by Philip van Hoof"));
105         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
106         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
107         
108         gtk_dialog_run (GTK_DIALOG (about));
109         gtk_widget_destroy(about);
110 }
111
112
113 static TnyList *
114 get_selected_headers (ModestWindow *win)
115 {
116         if (MODEST_IS_MAIN_WINDOW(win)) {
117                 GtkWidget *header_view;         
118                 
119                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
120                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
121                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
122                 
123         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
124                 /* for MsgViewWindows, we simply return a list with one element */
125                 TnyMsg *msg;
126                 TnyHeader *header;
127                 TnyList *list = NULL;
128                 
129                 msg  = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
130                 if (msg) {
131                         header = tny_msg_get_header (msg);
132                         list = tny_simple_list_new ();
133                         tny_list_prepend (list, G_OBJECT(header));
134                         g_object_unref (G_OBJECT(header));
135                 }
136                 return list;
137
138         } else
139                 return NULL;
140 }
141
142 void
143 modest_ui_actions_on_delete (GtkWidget *widget, ModestWindow *win)
144 {
145         TnyList *header_list;
146         TnyIterator *iter;
147
148         g_return_if_fail (MODEST_IS_WINDOW(win));
149                 
150         header_list = get_selected_headers (win);
151         
152         if (header_list) {
153                 iter = tny_list_create_iterator (header_list);
154                 do {
155                         TnyHeader *header;
156                         ModestMailOperation *mail_op;
157
158                         header = TNY_HEADER (tny_iterator_get_current (iter));
159                         /* TODO: thick grain mail operation involving
160                            a list of objects. Composite pattern ??? */
161                         mail_op = modest_mail_operation_new ();
162
163                         /* TODO: add confirmation dialog */
164
165                         /* Move to trash. TODO: Still not supported */
166                         modest_mail_operation_remove_msg (mail_op, header, FALSE);
167
168                         if (modest_mail_operation_get_status (mail_op) !=
169                             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
170                                 const GError *error;
171                                 error = modest_mail_operation_get_error (mail_op);
172                                 if (error)
173                                         g_warning (error->message);
174                         }
175
176                         g_object_unref (G_OBJECT (mail_op));
177                         g_object_unref (header);
178                         tny_iterator_next (iter);
179
180                 } while (!tny_iterator_is_done (iter));
181         }
182 }
183
184
185 void
186 modest_ui_actions_on_quit (GtkWidget *widget, ModestWindow *win)
187 {
188         /* FIXME: save size of main window */
189 /*      save_sizes (main_window); */
190         gtk_widget_destroy (GTK_WIDGET (win));
191 }
192
193 void
194 modest_ui_actions_on_accounts (GtkWidget *widget, ModestWindow *win)
195 {
196         GtkWidget *account_win;
197         account_win = modest_account_view_window_new ();
198
199         if (win)
200                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win));
201
202         gtk_widget_show (account_win);
203 }
204
205 void
206 modest_ui_actions_on_new_msg (GtkWidget *widget, ModestWindow *win)
207 {
208         ModestWindow *msg_win;
209         TnyMsg *msg = NULL;
210         TnyFolder *folder = NULL;
211         gchar *account_name = NULL;
212         gchar *from_str = NULL;
213         GError *err = NULL;
214         TnyAccount *account;
215         
216         account_name = g_strdup(modest_window_get_active_account (win));
217         if (!account_name)
218                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
219         
220         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
221                                                                        account_name,
222                                                                        TNY_ACCOUNT_TYPE_STORE);
223         if (!account) {
224                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
225                 goto cleanup;
226         }
227
228         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
229
230         msg    = modest_tny_msg_new ("", from_str, "", "", "", "", NULL);
231         if (!msg) {
232                 g_printerr ("modest: failed to create new msg\n");
233                 goto cleanup;
234         }
235         
236         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
237         if (!folder) {
238                 g_printerr ("modest: failed to find Drafts folder\n");
239                 goto cleanup;
240         }
241         
242         tny_folder_add_msg (folder, msg, &err);
243         if (err) {
244                 g_printerr ("modest: error adding msg to Drafts folder: %s",
245                             err->message);
246                 g_error_free (err);
247                 goto cleanup;
248         }
249
250         msg_win = modest_msg_edit_window_new (msg, account_name);
251         if (win)
252                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
253                                               GTK_WINDOW (win));        
254         gtk_widget_show_all (GTK_WIDGET (msg_win));
255
256 cleanup:
257         g_free (account_name);
258         g_free (from_str);
259         if (account)
260                 g_object_unref (G_OBJECT(account));
261         if (msg)
262                 g_object_unref (G_OBJECT(msg));
263         if (folder)
264                 g_object_unref (G_OBJECT(folder));
265 }
266
267
268 void
269 modest_ui_actions_on_open (GtkWidget *widget, ModestWindow *win)
270 {
271         modest_runtime_not_implemented (GTK_WINDOW(win)); /* FIXME */
272 }
273
274
275
276 static void
277 reply_forward_func (gpointer data, gpointer user_data)
278 {
279         TnyMsg *msg, *new_msg;
280         GetMsgAsyncHelper *helper;
281         ReplyForwardHelper *rf_helper;
282         ModestWindow *msg_win;
283         ModestEditType edit_type;
284         gchar *from;
285         GError *err = NULL;
286         TnyFolder *folder = NULL;
287         TnyAccount *account = NULL;
288         
289         msg = TNY_MSG (data);
290         helper = (GetMsgAsyncHelper *) user_data;
291         rf_helper = (ReplyForwardHelper *) helper->user_data;
292
293         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
294                                                    rf_helper->account_name);
295         /* Create reply mail */
296         switch (rf_helper->action) {
297         case ACTION_REPLY:
298                 new_msg = 
299                         modest_mail_operation_create_reply_mail (msg,  from, 
300                                                                  rf_helper->reply_forward_type,
301                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
302                 break;
303         case ACTION_REPLY_TO_ALL:
304                 new_msg = 
305                         modest_mail_operation_create_reply_mail (msg, from, rf_helper->reply_forward_type,
306                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
307                 edit_type = MODEST_EDIT_TYPE_REPLY;
308                 break;
309         case ACTION_FORWARD:
310                 new_msg = 
311                         modest_mail_operation_create_forward_mail (msg, from, rf_helper->reply_forward_type);
312                 edit_type = MODEST_EDIT_TYPE_FORWARD;
313                 break;
314         default:
315                 g_return_if_reached ();
316                 return;
317         }
318
319         if (!new_msg) {
320                 g_printerr ("modest: failed to create message\n");
321                 goto cleanup;
322         }
323
324         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
325                                                                        rf_helper->account_name,
326                                                                        TNY_ACCOUNT_TYPE_STORE);
327         if (!account) {
328                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
329                 goto cleanup;
330         }
331
332         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
333         if (!folder) {
334                 g_printerr ("modest: failed to find Drafts folder\n");
335                 goto cleanup;
336         }
337         
338         tny_folder_add_msg (folder, msg, &err);
339         if (err) {
340                 g_printerr ("modest: error adding msg to Drafts folder: %s",
341                             err->message);
342                 g_error_free (err);
343                 goto cleanup;
344         }       
345                         
346         /* Show edit window */
347         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
348         gtk_widget_show_all (GTK_WIDGET (msg_win));
349
350 cleanup:
351         if (new_msg)
352                 g_object_unref (G_OBJECT (new_msg));
353         if (folder)
354                 g_object_unref (G_OBJECT (folder));
355         if (account)
356                 g_object_unref (G_OBJECT (account));
357         
358         g_free (rf_helper->account_name);
359         g_slice_free (ReplyForwardHelper, rf_helper);
360 }
361 /*
362  * Common code for the reply and forward actions
363  */
364 static void
365 reply_forward (GtkWidget *widget, ReplyForwardAction action, ModestWindow *win)
366 {
367         TnyList *header_list;
368         guint reply_forward_type;
369         TnyHeader *header;
370         TnyFolder *folder;
371         GetMsgAsyncHelper *helper;
372         ReplyForwardHelper *rf_helper;
373         
374         g_return_if_fail (MODEST_IS_WINDOW(win));
375
376         header_list = get_selected_headers (win);
377         if (!header_list)
378                 return;
379         
380         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
381                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
382                                                   NULL);
383         /* We assume that we can only select messages of the
384            same folder and that we reply all of them from the
385            same account. In fact the interface currently only
386            allows single selection */
387         
388         /* Fill helpers */
389         rf_helper = g_slice_new0 (ReplyForwardHelper);
390         rf_helper->reply_forward_type = reply_forward_type;
391         rf_helper->action = action;
392
393         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
394         if (!rf_helper->account_name)
395                 rf_helper->account_name =
396                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
397
398         helper = g_slice_new0 (GetMsgAsyncHelper);
399         helper->window = win;
400         helper->func = reply_forward_func;
401         helper->iter = tny_list_create_iterator (header_list);
402         helper->user_data = rf_helper;
403
404         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
405                 TnyMsg *msg;
406                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
407                 if (!msg) {
408                         g_printerr ("modest: no message found\n");
409                         return;
410                 } else
411                         reply_forward_func (msg, helper);
412         } else {
413                 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
414                 folder = tny_header_get_folder (header);
415                 if (folder) {
416                         /* The callback will call it per each header */
417                         tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
418                         g_object_unref (G_OBJECT (folder));
419                 } else 
420                         g_printerr ("modest: no folder for header\n");
421                 
422                 /* Clean */
423                 g_object_unref (G_OBJECT (header));
424         }
425 }
426
427
428 void
429 modest_ui_actions_on_reply (GtkWidget *widget, ModestWindow *win)
430 {
431         g_return_if_fail (MODEST_IS_WINDOW(win));
432
433         reply_forward (widget, ACTION_REPLY, win);
434 }
435
436 void
437 modest_ui_actions_on_forward (GtkWidget *widget, ModestWindow *win)
438 {
439         g_return_if_fail (MODEST_IS_WINDOW(win));
440
441         reply_forward (widget, ACTION_FORWARD, win);
442 }
443
444 void
445 modest_ui_actions_on_reply_all (GtkWidget *widget,ModestWindow *win)
446 {
447         g_return_if_fail (MODEST_IS_WINDOW(win));
448
449         reply_forward (widget, ACTION_REPLY_TO_ALL, win);
450 }
451
452 void 
453 modest_ui_actions_on_next (GtkWidget *widget, 
454                            ModestMainWindow *main_window)
455 {
456         GtkWidget *header_view;
457         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
458
459         header_view = modest_main_window_get_child_widget (main_window,
460                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
461         if (!header_view)
462                 return;
463         
464         modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
465 }
466
467 void 
468 modest_ui_actions_on_prev (GtkWidget *widget, 
469                            ModestMainWindow *main_window)
470 {
471         GtkWidget *header_view;
472         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
473
474         header_view = modest_main_window_get_child_widget (main_window,
475                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
476         if (!header_view)
477                 return;
478         
479         modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
480 }
481
482
483 void
484 modest_ui_actions_on_send_receive (GtkWidget *widget,  ModestWindow *win)
485 {
486         gchar *account_name;
487         TnyAccount *tny_account;
488         ModestTnySendQueue *send_queue;
489         
490         account_name =
491                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
492         if (!account_name)
493                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
494         if (!account_name) {
495                 g_printerr ("modest: cannot get account\n");
496                 return;
497         }
498         
499         tny_account = 
500                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
501                                                                      account_name,
502                                                                      TNY_ACCOUNT_TYPE_TRANSPORT);
503         if (!tny_account) {
504                 g_printerr ("modest: cannot get tny transport account\n");
505                 return;
506         }
507
508         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
509         modest_tny_send_queue_flush (send_queue);
510
511         g_object_unref (G_OBJECT(send_queue));
512         g_object_unref (G_OBJECT(tny_account));
513 }
514
515
516
517 void
518 modest_ui_actions_toggle_view (GtkWidget *widget, ModestMainWindow *main_window)
519 {
520         ModestConf *conf;
521         GtkWidget *header_view;
522         
523         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
524
525         header_view = modest_main_window_get_child_widget (main_window,
526                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
527         if (!header_view)
528                 return;
529
530         conf = modest_runtime_get_conf ();
531         
532         /* what is saved/restored is depending on the style; thus; we save with
533          * old style, then update the style, and restore for this new style*/
534         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
535         
536         if (modest_header_view_get_style
537             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
538                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
539                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
540         else
541                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
542                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
543
544         modest_widget_memory_restore (conf, G_OBJECT(header_view),
545                                       "header-view");
546 }
547
548
549
550 /*
551  * Marks a message as read and passes it to the msg preview widget
552  */
553 static void
554 read_msg_func (gpointer data, gpointer user_data)
555 {
556         TnyMsg *msg;
557         TnyHeader *header;
558         GetMsgAsyncHelper *helper;
559         TnyHeaderFlags header_flags;
560         GtkWidget *msg_preview;
561         
562         msg = TNY_MSG (data);
563         helper = (GetMsgAsyncHelper *) user_data;
564
565         msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
566                                                            MODEST_WIDGET_TYPE_MSG_PREVIEW);
567         if (!msg_preview)
568                 return;
569         
570         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
571         header_flags = tny_header_get_flags (header);
572         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
573         g_object_unref (G_OBJECT (header));
574
575         /* Set message on msg view */
576         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
577 }
578
579 /*
580  * This function is a generic handler for the tny_folder_get_msg_async
581  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
582  * contains a user provided function that is called inside this
583  * method. This will allow us to use this callback in many different
584  * places. This callback performs the common actions for the
585  * get_msg_async call, more specific actions will be done by the user
586  * function
587  */
588 static void
589 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
590 {
591         GetMsgAsyncHelper *helper;
592
593         helper = (GetMsgAsyncHelper *) user_data;
594
595         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
596                 modest_ui_actions_on_item_not_found (NULL,
597                                                      MODEST_ITEM_TYPE_MESSAGE,
598                                                      helper->window);
599                 return;
600         }
601
602         /* Call user function */
603         helper->func (msg, user_data);
604
605         /* Process next element (if exists) */
606         tny_iterator_next (helper->iter);
607         if (tny_iterator_is_done (helper->iter)) {
608                 TnyList *headers;
609                 headers = tny_iterator_get_list (helper->iter);
610                 /* Free resources */
611                 g_object_unref (G_OBJECT (headers));
612                 g_object_unref (G_OBJECT (helper->iter));
613                 g_slice_free (GetMsgAsyncHelper, helper);
614         } else {
615                 TnyHeader *header;
616                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
617                 tny_folder_get_msg_async (folder, header,                         
618                                           get_msg_cb, helper);
619                 g_object_unref (G_OBJECT(header));
620         }
621 }
622
623 void 
624 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view, 
625                                       TnyHeader *header,
626                                       ModestMainWindow *main_window)
627 {
628         GtkWidget *msg_preview;
629         TnyFolder *folder;
630         GetMsgAsyncHelper *helper;
631         TnyList *list;
632
633         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
634         
635         msg_preview = modest_main_window_get_child_widget(main_window,
636                                                           MODEST_WIDGET_TYPE_MSG_PREVIEW);
637         if (!msg_preview)
638                 return;
639         
640         /* when there's no header, clear the msgview */
641         if (!header) {
642                 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
643                 return;
644         }
645
646         folder = tny_header_get_folder (TNY_HEADER(header));
647
648         /* Create list */
649         list = tny_simple_list_new ();
650         tny_list_prepend (list, G_OBJECT (header));
651
652         /* Fill helper data */
653         helper = g_slice_new0 (GetMsgAsyncHelper);
654         helper->window = MODEST_WINDOW (main_window);
655         helper->iter = tny_list_create_iterator (list);
656         helper->func = read_msg_func;
657
658         tny_folder_get_msg_async (TNY_FOLDER(folder),
659                                   header, get_msg_cb,
660                                   helper);
661
662         /* Frees */
663         g_object_unref (G_OBJECT (folder));
664 }
665
666
667
668 void 
669 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
670                                        ModestMainWindow *main_window)
671 {
672         ModestWindow *win;
673         TnyFolder *folder = NULL;
674         TnyMsg    *msg    = NULL;
675         gchar *account    = NULL;
676         
677         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
678         
679         if (!header)
680                 return;
681
682         folder = tny_header_get_folder (header);
683         if (!folder) {
684                 g_printerr ("modest: cannot get folder for header\n");
685                 goto cleanup;
686         }
687
688         /* FIXME: make async?; check error  */
689         msg = tny_folder_get_msg (folder, header, NULL);
690         if (!msg) {
691                 g_printerr ("modest: cannot get msg for header\n");
692                 goto cleanup;
693         }
694
695         account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
696         if (!account)
697                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
698         
699         win = modest_msg_view_window_new (msg, account);
700         gtk_window_set_transient_for (GTK_WINDOW (win),
701                                       GTK_WINDOW (main_window));
702
703         gtk_widget_show_all (GTK_WIDGET(win));
704         
705 cleanup:
706         g_free (account);
707         
708         if (folder)
709                 g_object_unref (G_OBJECT (folder));
710         if (msg)
711                 g_object_unref (G_OBJECT (msg));
712 }
713
714 void 
715 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
716                                                TnyFolder *folder, 
717                                                gboolean selected,
718                                                ModestMainWindow *main_window)
719 {
720 //      GtkLabel *folder_info_label;
721         gchar *txt;     
722         ModestConf *conf;
723         GtkWidget *header_view;
724         
725 /*      folder_info_label =  */
726 /*              GTK_LABEL (modest_widget_factory_get_folder_info_label */
727 /*                         (modest_runtime_get_widget_factory())); */
728
729 /*      if (!folder) { */
730 /*              gtk_label_set_label (GTK_LABEL(folder_info_label), ""); */
731 /*              return; */
732 /*      } */
733         
734         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
735
736         header_view = modest_main_window_get_child_widget(main_window,
737                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
738         if (!header_view)
739                 return;
740         
741         conf = modest_runtime_get_conf ();
742
743         if (!selected) { /* the folder was unselected; save it's settings  */
744                 modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
745                 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
746                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
747         } else {  /* the folder was selected */
748                 if (folder) { /* folder may be NULL */
749                         guint num, unread;
750                         gchar *title;
751
752                         num    = tny_folder_get_all_count    (folder);
753                         unread = tny_folder_get_unread_count (folder);
754                         
755                         title = g_strdup_printf ("Modest: %s",
756                                                  tny_folder_get_name (folder));
757                         
758                         gtk_window_set_title (GTK_WINDOW(main_window), title);
759                         g_free (title);
760                         
761                         txt = g_strdup_printf (_("%d %s, %d unread"),
762                                                num, num==1 ? _("item") : _("items"), unread);           
763                         //gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
764                         g_free (txt);
765                 }
766                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
767                 modest_widget_memory_restore (conf, G_OBJECT(header_view),
768                                               "header-view");
769         }
770 }
771
772
773 /****************************************************/
774 /*
775  * below some stuff to clearup statusbar messages after 1,5 seconds....
776  */
777 static gboolean
778 progress_bar_clean (GtkWidget *bar)
779 {
780         if (GTK_IS_PROGRESS_BAR(bar)) {
781                 gtk_progress_bar_set_text     (GTK_PROGRESS_BAR(bar), "");
782                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
783         }
784         return FALSE;
785 }
786
787 static gboolean
788 statusbar_clean (GtkWidget *bar)
789 {
790         if (GTK_IS_STATUSBAR(bar))
791                 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
792         return FALSE;
793 }
794
795
796 static void
797 statusbar_push (ModestMainWindow *main_window, guint context_id, const gchar *msg)
798 {
799         if (!msg)
800                 return;
801
802         GtkWidget *progress_bar, *status_bar;
803
804         progress_bar = modest_main_window_get_child_widget (main_window,
805                                                             MODEST_WIDGET_TYPE_PROGRESS_BAR);
806         status_bar = modest_main_window_get_child_widget (main_window,
807                                                           MODEST_WIDGET_TYPE_STATUS_BAR);
808         if (progress_bar) {
809                 gtk_widget_show (progress_bar);
810                 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
811         }
812         
813         if (status_bar) {
814                 gtk_widget_show (status_bar);
815                 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
816                 g_timeout_add (2500, (GSourceFunc)statusbar_clean, status_bar);
817         }
818
819 }
820 /****************************************************************************/
821
822 void 
823 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
824                                      ModestWindow *win)
825 {
826         GtkWidget *dialog;
827         gchar *txt, *item;
828         gboolean online;
829
830         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
831         
832         if (g_main_depth > 0)   
833                 gdk_threads_enter ();
834         online = tny_device_is_online (modest_runtime_get_device());
835
836         if (online) {
837                 /* already online -- the item is simply not there... */
838                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
839                                                  GTK_DIALOG_MODAL,
840                                                  GTK_MESSAGE_WARNING,
841                                                  GTK_BUTTONS_OK,
842                                                  _("The %s you selected cannot be found"),
843                                                  item);
844                 gtk_dialog_run (GTK_DIALOG(dialog));
845         } else {
846                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
847                                                       GTK_WINDOW (win),
848                                                       GTK_DIALOG_MODAL,
849                                                       GTK_STOCK_CANCEL,
850                                                       GTK_RESPONSE_REJECT,
851                                                       GTK_STOCK_OK,
852                                                       GTK_RESPONSE_ACCEPT,
853                                                       NULL);
854                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
855                                          "Do you want to get online?"), item);
856                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
857                                     gtk_label_new (txt), FALSE, FALSE, 0);
858                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
859                 g_free (txt);
860
861                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
862                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
863                         tny_device_force_online (modest_runtime_get_device());
864                 }
865         }
866         gtk_widget_destroy (dialog);
867         if (g_main_depth > 0)   
868                 gdk_threads_leave ();
869 }
870
871
872
873 void
874 modest_ui_actions_on_header_status_update (ModestHeaderView *header_view, 
875                                             const gchar *msg, gint num, 
876                                             gint total,  ModestMainWindow *main_window)
877 {
878         char* txt;
879         GtkWidget *progress_bar;
880
881         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
882
883         progress_bar = modest_main_window_get_child_widget (main_window, 
884                                                             MODEST_WIDGET_TYPE_PROGRESS_BAR);   
885         if (!progress_bar)
886                 return;
887         
888         if (total != 0)
889                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
890                                                (gdouble)num/(gdouble)total);
891         else
892                 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
893
894         txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
895         gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
896         g_free (txt);
897         
898         statusbar_push (main_window, 0, msg);
899 }
900
901
902 void
903 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
904                                      ModestWindow *win)
905 {
906         g_message (__FUNCTION__);
907 }       
908
909
910 void
911 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
912                                         ModestWindow *win)
913 {
914         g_message (__FUNCTION__);
915 }
916
917 void
918 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, int index,
919                                              ModestWindow *win)
920 {
921         g_message (__FUNCTION__);
922         
923 }
924
925 void
926 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
927 {
928         TnyTransportAccount *transport_account;
929         ModestMailOperation *mail_operation;
930         MsgData *data;
931         gchar *account_name, *from;
932         ModestAccountMgr *account_mgr;
933
934         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
935         
936         data = modest_msg_edit_window_get_msg_data (edit_window);
937
938         /* FIXME: Code added just for testing. The final version will
939            use the send queue provided by tinymail and some
940            classifier */
941         account_mgr = modest_runtime_get_account_mgr();
942         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
943         if (!account_name) 
944                 account_name = modest_account_mgr_get_default_account (account_mgr);
945         if (!account_name) {
946                 g_printerr ("modest: no account found\n");
947                 modest_msg_edit_window_free_msg_data (edit_window, data);
948                 return;
949         }
950         transport_account =
951                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
952                                       (modest_runtime_get_account_store(),
953                                        account_name,
954                                        TNY_ACCOUNT_TYPE_TRANSPORT));
955         if (!transport_account) {
956                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
957                 g_free (account_name);
958                 modest_msg_edit_window_free_msg_data (edit_window, data);
959                 return;
960         }
961         from = modest_account_mgr_get_from_string (account_mgr, account_name);
962                 
963         mail_operation = modest_mail_operation_new ();
964         modest_mail_operation_send_new_mail (mail_operation,
965                                              transport_account,
966                                              from,
967                                              data->to, 
968                                              data->cc, 
969                                              data->bcc,
970                                              data->subject, 
971                                              data->body, 
972                                              NULL);
973         /* Frees */
974         g_free (from);
975         g_free (account_name);
976         g_object_unref (G_OBJECT (mail_operation));
977         g_object_unref (G_OBJECT (transport_account));
978
979         modest_msg_edit_window_free_msg_data (edit_window, data);
980
981         /* Save settings and close the window */
982         /* save_settings (edit_window) */
983         gtk_widget_destroy (GTK_WIDGET (edit_window));
984 }
985
986 /*
987  * Shows a dialog with an entry that asks for some text. The returned
988  * value must be freed by the caller. The dialog window title will be
989  * set to @title.
990  */
991 static gchar *
992 ask_for_folder_name (GtkWindow *parent_window,
993                      const gchar *title)
994 {
995         GtkWidget *dialog, *entry;
996         gchar *folder_name = NULL;
997
998         /* Ask for folder name */
999         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1000                                               parent_window,
1001                                               GTK_DIALOG_MODAL,
1002                                               GTK_STOCK_CANCEL,
1003                                               GTK_RESPONSE_REJECT,
1004                                               GTK_STOCK_OK,
1005                                               GTK_RESPONSE_ACCEPT,
1006                                               NULL);
1007         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1008                             gtk_label_new(title),
1009                             FALSE, FALSE, 0);
1010                 
1011         entry = gtk_entry_new_with_max_length (40);
1012         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1013                             entry,
1014                             TRUE, FALSE, 0);    
1015         
1016         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1017         
1018         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1019                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1020
1021         gtk_widget_destroy (dialog);
1022
1023         return folder_name;
1024 }
1025
1026 void 
1027 modest_ui_actions_on_new_folder (GtkWidget *widget, ModestMainWindow *main_window)
1028 {
1029         TnyFolder *parent_folder;
1030         GtkWidget *folder_view;
1031         
1032         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1033
1034         folder_view = modest_main_window_get_child_widget (main_window,
1035                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1036         if (!folder_view)
1037                 return;
1038
1039         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1040         
1041         if (parent_folder) {
1042                 gchar *folder_name;
1043
1044                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1045                                                    _("Please enter a name for the new folder"));
1046
1047                 if (folder_name != NULL && strlen (folder_name) > 0) {
1048                         TnyFolder *new_folder;
1049                         ModestMailOperation *mail_op;
1050
1051                         mail_op = modest_mail_operation_new ();
1052                         new_folder = modest_mail_operation_create_folder (mail_op,
1053                                                                           TNY_FOLDER_STORE (parent_folder),
1054                                                                           (const gchar *) folder_name);
1055                         if (new_folder) {
1056                                 g_object_unref (new_folder);
1057                         } else {
1058                                 const GError *error;
1059                                 error = modest_mail_operation_get_error (mail_op);
1060                                 if (error)
1061                                         g_warning ("Error adding a subfolder: %s\n", error->message);
1062                         }
1063                         g_object_unref (mail_op);
1064                 }
1065                 g_object_unref (parent_folder);
1066         }
1067 }
1068
1069 void 
1070 modest_ui_actions_on_rename_folder (GtkWidget *widget,
1071                                      ModestMainWindow *main_window)
1072 {
1073         TnyFolder *folder;
1074         GtkWidget *folder_view;
1075         
1076         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1077
1078         folder_view = modest_main_window_get_child_widget (main_window,
1079                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1080         if (!folder_view)
1081                 return;
1082         
1083         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1084         
1085         if (folder) {
1086                 gchar *folder_name;
1087                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1088                                                    _("Please enter a new name for the folder"));
1089
1090                 if (folder_name != NULL && strlen (folder_name) > 0) {
1091                         ModestMailOperation *mail_op;
1092                         const GError *error;
1093
1094                         mail_op = modest_mail_operation_new ();
1095                         modest_mail_operation_rename_folder (mail_op,
1096                                                              folder,
1097                                                              (const gchar *) folder_name);
1098
1099                         error = modest_mail_operation_get_error (mail_op);
1100                         if (error)
1101                                 /* TODO: notify error ? */
1102                                 g_warning ("Could not rename a folder: %s\n", error->message);
1103
1104                         g_object_unref (mail_op);
1105                 }
1106                 g_object_unref (folder);
1107         }
1108 }
1109
1110 static void
1111 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1112 {
1113         TnyFolder *folder;
1114         ModestMailOperation *mail_op;
1115         GtkWidget *folder_view;
1116         const GError *error;
1117         
1118         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1119
1120         folder_view = modest_main_window_get_child_widget (main_window,
1121                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1122         if (!folder_view)
1123                 return;
1124
1125         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1126         
1127         mail_op = modest_mail_operation_new ();
1128         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1129
1130         error = modest_mail_operation_get_error (mail_op);
1131         if (error)
1132                 g_warning ("%s\n", error->message);
1133
1134         g_object_unref (mail_op);
1135 }
1136
1137 void 
1138 modest_ui_actions_on_delete_folder (GtkWidget *widget,
1139                                      ModestMainWindow *main_window)
1140 {
1141         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1142
1143         delete_folder (main_window, FALSE);
1144 }
1145
1146 void 
1147 modest_ui_actions_on_move_folder_to_trash_folder (GtkWidget *widget, ModestMainWindow *main_window)
1148 {
1149         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1150         
1151         delete_folder (main_window, TRUE);
1152 }
1153
1154 void
1155 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1156                                          const gchar* account_name,
1157                                          gchar **password, 
1158                                          gboolean *cancel, 
1159                                          gboolean *remember,
1160                                          ModestMainWindow *main_window)
1161 {
1162         gchar *txt;
1163         GtkWidget *dialog, *entry, *remember_pass_check;
1164
1165         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1166                                               NULL,
1167                                               GTK_DIALOG_MODAL,
1168                                               GTK_STOCK_CANCEL,
1169                                               GTK_RESPONSE_REJECT,
1170                                               GTK_STOCK_OK,
1171                                               GTK_RESPONSE_ACCEPT,
1172                                               NULL);
1173         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1174         
1175         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1176         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1177                             FALSE, FALSE, 0);
1178         g_free (txt);
1179
1180         entry = gtk_entry_new_with_max_length (40);
1181         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1182         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1183         
1184         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1185                             TRUE, FALSE, 0);    
1186
1187         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1188         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1189                             TRUE, FALSE, 0);
1190
1191         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1192         
1193         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1194                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1195                 *cancel   = FALSE;
1196         } else {
1197                 *password = NULL;
1198                 *cancel   = TRUE;
1199         }
1200
1201         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1202                 *remember = TRUE;
1203         else
1204                 *remember = FALSE;
1205
1206         gtk_widget_destroy (dialog);
1207 }