* Replaced tny_folder_get_msg by its async version
[modest] / src / maemo / modest-main-window.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 #include <glib/gi18n.h>
31 #include <string.h>
32 #include <gtk/gtkaboutdialog.h>
33 #include <gtk/gtktreeviewcolumn.h>
34
35 #include <modest-widget-memory.h>
36 #include <modest-icon-factory.h>
37
38 #include <widgets/modest-toolbar.h>
39
40 #include "modest-main-window.h"
41 #include "modest-account-view-window.h"
42 #include "modest-account-mgr.h"
43 #include "modest-conf.h"
44 #include "modest-edit-msg-window.h"
45 #include "modest-icon-names.h"
46 #include "modest-tny-platform-factory.h"
47 #include "modest-tny-msg-actions.h"
48 #include "modest-mail-operation.h"
49
50 /* 'private'/'protected' functions */
51 static void modest_main_window_class_init    (ModestMainWindowClass *klass);
52 static void modest_main_window_init          (ModestMainWindow *obj);
53 static void modest_main_window_finalize      (GObject *obj);
54
55 static void restore_sizes (ModestMainWindow *self);
56 static void save_sizes (ModestMainWindow *self);
57
58 /* list my signals */
59 enum {
60         /* MY_SIGNAL_1, */
61         /* MY_SIGNAL_2, */
62         LAST_SIGNAL
63 };
64
65 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
66 struct _ModestMainWindowPrivate {
67
68         GtkUIManager *ui_manager;
69
70         GtkWidget *toolbar;
71         GtkWidget *menu;
72
73         //GtkWidget *folder_paned;
74         GtkWidget *msg_paned;
75         GtkWidget *main_paned;
76         
77         ModestWidgetFactory *widget_factory;
78         TnyPlatformFactory *factory;
79   
80         ModestHeaderView *header_view;
81         ModestFolderView *folder_view;
82         ModestMsgView    *msg_preview;
83 };
84
85
86 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
87                                                 MODEST_TYPE_MAIN_WINDOW, \
88                                                 ModestMainWindowPrivate))
89 /* globals */
90 static GtkWindowClass *parent_class = NULL;
91
92 /* uncomment the following if you have defined any signals */
93 /* static guint signals[LAST_SIGNAL] = {0}; */
94
95 GType
96 modest_main_window_get_type (void)
97 {
98         static GType my_type = 0;
99         if (!my_type) {
100                 static const GTypeInfo my_info = {
101                         sizeof(ModestMainWindowClass),
102                         NULL,           /* base init */
103                         NULL,           /* base finalize */
104                         (GClassInitFunc) modest_main_window_class_init,
105                         NULL,           /* class finalize */
106                         NULL,           /* class data */
107                         sizeof(ModestMainWindow),
108                         1,              /* n_preallocs */
109                         (GInstanceInitFunc) modest_main_window_init,
110                         NULL
111                 };
112                 my_type = g_type_register_static (HILDON_TYPE_WINDOW,
113                                                   "ModestMainWindow",
114                                                   &my_info, 0);
115         }
116         return my_type;
117 }
118
119 static void
120 modest_main_window_class_init (ModestMainWindowClass *klass)
121 {
122         GObjectClass *gobject_class;
123         gobject_class = (GObjectClass*) klass;
124
125         parent_class            = g_type_class_peek_parent (klass);
126         gobject_class->finalize = modest_main_window_finalize;
127
128         g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
129
130         /* signal definitions go here, e.g.: */
131 /*      signals[MY_SIGNAL_1] = */
132 /*              g_signal_new ("my_signal_1",....); */
133 /*      signals[MY_SIGNAL_2] = */
134 /*              g_signal_new ("my_signal_2",....); */
135 /*      etc. */
136 }
137
138 static void
139 modest_main_window_init (ModestMainWindow *obj)
140 {
141         ModestMainWindowPrivate *priv;
142
143         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
144         
145         priv->factory = modest_tny_platform_factory_get_instance ();
146 }
147
148 static void
149 modest_main_window_finalize (GObject *obj)
150 {
151         ModestMainWindowPrivate *priv;  
152         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
153         if (priv->widget_factory) {
154                 g_object_unref (G_OBJECT(priv->widget_factory));
155                 priv->widget_factory = NULL;
156         }
157
158         G_OBJECT_CLASS(parent_class)->finalize (obj);
159 }
160
161
162 static void
163 on_menu_about (GtkWidget *widget, gpointer data)
164 {
165         GtkWidget *about;
166         const gchar *authors[] = {
167                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
168                 NULL
169         };      
170         about = gtk_about_dialog_new ();
171         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
172         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
173         gtk_about_dialog_set_copyright (
174                 GTK_ABOUT_DIALOG(about),
175                 _("Copyright (c) 2006, Nokia Corporation\n"
176                   "All rights reserved."));
177         gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG(about),
178                 _("a modest e-mail client\n\n"
179                   "design and implementation: Dirk-Jan C. Binnema\n"
180                   "contributions from the fine people at KernelConcepts\n\n"
181                   "uses the tinymail email framework written by Philip van Hoof"));
182         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
183         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
184
185         gtk_dialog_run (GTK_DIALOG (about));
186         gtk_widget_destroy(about);
187 }
188
189
190 static void
191 on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget)
192 {
193         GtkWidget *account_win;
194         ModestMainWindowPrivate *priv;
195
196         g_return_if_fail (widget);
197         g_return_if_fail (self);
198         
199         priv        = MODEST_MAIN_WINDOW_GET_PRIVATE(self);     
200         account_win = modest_account_view_window_new (priv->widget_factory);
201
202         gtk_window_set_transient_for (GTK_WINDOW(account_win),
203                                       GTK_WINDOW(self));
204                                       
205         gtk_widget_show (account_win);
206 }
207
208
209 static void
210 on_menu_new_message (ModestMainWindow *self, guint action, GtkWidget *widget)
211 {
212         GtkWidget *msg_win;
213         ModestMainWindowPrivate *priv;
214
215         priv  = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
216
217         msg_win = modest_edit_msg_window_new (priv->widget_factory,
218                                               MODEST_EDIT_TYPE_NEW,
219                                               NULL);
220         gtk_widget_show (msg_win);
221 }
222
223 static void
224 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
225 {
226         GtkWidget *msg_win;
227         TnyHeader *new_header;
228         TnyMsg *new_msg;
229         ModestMainWindowPrivate *priv;
230         ModestEditType edit_type = -2;
231         GetMsgAsyncHelper *helper;
232
233         helper = (GetMsgAsyncHelper *) (user_data);
234         priv  = helper->main_window_private;
235
236         /* FIXME: select proper action */
237         new_msg = NULL;
238         switch (helper->action) {
239         case 1:
240                 new_msg = 
241                         modest_mail_operation_create_reply_mail (msg, helper->from, helper->reply_type,
242                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
243                 edit_type = MODEST_EDIT_TYPE_REPLY;
244                 break;
245         case 2:
246                 new_msg = 
247                         modest_mail_operation_create_reply_mail (msg, helper->from, helper->reply_type,
248                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
249                 edit_type = MODEST_EDIT_TYPE_REPLY;
250                 break;
251         case 3:
252                 new_msg = 
253                         modest_mail_operation_create_forward_mail (msg, helper->from, helper->forward_type);
254                 edit_type = MODEST_EDIT_TYPE_FORWARD;
255                 break;
256         default:
257                 g_warning ("unexpected action type: %d", helper->action);
258         }
259         
260         if (new_msg) {
261                 /* Set from */
262                 new_header = tny_msg_get_header (new_msg);
263                 tny_header_set_from (new_header, helper->from);
264                 
265                 /* Show edit window */
266                 msg_win = modest_edit_msg_window_new (priv->widget_factory,
267                                                       edit_type,
268                                                       new_msg);
269                 gtk_widget_show (msg_win);
270                 
271                 /* Clean and go on */
272                 g_object_unref (new_msg);
273         }
274 }
275
276 static void
277 on_menu_reply_forward (ModestMainWindow *self, guint action, GtkWidget *widget)
278 {
279         ModestMainWindowPrivate *priv;
280         ModestHeaderView *header_view;
281         TnyList *header_list;
282         TnyIterator *iter;
283         gchar *reply_key, *forward_key;
284         ModestMailOperationReplyType reply_type;
285         ModestMailOperationForwardType forward_type;
286         ModestConf *conf;
287         GError *error;
288         GetMsgAsyncHelper *helper;
289
290         priv  = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
291         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
292
293         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
294         header_list = modest_header_view_get_selected_headers (header_view);
295
296         /* Get reply and forward types */
297         error = NULL;
298         reply_key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE, MODEST_CONF_REPLY_TYPE);
299         reply_type = modest_conf_get_int (conf, reply_key, &error);
300         if (error || reply_type == 0) {
301                 g_warning ("key %s not defined", reply_key);
302                 reply_type = MODEST_MAIL_OPERATION_REPLY_TYPE_CITE;
303                 if (error) {
304                         g_error_free (error);
305                         error = NULL;
306                 }
307         }
308         g_free (reply_key);
309         
310         forward_key = g_strdup_printf ("%s/%s", MODEST_CONF_NAMESPACE, MODEST_CONF_FORWARD_TYPE);
311         forward_type = modest_conf_get_int (conf, forward_key, &error);
312         if (error || forward_type == 0) {
313                 g_warning ("key %s not defined", forward_key);
314                 forward_type = MODEST_MAIL_OPERATION_FORWARD_TYPE_INLINE;
315                 if (error) {
316                         g_error_free (error);
317                         error = NULL;
318                 }
319         }
320         g_free (forward_key);
321         
322         if (header_list) {
323                 TnyHeader *header;
324                 TnyFolder *folder;
325                 gchar *from, *email_key;
326                 const gchar *account_name;
327
328                 /* We assume that we can only select messages of the
329                    same folder and that we reply all of them from the
330                    same account. In fact the interface currently only
331                    allows single selection */
332                 account_name = modest_folder_view_get_selected_account (priv->folder_view);
333                 email_key = g_strdup_printf ("%s/%s/%s", MODEST_ACCOUNT_NAMESPACE, 
334                                              account_name, MODEST_ACCOUNT_EMAIL);
335                 from = modest_conf_get_string (conf, email_key, NULL);
336                 g_free (email_key);
337
338                 iter = tny_list_create_iterator (header_list);
339                 header = TNY_HEADER (tny_iterator_get_current (iter));
340                 folder = tny_header_get_folder (header);
341
342                 do {
343                         /* Since it's not an object, we need to create
344                            it each time due to it's not a GObject and
345                            we can not do a g_object_ref. No need to
346                            free it, tinymail will do it for us. */
347                         helper = g_slice_new0 (GetMsgAsyncHelper);
348                         helper->main_window_private = priv;
349                         helper->reply_type = reply_type;
350                         helper->forward_type = forward_type;
351                         helper->action = action;
352                         helper->from = from;
353
354                         /* Get msg from header */
355                         header = TNY_HEADER (tny_iterator_get_current (iter));
356                         tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
357                         tny_iterator_next (iter);
358
359                 } while (!tny_iterator_is_done (iter));
360
361                 /* Clean */
362                 g_free (from);
363                 g_object_unref (G_OBJECT (iter));
364                 g_object_unref (G_OBJECT (folder));
365         }
366 }
367
368 static void
369 on_menu_quit (ModestMainWindow *self, guint action, GtkWidget *widget)
370 {
371         save_sizes (self);
372         gtk_widget_destroy (GTK_WIDGET(self));
373 }
374
375 static void
376 on_menu_delete (ModestMainWindow *self, guint action, GtkWidget *widget)
377 {
378         ModestMainWindowPrivate *priv;
379         ModestHeaderView *header_view;
380         TnyList *header_list;
381         TnyIterator *iter;
382         GtkTreeModel *model;
383
384         priv  = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
385
386         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
387         header_list = modest_header_view_get_selected_headers (header_view);
388         
389         if (header_list) {
390                 iter = tny_list_create_iterator (header_list);
391                 model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
392                 if (GTK_IS_TREE_MODEL_SORT (model))
393                         model = gtk_tree_model_sort_get_model (GTK_TREE_MODEL_SORT (model));
394                 do {
395                         TnyHeader *header;
396                         ModestMailOperation *mail_op;
397
398                         header = TNY_HEADER (tny_iterator_get_current (iter));
399                         /* TODO: thick grain mail operation involving
400                            a list of objects. Composite pattern ??? */
401                         mail_op = modest_mail_operation_new ();
402
403                         /* Move to trash */
404                         modest_mail_operation_remove_msg (mail_op, header, TRUE);
405
406                         /* Remove from tree model */
407                         tny_list_remove (TNY_LIST (model), G_OBJECT (header));
408
409                         g_object_unref (G_OBJECT (mail_op));
410                         g_object_unref (header);
411                         tny_iterator_next (iter);
412
413                 } while (!tny_iterator_is_done (iter));
414         }
415 }
416
417
418 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
419 static const gchar* UI_DEF=
420         "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
421         "<ui>"
422         "  <popup>"
423         "    <menu name=\"Message\" \"MenuMessage\">"
424         "      <menuitem name=\"New\" action=\"on_menu_new_message\" />"
425         "    </menu>"
426 //      "    <menu name=\"JustifyMenu\" action=\"JustifyMenuAction\">"
427 //      "      <menuitem name=\"Left\" action=\"justify-left\"/>"
428 //      "      <menuitem name=\"Centre\" action=\"justify-center\"/>"
429 //      "      <menuitem name=\"Right\" action=\"justify-right\"/>"
430 //      "      <menuitem name=\"Fill\" action=\"justify-fill\"/>"
431 //      "    </menu>"
432         "  </popup>"
433         "</ui>";
434
435 static GtkMenu *
436 get_menu (ModestMainWindow *self)
437 {
438         GtkWidget *w;
439         int i = 0;
440         
441         ModestMainWindowPrivate *priv;
442         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
443
444         priv->ui_manager = gtk_ui_manager_new ();
445
446         gtk_ui_manager_add_ui_from_string (priv->ui_manager,
447                                            UI_DEF, strlen(UI_DEF),
448                                            NULL);
449
450         w = gtk_ui_manager_get_widget (priv->ui_manager, "/popup");
451         g_warning ("==> GtkMenu? ==> %s", GTK_IS_MENU(w) ? "yes" : "no"); 
452
453         return GTK_MENU(w);
454 }
455
456
457
458 static ModestHeaderView*
459 header_view_new (ModestMainWindow *self)
460 {
461         int i;
462         GList *columns = NULL;
463         ModestHeaderView *header_view;
464         ModestMainWindowPrivate *priv;
465         ModestHeaderViewColumn cols[] = {
466                 MODEST_HEADER_VIEW_COLUMN_MSGTYPE,
467                 MODEST_HEADER_VIEW_COLUMN_ATTACH,
468                 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER
469 //              MODEST_HEADER_VIEW_COLUMN_FROM,
470 //              MODEST_HEADER_VIEW_COLUMN_SUBJECT,
471 //              MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE
472         };
473         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
474         
475         for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i)
476                 columns = g_list_append (columns, GINT_TO_POINTER(cols[i]));
477
478         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
479         modest_header_view_set_columns (header_view, columns);
480         g_list_free (columns);
481
482         return header_view;
483 }
484
485
486 static void
487 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
488                            ModestMainWindow *self)
489 {
490         GtkTreeSelection *sel;
491         GtkTreeIter iter;
492         GtkTreeModel *model;
493         ModestMainWindowPrivate *priv;
494
495         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
496         
497         switch (button_id) {
498         case MODEST_TOOLBAR_BUTTON_NEW_MAIL:
499                 on_menu_new_message (self, 0, NULL);
500                 break;
501         case MODEST_TOOLBAR_BUTTON_REPLY:
502                 on_menu_reply_forward (self, 1, NULL);
503                 break;
504         case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
505                 on_menu_reply_forward (self, 2, NULL);
506                 break;
507         case MODEST_TOOLBAR_BUTTON_FORWARD:
508                 on_menu_reply_forward (self, 3, NULL);
509                 break;
510         case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
511                 
512
513         case MODEST_TOOLBAR_BUTTON_NEXT:
514                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->header_view));
515                 if (sel) {
516                         gtk_tree_selection_get_selected (sel, &model, &iter);
517                         gtk_tree_model_iter_next (model, &iter);
518                         gtk_tree_selection_select_iter (sel, &iter);
519                 }
520                 
521         case MODEST_TOOLBAR_BUTTON_PREV:
522         /*      if (sel) { */
523 /*                      gtk_tree_selection_get_selected (sel, &model, &iter); */
524 /*                      gtk_tree_model_iter_prev (model, &iter); */
525 /*                      gtk_tree_selection_select_iter (sel, &iter); */
526 /*              } */
527
528                 break;
529         case MODEST_TOOLBAR_BUTTON_DELETE:
530                 on_menu_delete (self, 0, GTK_WIDGET (toolbar));
531                 break;
532
533         default:
534                 g_printerr ("modest: key %d pressed\n", button_id);
535         }
536 }
537
538 static ModestToolbar*
539 toolbar_new (ModestMainWindow *self)
540 {
541         int i;
542         ModestToolbar *toolbar;
543         GSList *buttons = NULL;
544         ModestMainWindowPrivate *priv;
545
546         ModestToolbarButton button_ids[] = {
547                 MODEST_TOOLBAR_BUTTON_NEW_MAIL,
548                 MODEST_TOOLBAR_BUTTON_REPLY,
549                 MODEST_TOOLBAR_BUTTON_REPLY_ALL,
550                 MODEST_TOOLBAR_BUTTON_FORWARD,
551                 MODEST_TOOLBAR_SEPARATOR,
552                 MODEST_TOOLBAR_BUTTON_SEND_RECEIVE,
553                 MODEST_TOOLBAR_SEPARATOR,
554                 MODEST_TOOLBAR_BUTTON_PREV,
555                 MODEST_TOOLBAR_BUTTON_NEXT,
556                 MODEST_TOOLBAR_SEPARATOR,               
557                 MODEST_TOOLBAR_BUTTON_DELETE
558         };              
559         
560         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
561
562         for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
563                 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
564         
565         toolbar = modest_widget_factory_get_main_toolbar (priv->widget_factory, buttons);
566         g_slist_free (buttons);
567         
568         g_signal_connect (G_OBJECT(toolbar), "button_clicked",
569                           G_CALLBACK(on_toolbar_button_clicked), self);
570         
571         return toolbar;
572 }
573
574
575
576 static void
577 restore_sizes (ModestMainWindow *self)
578 {
579         ModestConf *conf;
580         ModestMainWindowPrivate *priv;
581         
582         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
583         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
584
585         modest_widget_memory_restore_settings (conf,GTK_WIDGET(self),
586                                                "modest-main-window");
587         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->msg_paned),
588                                                "modest-msg-paned");
589         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->main_paned),
590                                                "modest-main-paned");
591 }
592
593
594 static void
595 save_sizes (ModestMainWindow *self)
596 {
597         ModestMainWindowPrivate *priv;
598         ModestConf *conf;
599         
600         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
601         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
602         
603         modest_widget_memory_save_settings (conf,GTK_WIDGET(self),
604                                             "modest-main-window");
605         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->msg_paned),
606                                             "modest-msg-paned");
607         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->main_paned),
608                                             "modest-main-paned");
609 }
610
611 static GtkWidget*
612 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
613 {
614         GtkWidget *win;
615
616         win = gtk_scrolled_window_new (NULL, NULL);
617         gtk_scrolled_window_set_policy
618                 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
619                  GTK_POLICY_AUTOMATIC);
620         
621         if (needs_viewport)
622                 gtk_scrolled_window_add_with_viewport
623                         (GTK_SCROLLED_WINDOW(win), widget);
624         else
625                 gtk_container_add (GTK_CONTAINER(win),
626                                    widget);
627
628         return win;
629 }
630
631
632 static gboolean
633 on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self)
634 {
635         save_sizes (self);
636         return FALSE;
637 }
638
639
640 GtkWidget*
641 modest_main_window_new (ModestWidgetFactory *widget_factory)
642 {
643         GObject *obj;
644         ModestMainWindowPrivate *priv;
645         
646         GtkWidget *main_vbox;
647         GtkWidget *status_hbox;
648         GtkWidget *header_win, *folder_win, *favorites_win;
649         
650         g_return_val_if_fail (widget_factory, NULL);
651
652         obj  = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
653         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
654
655         g_object_ref (widget_factory);
656         priv->widget_factory = widget_factory;
657
658         /* widgets from factory */
659         priv->folder_view = modest_widget_factory_get_folder_view (widget_factory);
660         priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
661         priv->msg_preview = modest_widget_factory_get_msg_preview (widget_factory);
662         
663         folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
664                                                  FALSE);
665         header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
666                                                  FALSE);                                
667         /*menu */
668         priv->menu = get_menu (MODEST_MAIN_WINDOW(obj));
669         hildon_window_set_menu (HILDON_WINDOW(obj), GTK_MENU(priv->menu));
670         
671         priv->toolbar = GTK_WIDGET(toolbar_new (MODEST_MAIN_WINDOW(obj)));
672         
673         /* paned */
674         priv->msg_paned = gtk_vpaned_new ();
675         priv->main_paned = gtk_hpaned_new ();
676
677         gtk_paned_add1 (GTK_PANED(priv->main_paned), folder_win);
678         gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
679
680         gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
681         gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
682
683         gtk_widget_show (GTK_WIDGET(priv->header_view));
684         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
685
686         /* status bar / progress */
687         status_hbox = gtk_hbox_new (FALSE, 0);
688         gtk_box_pack_start (GTK_BOX(status_hbox),
689                             modest_widget_factory_get_folder_info_label (widget_factory),
690                             FALSE,FALSE, 6);
691         gtk_box_pack_start (GTK_BOX(status_hbox),
692                             modest_widget_factory_get_status_bar(widget_factory),
693                             TRUE, TRUE, 0);
694         gtk_box_pack_start (GTK_BOX(status_hbox),
695                             modest_widget_factory_get_progress_bar(widget_factory),
696                             FALSE, FALSE, 0);
697         gtk_box_pack_start (GTK_BOX(status_hbox),
698                           modest_widget_factory_get_online_toggle(widget_factory),
699                           FALSE, FALSE, 0);
700
701         /* putting it all together... */
702         main_vbox = gtk_vbox_new (FALSE, 6);
703         gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE,0);
704         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);        
705         gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 0);
706         
707         gtk_container_add (GTK_CONTAINER(obj), main_vbox);
708         restore_sizes (MODEST_MAIN_WINDOW(obj));        
709
710         gtk_window_set_title (GTK_WINDOW(obj), "Modest");
711         gtk_window_set_icon  (GTK_WINDOW(obj),
712                               modest_icon_factory_get_icon (MODEST_APP_ICON));
713         
714         gtk_widget_show_all (main_vbox);
715
716         g_signal_connect (G_OBJECT(obj), "delete-event",
717                           G_CALLBACK(on_delete_event), obj);
718         
719         return GTK_WIDGET(obj);
720 }