36137972424b0343d3203298df8050e6f0447fad
[modest] / src / gtk / 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 <gtk/gtkaboutdialog.h>
32 #include <gtk/gtktreeviewcolumn.h>
33
34 #include <modest-widget-memory.h>
35 #include <modest-icon-factory.h>
36
37 #include <widgets/modest-toolbar.h>
38
39 #include "modest-main-window.h"
40 #include "modest-account-view-window.h"
41 #include "modest-account-mgr.h"
42 #include "modest-conf.h"
43 #include "modest-edit-msg-window.h"
44 #include "modest-icon-names.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-mail-operation.h"
47
48 /* 'private'/'protected' functions */
49 static void modest_main_window_class_init    (ModestMainWindowClass *klass);
50 static void modest_main_window_init          (ModestMainWindow *obj);
51 static void modest_main_window_finalize      (GObject *obj);
52
53 static void restore_sizes (ModestMainWindow *self);
54 static void save_sizes (ModestMainWindow *self);
55
56 /* list my signals */
57 enum {
58         /* MY_SIGNAL_1, */
59         /* MY_SIGNAL_2, */
60         LAST_SIGNAL
61 };
62
63 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
64 struct _ModestMainWindowPrivate {
65
66         GtkWidget *toolbar;
67         GtkWidget *menubar;
68
69         GtkWidget *folder_paned;
70         GtkWidget *msg_paned;
71         GtkWidget *main_paned;
72         
73         ModestWidgetFactory *widget_factory;
74         TnyPlatformFactory *factory;
75   
76         ModestHeaderView *header_view;
77         ModestFolderView *folder_view;
78         ModestMsgView    *msg_preview;
79 };
80
81
82 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
83                                                 MODEST_TYPE_MAIN_WINDOW, \
84                                                 ModestMainWindowPrivate))
85 /* globals */
86 static GtkWindowClass *parent_class = NULL;
87
88 /* uncomment the following if you have defined any signals */
89 /* static guint signals[LAST_SIGNAL] = {0}; */
90
91 GType
92 modest_main_window_get_type (void)
93 {
94         static GType my_type = 0;
95         if (!my_type) {
96                 static const GTypeInfo my_info = {
97                         sizeof(ModestMainWindowClass),
98                         NULL,           /* base init */
99                         NULL,           /* base finalize */
100                         (GClassInitFunc) modest_main_window_class_init,
101                         NULL,           /* class finalize */
102                         NULL,           /* class data */
103                         sizeof(ModestMainWindow),
104                         1,              /* n_preallocs */
105                         (GInstanceInitFunc) modest_main_window_init,
106                         NULL
107                 };
108                 my_type = g_type_register_static (GTK_TYPE_WINDOW,
109                                                   "ModestMainWindow",
110                                                   &my_info, 0);
111         }
112         return my_type;
113 }
114
115 static void
116 modest_main_window_class_init (ModestMainWindowClass *klass)
117 {
118         GObjectClass *gobject_class;
119         gobject_class = (GObjectClass*) klass;
120
121         parent_class            = g_type_class_peek_parent (klass);
122         gobject_class->finalize = modest_main_window_finalize;
123
124         g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
125
126         /* signal definitions go here, e.g.: */
127 /*      signals[MY_SIGNAL_1] = */
128 /*              g_signal_new ("my_signal_1",....); */
129 /*      signals[MY_SIGNAL_2] = */
130 /*              g_signal_new ("my_signal_2",....); */
131 /*      etc. */
132 }
133
134 static void
135 modest_main_window_init (ModestMainWindow *obj)
136 {
137         ModestMainWindowPrivate *priv;
138
139         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
140         
141         priv->factory = modest_tny_platform_factory_get_instance ();
142 }
143
144 static void
145 modest_main_window_finalize (GObject *obj)
146 {
147         ModestMainWindowPrivate *priv;  
148         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
149         if (priv->widget_factory) {
150                 g_object_unref (G_OBJECT(priv->widget_factory));
151                 priv->widget_factory = NULL;
152         }
153
154         G_OBJECT_CLASS(parent_class)->finalize (obj);
155 }
156
157
158 static void
159 on_menu_about (GtkWidget *widget, gpointer data)
160 {
161         GtkWidget *about;
162         const gchar *authors[] = {
163                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
164                 NULL
165         };      
166         about = gtk_about_dialog_new ();
167         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
168         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
169         gtk_about_dialog_set_copyright (
170                 GTK_ABOUT_DIALOG(about),
171                 _("Copyright (c) 2006, Nokia Corporation\n"
172                   "All rights reserved."));
173         gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG(about),
174                 _("a modest e-mail client\n\n"
175                   "design and implementation: Dirk-Jan C. Binnema\n"
176                   "contributions from the fine people at KernelConcepts\n\n"
177                   "uses the tinymail email framework written by Philip van Hoof"));
178         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
179         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
180
181         gtk_dialog_run (GTK_DIALOG (about));
182         gtk_widget_destroy(about);
183 }
184
185
186 static void
187 on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget)
188 {
189         GtkWidget *account_win;
190         ModestMainWindowPrivate *priv;
191
192         g_return_if_fail (widget);
193         g_return_if_fail (self);
194         
195         priv        = MODEST_MAIN_WINDOW_GET_PRIVATE(self);     
196         account_win = modest_account_view_window_new (priv->widget_factory);
197
198         gtk_window_set_transient_for (GTK_WINDOW(account_win),
199                                       GTK_WINDOW(self));
200                                       
201         gtk_widget_show (account_win);
202 }
203
204
205 static void
206 on_menu_new_message (ModestMainWindow *self, guint action, GtkWidget *widget)
207 {
208         GtkWidget *msg_win;
209         ModestMainWindowPrivate *priv;
210
211         priv  = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
212
213         msg_win = modest_edit_msg_window_new (priv->widget_factory,
214                                               MODEST_EDIT_TYPE_NEW,
215                                               NULL);
216         gtk_widget_show (msg_win);
217 }
218
219 static void
220 on_menu_reply_forward (ModestMainWindow *self, guint action, GtkWidget *widget)
221 {
222         GtkWidget *msg_win;
223         ModestMainWindowPrivate *priv;
224         ModestHeaderView *header_view;
225         TnyList *header_list;
226         TnyIterator *iter;
227
228         priv  = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
229
230         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
231         header_list = modest_header_view_get_selected_headers (header_view);
232
233         if (header_list) {
234                 iter = tny_list_create_iterator (header_list);
235                 do {
236                         TnyHeader *header;
237                         TnyFolder *folder;
238                         TnyMsg    *msg, *new_msg;
239                         ModestEditType edit_type;
240
241                         /* Get msg from header */
242                         header = TNY_HEADER (tny_iterator_get_current (iter));
243                         folder = tny_header_get_folder (header);
244                         msg = tny_folder_get_msg (folder, header);
245
246                         /* FIXME: select proper action */
247                         switch (action) {
248                         case 1:
249                                 /* TODO: get reply type from config */
250                                 new_msg = 
251                                         modest_mail_operation_create_reply_mail (msg,
252                                                                                  MODEST_MAIL_OPERATION_REPLY_TYPE_CITE,
253                                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_SENDER);
254                                 edit_type = MODEST_EDIT_TYPE_REPLY;
255                                 break;
256                         case 2:
257                                 /* TODO: get reply type from config */
258                                 new_msg = 
259                                         modest_mail_operation_create_reply_mail (msg,
260                                                                                  MODEST_MAIL_OPERATION_REPLY_TYPE_QUOTE,
261                                                                                  MODEST_MAIL_OPERATION_REPLY_MODE_ALL);
262                                 edit_type = MODEST_EDIT_TYPE_REPLY;
263                                 break;
264                         case 3:
265                                 /* TODO: get forward type from config */
266                                 new_msg = 
267                                         modest_mail_operation_create_forward_mail (msg,
268                                                                                    MODEST_MAIL_OPERATION_FORWARD_TYPE_INLINE);
269                                 edit_type = MODEST_EDIT_TYPE_FORWARD;
270                                 break;
271                         }
272                         /* Show edit window */
273                         msg_win = modest_edit_msg_window_new (priv->widget_factory,
274                                                               edit_type,
275                                                               new_msg);
276                         gtk_widget_show (msg_win);
277
278                         /* Clean and go on */
279                         g_object_unref (new_msg);
280                         tny_iterator_next (iter);
281
282                 } while (!tny_iterator_is_done (iter));
283         }
284 }
285
286 static void
287 on_menu_quit (ModestMainWindow *self, guint action, GtkWidget *widget)
288 {
289         save_sizes (self);
290         gtk_widget_destroy (GTK_WIDGET(self));
291 }
292
293
294 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
295 static GtkItemFactoryEntry menu_items[] = {
296         { "/_File",             NULL,                   NULL,           0, "<Branch>", NULL },
297         { "/File/_New",         "<control>N",           NULL,           0, "<StockItem>", GTK_STOCK_NEW },
298         { "/File/_Open",        "<control>O",           NULL,           0, "<StockItem>", GTK_STOCK_OPEN },
299         { "/File/_Save",        "<control>S",           NULL,           0, "<StockItem>", GTK_STOCK_SAVE },
300         { "/File/Save _As",     NULL,                   NULL,           0, "<Item>", NULL },
301         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>", NULL },
302         { "/File/_Quit",        "<CTRL>Q",              on_menu_quit,  0, "<StockItem>", GTK_STOCK_QUIT },
303
304         { "/_Edit",             NULL,                   NULL,           0, "<Branch>", NULL },
305         { "/Edit/_Undo",        "<CTRL>Z",              NULL,           0, "<StockItem>", GTK_STOCK_UNDO },
306         { "/Edit/_Redo",        "<shift><CTRL>Z",       NULL,           0, "<StockItem>", GTK_STOCK_REDO },
307         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>", NULL },
308         { "/Edit/Cut",          "<control>X",           NULL,           0, "<StockItem>", GTK_STOCK_CUT  },
309         { "/Edit/Copy",         "<CTRL>C",              NULL,           0, "<StockItem>", GTK_STOCK_COPY },
310         { "/Edit/Paste",        NULL,                   NULL,           0, "<StockItem>", GTK_STOCK_PASTE},
311         { "/Edit/sep1",         NULL,                   NULL,           0, "<Separator>", NULL },
312         { "/Edit/Delete",       "<CTRL>Q",              NULL,           0, "<Item>" ,NULL},
313         { "/Edit/Select all",   "<CTRL>A",              NULL,           0, "<Item>" ,NULL},
314         { "/Edit/Deelect all",  "<Shift><CTRL>A",       NULL,           0, "<Item>" ,NULL},
315
316         { "/_Actions",                NULL,             NULL,           0, "<Branch>" ,NULL},
317         { "/Actions/_New Message",    NULL,             on_menu_new_message,            0, "<Item>",NULL },
318         { "/Actions/_Reply",    NULL,                   NULL,           0, "<Item>" ,NULL},
319         { "/Actions/_Forward",  NULL,                   NULL,           0, "<Item>" ,NULL},
320         { "/Actions/_Bounce",   NULL,                   NULL,           0, "<Item>",NULL },     
321         
322         { "/_Options",           NULL,                  NULL,           0, "<Branch>" ,NULL},
323         { "/Options/_Accounts",  NULL,                  on_menu_accounts,0, "<Item>" ,NULL},
324         { "/Options/_Contacts",  NULL,                  NULL,           0, "<Item>" ,NULL },
325
326
327         { "/_Help",         NULL,                       NULL,           0, "<Branch>" ,NULL},
328         { "/_Help/About",   NULL,                       on_menu_about,  0, "<StockItem>", GTK_STOCK_ABOUT},
329 };
330
331 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
332
333
334 static GtkWidget *
335 menubar_new (ModestMainWindow *self)
336 {
337         GtkItemFactory *item_factory;
338         GtkAccelGroup *accel_group;
339         
340         /* Make an accelerator group (shortcut keys) */
341         accel_group = gtk_accel_group_new ();
342         
343         /* Make an ItemFactory (that makes a menubar) */
344         item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
345                                              accel_group);
346         
347         /* This function generates the menu items. Pass the item factory,
348            the number of items in the array, the array itself, and any
349            callback data for the the menu items. */
350         gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
351         
352         ///* Attach the new accelerator group to the window. */
353         gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
354         
355         /* Finally, return the actual menu bar created by the item factory. */
356         return gtk_item_factory_get_widget (item_factory, "<main>");
357 }
358
359
360
361
362 static ModestHeaderView*
363 header_view_new (ModestMainWindow *self)
364 {
365         int i;
366         GSList *columns = NULL;
367         ModestHeaderView *header_view;
368         ModestMainWindowPrivate *priv;
369         ModestHeaderViewColumn cols[] = {
370                 MODEST_HEADER_VIEW_COLUMN_MSGTYPE,
371                 MODEST_HEADER_VIEW_COLUMN_ATTACH,
372 /*              MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER, */
373                 MODEST_HEADER_VIEW_COLUMN_FROM,
374                 MODEST_HEADER_VIEW_COLUMN_SUBJECT,
375                 MODEST_HEADER_VIEW_COLUMN_RECEIVED_DATE
376         };
377         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
378         
379         for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i)
380                 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
381
382         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
383         modest_header_view_set_columns (header_view, columns);
384         g_slist_free (columns);
385
386         return header_view;
387 }
388
389 static void
390 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
391                            ModestMainWindow *self)
392 {
393         GtkTreeSelection *sel;
394         GtkTreeIter iter;
395         GtkTreeModel *model;
396         ModestMainWindowPrivate *priv;
397
398         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
399         
400         switch (button_id) {
401         case MODEST_TOOLBAR_BUTTON_NEW_MAIL:
402                 on_menu_new_message (self, 0, NULL);
403                 break;
404         case MODEST_TOOLBAR_BUTTON_REPLY:
405                 on_menu_reply_forward (self, 1, NULL);
406                 break;
407         case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
408                 on_menu_reply_forward (self, 2, NULL);
409                 break;
410         case MODEST_TOOLBAR_BUTTON_FORWARD:
411                 on_menu_reply_forward (self, 3, NULL);
412                 break;
413         case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
414                 
415
416         case MODEST_TOOLBAR_BUTTON_NEXT:
417                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->header_view));
418                 if (sel) {
419                         gtk_tree_selection_get_selected (sel, &model, &iter);
420                         gtk_tree_model_iter_next (model, &iter);
421                         gtk_tree_selection_select_iter (sel, &iter);
422                 }
423                 
424         case MODEST_TOOLBAR_BUTTON_PREV:
425         /*      if (sel) { */
426 /*                      gtk_tree_selection_get_selected (sel, &model, &iter); */
427 /*                      gtk_tree_model_iter_prev (model, &iter); */
428 /*                      gtk_tree_selection_select_iter (sel, &iter); */
429 /*              } */
430
431                 break;
432         case MODEST_TOOLBAR_BUTTON_DELETE:
433
434         default:
435                 g_printerr ("modest: key %d pressed\n", button_id);
436         }
437 }
438
439 static ModestToolbar*
440 toolbar_new (ModestMainWindow *self)
441 {
442         int i;
443         ModestToolbar *toolbar;
444         GSList *buttons = NULL;
445         ModestMainWindowPrivate *priv;
446
447         ModestToolbarButton button_ids[] = {
448                 MODEST_TOOLBAR_BUTTON_NEW_MAIL,
449                 MODEST_TOOLBAR_BUTTON_REPLY,
450                 MODEST_TOOLBAR_BUTTON_REPLY_ALL,
451                 MODEST_TOOLBAR_BUTTON_FORWARD,
452                 MODEST_TOOLBAR_SEPARATOR,
453                 MODEST_TOOLBAR_BUTTON_SEND_RECEIVE,
454                 MODEST_TOOLBAR_SEPARATOR,
455                 MODEST_TOOLBAR_BUTTON_PREV,
456                 MODEST_TOOLBAR_BUTTON_NEXT,
457                 MODEST_TOOLBAR_SEPARATOR,               
458                 MODEST_TOOLBAR_BUTTON_DELETE
459         };              
460         
461         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
462
463         for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
464                 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
465         
466         toolbar = modest_widget_factory_get_main_toolbar (priv->widget_factory, buttons);
467         g_slist_free (buttons);
468         
469         g_signal_connect (G_OBJECT(toolbar), "button_clicked",
470                           G_CALLBACK(on_toolbar_button_clicked), self);
471         
472         return toolbar;
473 }
474
475
476
477 static void
478 restore_sizes (ModestMainWindow *self)
479 {
480         ModestConf *conf;
481         ModestMainWindowPrivate *priv;
482         
483         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
484         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
485
486         modest_widget_memory_restore_settings (conf,GTK_WIDGET(self),
487                                                "modest-main-window");
488         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->folder_paned),
489                                                "modest-folder-paned");
490         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->msg_paned),
491                                                "modest-msg-paned");
492         modest_widget_memory_restore_settings (conf, GTK_WIDGET(priv->main_paned),
493                                                "modest-main-paned");
494 }
495
496
497 static void
498 save_sizes (ModestMainWindow *self)
499 {
500         ModestMainWindowPrivate *priv;
501         ModestConf *conf;
502         
503         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
504         conf = modest_tny_platform_factory_get_modest_conf_instance (priv->factory);
505         
506         modest_widget_memory_save_settings (conf,GTK_WIDGET(self),
507                                             "modest-main-window");
508         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->folder_paned),
509                                             "modest-folder-paned");
510         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->msg_paned),
511                                             "modest-msg-paned");
512         modest_widget_memory_save_settings (conf, GTK_WIDGET(priv->main_paned),
513                                             "modest-main-paned");
514 }
515
516 static GtkWidget*
517 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
518 {
519         GtkWidget *win;
520
521         win = gtk_scrolled_window_new (NULL, NULL);
522         gtk_scrolled_window_set_policy
523                 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
524                  GTK_POLICY_AUTOMATIC);
525         
526         if (needs_viewport)
527                 gtk_scrolled_window_add_with_viewport
528                         (GTK_SCROLLED_WINDOW(win), widget);
529         else
530                 gtk_container_add (GTK_CONTAINER(win),
531                                    widget);
532
533         return win;
534 }
535
536
537 static gboolean
538 on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self)
539 {
540         save_sizes (self);
541         return FALSE;
542 }
543
544 static GtkWidget*
545 favorites_view ()
546 {
547         GtkWidget *favorites;
548         GtkTreeStore *store;
549         GtkTreeViewColumn *col;
550
551         store = gtk_tree_store_new (1, G_TYPE_STRING);
552         favorites = gtk_tree_view_new_with_model (GTK_TREE_MODEL(store));
553         col = gtk_tree_view_column_new_with_attributes (_("Favorites"),
554                                                         gtk_cell_renderer_text_new(),
555                                                         "text", 0, NULL);
556         
557         gtk_tree_view_append_column (GTK_TREE_VIEW(favorites), col);
558         gtk_widget_show_all (favorites);
559
560         g_object_unref (G_OBJECT(store));
561
562         return favorites;
563 }
564
565
566
567 GtkWidget*
568 modest_main_window_new (ModestWidgetFactory *widget_factory)
569 {
570         GObject *obj;
571         ModestMainWindowPrivate *priv;
572         
573         GtkWidget *main_vbox;
574         GtkWidget *status_hbox;
575         GtkWidget *header_win, *folder_win, *favorites_win;
576         
577         g_return_val_if_fail (widget_factory, NULL);
578
579         obj  = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
580         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
581
582         g_object_ref (widget_factory);
583         priv->widget_factory = widget_factory;
584
585         /* widgets from factory */
586         priv->folder_view = modest_widget_factory_get_folder_view (widget_factory);
587         priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
588         priv->msg_preview = modest_widget_factory_get_msg_preview (widget_factory);
589         
590         folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
591                                                  FALSE);
592         header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
593                                                  FALSE);                           
594         favorites_win = wrapped_in_scrolled_window (favorites_view(),FALSE);                       
595         
596         /* tool/menubar */
597         priv->menubar = menubar_new (MODEST_MAIN_WINDOW(obj));
598         priv->toolbar = GTK_WIDGET(toolbar_new (MODEST_MAIN_WINDOW(obj)));
599
600         /* paned */
601         priv->folder_paned = gtk_vpaned_new ();
602         priv->msg_paned = gtk_vpaned_new ();
603         priv->main_paned = gtk_hpaned_new ();
604         gtk_paned_add1 (GTK_PANED(priv->main_paned), priv->folder_paned);
605         gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
606         gtk_paned_add1 (GTK_PANED(priv->folder_paned), favorites_win);
607         gtk_paned_add2 (GTK_PANED(priv->folder_paned), folder_win);
608         gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
609         gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
610
611         gtk_widget_show (GTK_WIDGET(priv->header_view));
612         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
613
614         
615         /* status bar / progress */
616         status_hbox = gtk_hbox_new (FALSE, 0);
617         gtk_box_pack_start (GTK_BOX(status_hbox),
618                             modest_widget_factory_get_folder_info_label (widget_factory),
619                             FALSE,FALSE, 6);
620         gtk_box_pack_start (GTK_BOX(status_hbox),
621                             modest_widget_factory_get_status_bar(widget_factory),
622                             TRUE, TRUE, 0);
623         gtk_box_pack_start (GTK_BOX(status_hbox),
624                             modest_widget_factory_get_progress_bar(widget_factory),
625                             FALSE, FALSE, 0);
626         gtk_box_pack_start (GTK_BOX(status_hbox),
627                           modest_widget_factory_get_online_toggle(widget_factory),
628                           FALSE, FALSE, 0);
629
630         /* putting it all together... */
631         main_vbox = gtk_vbox_new (FALSE, 6);
632         gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
633         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
634         gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE,0);
635         gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 0);
636         
637         gtk_container_add (GTK_CONTAINER(obj), main_vbox);
638         restore_sizes (MODEST_MAIN_WINDOW(obj));        
639
640         gtk_window_set_title (GTK_WINDOW(obj), "Modest");
641         gtk_window_set_icon  (GTK_WINDOW(obj),
642                               modest_icon_factory_get_icon (MODEST_APP_ICON));
643         
644         gtk_widget_show_all (main_vbox);
645
646         g_signal_connect (G_OBJECT(obj), "delete-event",
647                           G_CALLBACK(on_delete_event), obj);
648         
649         return GTK_WIDGET(obj);
650 }