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