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