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