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