* Modified the order of the widget creation proccess
[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, 
537                                       TnyHeader *header,
538                                       ModestMainWindow *main_window)
539 {
540         GtkWidget *msg_preview;
541         TnyFolder *folder;
542         GetMsgAsyncHelper *helper;
543         TnyList *list;
544
545         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
546         
547         msg_preview = modest_main_window_get_child_widget(main_window,
548                                                           MODEST_WIDGET_TYPE_MSG_PREVIEW);
549         if (!msg_preview)
550                 return;
551         
552         /* when there's no header, clear the msgview */
553         if (!header) {
554                 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
555                 return;
556         }
557
558         folder = tny_header_get_folder (TNY_HEADER(header));
559
560         /* Create list */
561         list = tny_simple_list_new ();
562         tny_list_prepend (list, G_OBJECT (header));
563
564         /* Fill helper data */
565         helper = g_slice_new0 (GetMsgAsyncHelper);
566         helper->main_window = main_window;
567         helper->iter = tny_list_create_iterator (list);
568         helper->func = read_msg_func;
569
570         tny_folder_get_msg_async (TNY_FOLDER(folder),
571                                   header, get_msg_cb,
572                                   helper);
573
574         /* Frees */
575         g_object_unref (G_OBJECT (folder));
576 }
577
578
579
580 void 
581 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
582                                        ModestMainWindow *main_window)
583 {
584         ModestWindow *win;
585         TnyFolder *folder = NULL;
586         TnyMsg    *msg    = NULL;
587         gchar *account    = NULL;
588         
589         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
590         
591         if (!header)
592                 return;
593
594         folder = tny_header_get_folder (header);
595         if (!folder) {
596                 g_printerr ("modest: cannot get folder for header\n");
597                 goto cleanup;
598         }
599
600         /* FIXME: make async?; check error  */
601         msg = tny_folder_get_msg (folder, header, NULL);
602         if (!msg) {
603                 g_printerr ("modest: cannot get msg for header\n");
604                 goto cleanup;
605         }
606
607         account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
608         if (!account)
609                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
610         
611         win = modest_msg_view_window_new (msg, account);
612         gtk_window_set_transient_for (GTK_WINDOW (win),
613                                       GTK_WINDOW (main_window));
614
615         gtk_widget_show_all (GTK_WIDGET(win));
616         
617 cleanup:
618         g_free (account);
619         
620         if (folder)
621                 g_object_unref (G_OBJECT (folder));
622         if (msg)
623                 g_object_unref (G_OBJECT (folder));
624 }
625
626
627
628
629
630 void 
631 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
632                                                TnyFolder *folder, 
633                                                gboolean selected,
634                                                ModestMainWindow *main_window)
635 {
636 //      GtkLabel *folder_info_label;
637         gchar *txt;     
638         ModestConf *conf;
639         GtkWidget *header_view;
640         
641 /*      folder_info_label =  */
642 /*              GTK_LABEL (modest_widget_factory_get_folder_info_label */
643 /*                         (modest_runtime_get_widget_factory())); */
644
645 /*      if (!folder) { */
646 /*              gtk_label_set_label (GTK_LABEL(folder_info_label), ""); */
647 /*              return; */
648 /*      } */
649         
650         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
651
652         header_view = modest_main_window_get_child_widget(main_window,
653                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
654         if (!header_view)
655                 return;
656         
657         conf = modest_runtime_get_conf ();
658
659         if (!selected) { /* the folder was unselected; save it's settings  */
660                 modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
661                 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
662                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
663         } else {  /* the folder was selected */
664                 if (folder) { /* folder may be NULL */
665                         guint num, unread;
666                         gchar *title;
667
668                         num    = tny_folder_get_all_count    (folder);
669                         unread = tny_folder_get_unread_count (folder);
670                         
671                         title = g_strdup_printf ("Modest: %s",
672                                                  tny_folder_get_name (folder));
673                         
674                         gtk_window_set_title (GTK_WINDOW(main_window), title);
675                         g_free (title);
676                         
677                         txt = g_strdup_printf (_("%d %s, %d unread"),
678                                                num, num==1 ? _("item") : _("items"), unread);           
679                         //gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
680                         g_free (txt);
681                 }
682                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
683                 modest_widget_memory_restore (conf, G_OBJECT(header_view),
684                                               "header-view");
685         }
686 }
687
688
689 /****************************************************/
690 /*
691  * below some stuff to clearup statusbar messages after 1,5 seconds....
692  */
693 static gboolean
694 progress_bar_clean (GtkWidget *bar)
695 {
696         if (GTK_IS_PROGRESS_BAR(bar)) {
697                 gtk_progress_bar_set_text     (GTK_PROGRESS_BAR(bar), "");
698                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(bar), 1.0);
699         }
700         return FALSE;
701 }
702
703 static gboolean
704 statusbar_clean (GtkWidget *bar)
705 {
706         if (GTK_IS_STATUSBAR(bar))
707                 gtk_statusbar_push (GTK_STATUSBAR(bar), 0, "");
708         return FALSE;
709 }
710
711
712 static void
713 statusbar_push (ModestMainWindow *main_window, guint context_id, const gchar *msg)
714 {
715         if (!msg)
716                 return;
717
718         GtkWidget *progress_bar, *status_bar;
719
720         progress_bar = modest_main_window_get_child_widget (main_window,
721                                                             MODEST_WIDGET_TYPE_PROGRESS_BAR);
722         status_bar = modest_main_window_get_child_widget (main_window,
723                                                           MODEST_WIDGET_TYPE_STATUS_BAR);
724         if (progress_bar) {
725                 gtk_widget_show (progress_bar);
726                 g_timeout_add (3000, (GSourceFunc)progress_bar_clean, progress_bar);
727         }
728         
729         if (status_bar) {
730                 gtk_widget_show (status_bar);
731                 gtk_statusbar_push (GTK_STATUSBAR(status_bar), 0, msg);
732                 g_timeout_add (1500, (GSourceFunc)statusbar_clean, status_bar);
733         }
734
735 }
736 /****************************************************************************/
737
738 void 
739 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
740                                      ModestWindow *win)
741 {
742         GtkWidget *dialog;
743         gchar *txt, *item;
744         gboolean online;
745         TnyDevice *device;
746         TnyAccountStore *account_store;
747
748         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
749         
750         /* Get device. Do not ask the platform factory for it, because
751            it returns always a new one */
752         account_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store ());
753         device = tny_account_store_get_device (account_store);
754
755         if (g_main_depth > 0)   
756                 gdk_threads_enter ();
757         online = tny_device_is_online (device);
758
759         if (online) {
760                 /* already online -- the item is simply not there... */
761                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
762                                                  GTK_DIALOG_MODAL,
763                                                  GTK_MESSAGE_WARNING,
764                                                  GTK_BUTTONS_OK,
765                                                  _("The %s you selected cannot be found"),
766                                                  item);
767                 gtk_dialog_run (GTK_DIALOG(dialog));
768         } else {
769                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
770                                                       GTK_WINDOW (win),
771                                                       GTK_DIALOG_MODAL,
772                                                       GTK_STOCK_CANCEL,
773                                                       GTK_RESPONSE_REJECT,
774                                                       GTK_STOCK_OK,
775                                                       GTK_RESPONSE_ACCEPT,
776                                                       NULL);
777                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
778                                          "Do you want to get online?"), item);
779                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
780                                     gtk_label_new (txt), FALSE, FALSE, 0);
781                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
782                 g_free (txt);
783
784                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
785                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
786                         tny_device_force_online (device);
787                 }
788         }
789         gtk_widget_destroy (dialog);
790         if (g_main_depth > 0)   
791                 gdk_threads_leave ();
792 }
793
794
795
796 void
797 modest_ui_actions_on_header_status_update (ModestHeaderView *header_view, 
798                                             const gchar *msg, gint num, 
799                                             gint total,  ModestMainWindow *main_window)
800 {
801         char* txt;
802         GtkWidget *progress_bar;
803
804         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
805
806         progress_bar = modest_main_window_get_child_widget (main_window, 
807                                                             MODEST_WIDGET_TYPE_PROGRESS_BAR);   
808         if (!progress_bar)
809                 return;
810         
811         if (total != 0)
812                 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR(progress_bar),
813                                                (gdouble)num/(gdouble)total);
814         else
815                 gtk_progress_bar_pulse (GTK_PROGRESS_BAR(progress_bar));
816
817         txt = g_strdup_printf (_("Downloading %d of %d"), num, total);
818         gtk_progress_bar_set_text (GTK_PROGRESS_BAR(progress_bar), txt);
819         g_free (txt);
820         
821         statusbar_push (main_window, 0, msg);
822 }
823
824
825 void
826 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
827                                      ModestWindow *win)
828 {
829         g_message (__FUNCTION__);
830 }       
831
832
833 void
834 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
835                                         ModestWindow *win)
836 {
837         g_message (__FUNCTION__);
838 }
839
840 void
841 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, int index,
842                                              ModestWindow *win)
843 {
844         g_message (__FUNCTION__);
845         
846 }
847
848 void
849 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
850 {
851         TnyTransportAccount *transport_account;
852         ModestMailOperation *mail_operation;
853         MsgData *data;
854         gchar *account_name, *from;
855         ModestAccountMgr *account_mgr;
856
857         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
858         
859         data = modest_msg_edit_window_get_msg_data (edit_window);
860
861         /* FIXME: Code added just for testing. The final version will
862            use the send queue provided by tinymail and some
863            classifier */
864         account_mgr = modest_runtime_get_account_mgr();
865         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
866         if (!account_name) 
867                 account_name = modest_account_mgr_get_default_account (account_mgr);
868         if (!account_name) {
869                 g_printerr ("modest: no account found\n");
870                 modest_msg_edit_window_free_msg_data (edit_window, data);
871                 return;
872         }
873         transport_account =
874                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
875                                       (modest_runtime_get_account_store(),
876                                        account_name,
877                                        TNY_ACCOUNT_TYPE_TRANSPORT));
878         if (!transport_account) {
879                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
880                 g_free (account_name);
881                 modest_msg_edit_window_free_msg_data (edit_window, data);
882                 return;
883         }
884         from = modest_account_mgr_get_from_string (account_mgr, account_name);
885                 
886         mail_operation = modest_mail_operation_new ();
887         modest_mail_operation_send_new_mail (mail_operation,
888                                              transport_account,
889                                              from,
890                                              data->to, 
891                                              data->cc, 
892                                              data->bcc,
893                                              data->subject, 
894                                              data->body, 
895                                              NULL);
896         /* Frees */
897         g_free (from);
898         g_free (account_name);
899         g_object_unref (G_OBJECT (mail_operation));
900         g_object_unref (G_OBJECT (transport_account));
901
902         modest_msg_edit_window_free_msg_data (edit_window, data);
903
904         /* Save settings and close the window */
905         /* save_settings (edit_window) */
906         gtk_widget_destroy (GTK_WIDGET (edit_window));
907 }
908
909 /*
910  * Shows a dialog with an entry that asks for some text. The returned
911  * value must be freed by the caller. The dialog window title will be
912  * set to @title.
913  */
914 static gchar *
915 ask_for_folder_name (GtkWindow *parent_window,
916                      const gchar *title)
917 {
918         GtkWidget *dialog, *entry;
919         gchar *folder_name = NULL;
920
921         /* Ask for folder name */
922         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
923                                               parent_window,
924                                               GTK_DIALOG_MODAL,
925                                               GTK_STOCK_CANCEL,
926                                               GTK_RESPONSE_REJECT,
927                                               GTK_STOCK_OK,
928                                               GTK_RESPONSE_ACCEPT,
929                                               NULL);
930         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
931                             gtk_label_new(title),
932                             FALSE, FALSE, 0);
933                 
934         entry = gtk_entry_new_with_max_length (40);
935         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
936                             entry,
937                             TRUE, FALSE, 0);    
938         
939         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
940         
941         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
942                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
943
944         gtk_widget_destroy (dialog);
945
946         return folder_name;
947 }
948
949 void 
950 modest_ui_actions_on_new_folder (GtkWidget *widget, ModestMainWindow *main_window)
951 {
952         TnyFolder *parent_folder;
953         GtkWidget *folder_view;
954         
955         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
956
957         folder_view = modest_main_window_get_child_widget (main_window,
958                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
959         if (!folder_view)
960                 return;
961
962         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
963         
964         if (parent_folder) {
965                 gchar *folder_name;
966
967                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
968                                                    _("Please enter a name for the new folder"));
969
970                 if (folder_name != NULL && strlen (folder_name) > 0) {
971                         TnyFolder *new_folder;
972                         ModestMailOperation *mail_op;
973
974                         mail_op = modest_mail_operation_new ();
975                         new_folder = modest_mail_operation_create_folder (mail_op,
976                                                                           TNY_FOLDER_STORE (parent_folder),
977                                                                           (const gchar *) folder_name);
978                         if (new_folder) {
979                                 /* TODO: tinymail should do this. 
980                                    Update view */
981                                 modest_folder_view_add_subfolder (MODEST_FOLDER_VIEW(folder_view),
982                                                                   new_folder);
983
984                                 /* Free new folder */
985                                 g_object_unref (new_folder);
986                         }
987                         g_object_unref (mail_op);
988                 }
989                 g_object_unref (parent_folder);
990         }
991 }
992
993 void 
994 modest_ui_actions_on_rename_folder (GtkWidget *widget,
995                                      ModestMainWindow *main_window)
996 {
997         TnyFolder *folder;
998         GtkWidget *folder_view;
999         
1000         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1001
1002         folder_view = modest_main_window_get_child_widget (main_window,
1003                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1004         if (!folder_view)
1005                 return;
1006         
1007         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1008         
1009         if (folder) {
1010                 gchar *folder_name;
1011                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1012                                                    _("Please enter a new name for the folder"));
1013
1014                 if (folder_name != NULL && strlen (folder_name) > 0) {
1015                         ModestMailOperation *mail_op;
1016                         const GError *error;
1017
1018                         mail_op = modest_mail_operation_new ();
1019                         modest_mail_operation_rename_folder (mail_op,
1020                                                              folder,
1021                                                              (const gchar *) folder_name);
1022
1023                         error = modest_mail_operation_get_error (mail_op);
1024                         if (!error)
1025                                 /* TODO: tinymail should do this. 
1026                                    Update view */
1027                                 modest_folder_view_rename (MODEST_FOLDER_VIEW(folder_view));
1028
1029                         /* TODO: else ? notify error ? */
1030
1031                         g_object_unref (mail_op);
1032                 }
1033                 g_object_unref (folder);
1034         }
1035 }
1036
1037 static void
1038 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1039 {
1040         TnyFolder *folder;
1041         ModestMailOperation *mail_op;
1042         GtkWidget *folder_view;
1043         
1044         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1045
1046         folder_view = modest_main_window_get_child_widget (main_window,
1047                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1048         if (!folder_view)
1049                 return;
1050
1051         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1052         
1053         mail_op = modest_mail_operation_new ();
1054         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1055         g_object_unref (mail_op);
1056 }
1057
1058 void 
1059 modest_ui_actions_on_delete_folder (GtkWidget *widget,
1060                                      ModestMainWindow *main_window)
1061 {
1062         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1063
1064         delete_folder (main_window, FALSE);
1065 }
1066
1067 void 
1068 modest_ui_actions_on_move_folder_to_trash_folder (GtkWidget *widget, ModestMainWindow *main_window)
1069 {
1070         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1071         
1072         delete_folder (main_window, TRUE);
1073 }
1074
1075 void
1076 modest_ui_actions_on_accounts_reloaded (TnyAccountStore *store, gpointer user_data)
1077 {
1078         /* FIXME */
1079         /* ModestFolderView *folder_view; */
1080         
1081 /*      folder_view = modest_widget_factory_get_folder_view (modest_runtime_get_widget_factory()); */
1082 /*      modest_folder_view_update_model (folder_view, store); */
1083 }
1084
1085 void 
1086 modest_ui_actions_on_folder_moved (ModestFolderView *folder_view,  TnyFolder *folder, 
1087                                     TnyFolderStore *parent,  gboolean *done,
1088                                     gpointer user_data)
1089 {
1090         ModestMailOperation *mail_op;
1091         const GError *error;
1092
1093         *done = TRUE;
1094
1095         /* Try to move the folder */    
1096         mail_op = modest_mail_operation_new ();
1097         modest_mail_operation_move_folder (mail_op, folder, parent);
1098
1099         error = modest_mail_operation_get_error (mail_op);
1100         if (error)
1101                 *done = FALSE;
1102
1103         g_object_unref (G_OBJECT (mail_op));
1104 }
1105
1106
1107
1108 void
1109 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1110                                          const gchar* account_name,
1111                                          gchar **password, 
1112                                          gboolean *cancel, 
1113                                          gboolean *remember,
1114                                          ModestMainWindow *main_window)
1115 {
1116         gchar *txt;
1117         GtkWidget *dialog, *entry, *remember_pass_check;
1118
1119         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1120                                               NULL,
1121                                               GTK_DIALOG_MODAL,
1122                                               GTK_STOCK_CANCEL,
1123                                               GTK_RESPONSE_REJECT,
1124                                               GTK_STOCK_OK,
1125                                               GTK_RESPONSE_ACCEPT,
1126                                               NULL);
1127         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1128         
1129         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1130         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1131                             FALSE, FALSE, 0);
1132         g_free (txt);
1133
1134         entry = gtk_entry_new_with_max_length (40);
1135         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1136         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1137         
1138         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1139                             TRUE, FALSE, 0);    
1140
1141         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1142         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1143                             TRUE, FALSE, 0);
1144
1145         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1146         
1147         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1148                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1149                 *cancel   = FALSE;
1150         } else {
1151                 *password = NULL;
1152                 *cancel   = TRUE;
1153         }
1154
1155         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1156                 *remember = TRUE;
1157         else
1158                 *remember = FALSE;
1159
1160         gtk_widget_destroy (dialog);
1161 }