* add icon for main window
[modest] / src / gtk2 / 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 <modest-widget-memory.h>
31 #include <modest-icon-factory.h>
32
33 #include "modest-main-window.h"
34 #include "modest-account-view-window.h"
35 #include "modest-edit-msg-window.h"
36 #include "modest-icon-names.h"
37
38
39 /* 'private'/'protected' functions */
40 static void modest_main_window_class_init    (ModestMainWindowClass *klass);
41 static void modest_main_window_init          (ModestMainWindow *obj);
42 static void modest_main_window_finalize      (GObject *obj);
43
44 static void restore_sizes (ModestMainWindow *self);
45 static void save_sizes (ModestMainWindow *self);
46
47 /* list my signals */
48 enum {
49         /* MY_SIGNAL_1, */
50         /* MY_SIGNAL_2, */
51         LAST_SIGNAL
52 };
53
54 typedef struct _ModestMainWindowPrivate ModestMainWindowPrivate;
55 struct _ModestMainWindowPrivate {
56
57         GtkWidget *toolbar;
58         GtkWidget *menubar;
59
60         GtkWidget *folder_paned;
61         GtkWidget *msg_paned;
62         GtkWidget *main_paned;
63         
64         ModestWidgetFactory *widget_factory;
65         ModestConf *conf;
66         ModestAccountMgr *account_mgr;
67         
68         ModestHeaderView *header_view;
69         ModestFolderView *folder_view;
70         ModestMsgView    *msg_preview;
71 };
72
73
74 #define MODEST_MAIN_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
75                                                 MODEST_TYPE_MAIN_WINDOW, \
76                                                 ModestMainWindowPrivate))
77 /* globals */
78 static GtkWindowClass *parent_class = NULL;
79
80 /* uncomment the following if you have defined any signals */
81 /* static guint signals[LAST_SIGNAL] = {0}; */
82
83 GType
84 modest_main_window_get_type (void)
85 {
86         static GType my_type = 0;
87         if (!my_type) {
88                 static const GTypeInfo my_info = {
89                         sizeof(ModestMainWindowClass),
90                         NULL,           /* base init */
91                         NULL,           /* base finalize */
92                         (GClassInitFunc) modest_main_window_class_init,
93                         NULL,           /* class finalize */
94                         NULL,           /* class data */
95                         sizeof(ModestMainWindow),
96                         1,              /* n_preallocs */
97                         (GInstanceInitFunc) modest_main_window_init,
98                         NULL
99                 };
100                 my_type = g_type_register_static (GTK_TYPE_WINDOW,
101                                                   "ModestMainWindow",
102                                                   &my_info, 0);
103         }
104         return my_type;
105 }
106
107 static void
108 modest_main_window_class_init (ModestMainWindowClass *klass)
109 {
110         GObjectClass *gobject_class;
111         gobject_class = (GObjectClass*) klass;
112
113         parent_class            = g_type_class_peek_parent (klass);
114         gobject_class->finalize = modest_main_window_finalize;
115
116         g_type_class_add_private (gobject_class, sizeof(ModestMainWindowPrivate));
117
118         /* signal definitions go here, e.g.: */
119 /*      signals[MY_SIGNAL_1] = */
120 /*              g_signal_new ("my_signal_1",....); */
121 /*      signals[MY_SIGNAL_2] = */
122 /*              g_signal_new ("my_signal_2",....); */
123 /*      etc. */
124 }
125
126 static void
127 modest_main_window_init (ModestMainWindow *obj)
128 {
129         ModestMainWindowPrivate *priv;
130
131         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
132
133         priv->widget_factory = NULL;
134         priv->conf           = NULL;
135         priv->account_mgr    = NULL;
136 }
137
138 static void
139 modest_main_window_finalize (GObject *obj)
140 {
141         ModestMainWindowPrivate *priv;  
142         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
143         if (priv->widget_factory) {
144                 g_object_unref (G_OBJECT(priv->widget_factory));
145                 priv->widget_factory = NULL;
146         }
147         if (priv->conf) {
148                 g_object_unref (G_OBJECT(priv->conf));
149                 priv->conf = NULL;
150         }               
151
152         if (priv->account_mgr) {
153                 g_object_unref (G_OBJECT(priv->account_mgr));
154                 priv->account_mgr = NULL;
155         }               
156
157         G_OBJECT_CLASS(parent_class)->finalize (obj);
158 }
159
160
161 static void
162 on_menu_about (GtkWidget *widget, gpointer data)
163 {
164         GtkWidget *about;
165         const gchar *authors[] = {
166                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
167                 NULL
168         };      
169         about = gtk_about_dialog_new ();
170         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
171         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
172         gtk_about_dialog_set_copyright (
173                 GTK_ABOUT_DIALOG(about),
174                 _("Copyright (c) 2006, Nokia Corporation\n"
175                   "All rights reserved."));
176         gtk_about_dialog_set_comments ( GTK_ABOUT_DIALOG(about),
177                 _("a modest e-mail client\n\n"
178                   "design and implementation: Dirk-Jan C. Binnema\n"
179                   "contributions from the fine people at KernelConcepts\n\n"
180                   "uses the tinymail email framework written by Philip van Hoof"));
181         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
182         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
183
184         gtk_dialog_run (GTK_DIALOG (about));
185         gtk_widget_destroy(about);
186 }
187
188
189 static void
190 on_menu_accounts (ModestMainWindow *self, guint action, GtkWidget *widget)
191 {
192         GtkWidget *account_win;
193         ModestMainWindowPrivate *priv;
194
195         g_return_if_fail (widget);
196         g_return_if_fail (self);
197         
198         priv        = MODEST_MAIN_WINDOW_GET_PRIVATE(self);     
199         account_win = modest_account_view_window_new (priv->account_mgr,
200                                                       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->conf,
218                                               MODEST_EDIT_TYPE_NEW,
219                                               NULL);
220         gtk_widget_show (msg_win);
221 }
222
223 static void
224 on_menu_quit (ModestMainWindow *self, guint action, GtkWidget *widget)
225 {
226         gtk_main_quit ();
227 }
228
229
230
231 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
232 static GtkItemFactoryEntry menu_items[] = {
233         { "/_File",             NULL,                   NULL,           0, "<Branch>" },
234         { "/File/_New",         "<control>N",           NULL,           0, "<StockItem>", GTK_STOCK_NEW },
235         { "/File/_Open",        "<control>O",           NULL,           0, "<StockItem>", GTK_STOCK_OPEN },
236         { "/File/_Save",        "<control>S",           NULL,           0, "<StockItem>", GTK_STOCK_SAVE },
237         { "/File/Save _As",     NULL,                   NULL,           0, "<Item>" },
238         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>" },
239         { "/File/_Quit",        "<CTRL>Q",              on_menu_quit,  0, "<StockItem>", GTK_STOCK_QUIT },
240
241         { "/_Edit",             NULL,                   NULL,           0, "<Branch>" },
242         { "/Edit/_Undo",        "<CTRL>Z",              NULL,           0, "<StockItem>", GTK_STOCK_UNDO },
243         { "/Edit/_Redo",        "<shift><CTRL>Z",       NULL,           0, "<StockItem>", GTK_STOCK_REDO },
244         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>" },
245         { "/Edit/Cut",          "<control>X",           NULL,           0, "<StockItem>", GTK_STOCK_CUT  },
246         { "/Edit/Copy",         "<CTRL>C",              NULL,           0, "<StockItem>", GTK_STOCK_COPY },
247         { "/Edit/Paste",        NULL,                   NULL,           0, "<StockItem>", GTK_STOCK_PASTE},
248         { "/Edit/sep1",         NULL,                   NULL,           0, "<Separator>" },
249         { "/Edit/Delete",       "<CTRL>Q",              NULL,           0, "<Item>" },
250         { "/Edit/Select all",   "<CTRL>A",              NULL,           0, "<Item>" },
251         { "/Edit/Deelect all",  "<Shift><CTRL>A",       NULL,           0, "<Item>" },
252
253         { "/_Actions",                NULL,             NULL,           0, "<Branch>" },
254         { "/Actions/_New Message",    NULL,             on_menu_new_message,            0, "<Item>" },
255         { "/Actions/_Reply",    NULL,                   NULL,           0, "<Item>" },
256         { "/Actions/_Forward",  NULL,                   NULL,           0, "<Item>" },
257         { "/Actions/_Bounce",   NULL,                   NULL,           0, "<Item>" },  
258         
259         { "/_Options",           NULL,                  NULL,           0, "<Branch>" },
260         { "/Options/_Accounts",  NULL,                  on_menu_accounts,0, "<Item>" },
261         { "/Options/_Contacts",  NULL,                  NULL,           0, "<Item>" },
262
263
264         { "/_Help",         NULL,                       NULL,           0, "<Branch>" },
265         { "/_Help/About",   NULL,                       on_menu_about,  0, "<StockItem>", GTK_STOCK_ABOUT},
266 };
267
268 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
269
270
271 static GtkWidget *
272 menubar_new (ModestMainWindow *self)
273 {
274         GtkItemFactory *item_factory;
275         GtkAccelGroup *accel_group;
276         
277         /* Make an accelerator group (shortcut keys) */
278         accel_group = gtk_accel_group_new ();
279         
280         /* Make an ItemFactory (that makes a menubar) */
281         item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
282                                              accel_group);
283         
284         /* This function generates the menu items. Pass the item factory,
285            the number of items in the array, the array itself, and any
286            callback data for the the menu items. */
287         gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
288         
289         ///* Attach the new accelerator group to the window. */
290         gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
291         
292         /* Finally, return the actual menu bar created by the item factory. */
293         return gtk_item_factory_get_widget (item_factory, "<main>");
294 }
295
296
297
298
299 static ModestHeaderView*
300 header_view_new (ModestMainWindow *self)
301 {
302         int i;
303         GSList *columns = NULL;
304         ModestHeaderView *header_view;
305         ModestMainWindowPrivate *priv;
306         ModestHeaderViewColumn cols[] = {
307                 MODEST_HEADER_VIEW_COLUMN_MSGTYPE,
308                 MODEST_HEADER_VIEW_COLUMN_ATTACH,
309                 MODEST_HEADER_VIEW_COLUMN_COMPACT_HEADER
310         };
311
312         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
313         
314         for (i = 0 ; i != sizeof(cols) / sizeof(ModestHeaderViewColumn); ++i)
315                 columns = g_slist_append (columns, GINT_TO_POINTER(cols[i]));
316
317         header_view = modest_widget_factory_get_header_view (priv->widget_factory);
318         modest_header_view_set_columns (header_view, columns);
319         g_slist_free (columns);
320
321         return header_view;
322 }
323
324
325 static void
326 restore_sizes (ModestMainWindow *self)
327 {
328         ModestMainWindowPrivate *priv;
329         
330         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
331         
332         modest_widget_memory_restore_settings (priv->conf,GTK_WIDGET(self),
333                                                "modest-main-window");
334         modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(priv->folder_paned),
335                                                "modest-folder-paned");
336         modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(priv->msg_paned),
337                                                "modest-msg-paned");
338         modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(priv->main_paned),
339                                                "modest-main-paned");
340
341 }
342
343
344 static void
345 save_sizes (ModestMainWindow *self)
346 {
347         ModestMainWindowPrivate *priv;
348         
349         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(self);
350         
351         modest_widget_memory_save_settings (priv->conf,GTK_WIDGET(self),
352                                             "modest-main-window");
353         modest_widget_memory_save_settings (priv->conf, GTK_WIDGET(priv->folder_paned),
354                                             "modest-folder-paned");
355         modest_widget_memory_save_settings (priv->conf, GTK_WIDGET(priv->msg_paned),
356                                             "modest-msg-paned");
357         modest_widget_memory_save_settings (priv->conf, GTK_WIDGET(priv->main_paned),
358                                             "modest-main-paned");
359
360         
361
362 }
363
364
365 static GtkWidget*
366 wrapped_in_scrolled_window (GtkWidget *widget, gboolean needs_viewport)
367 {
368         GtkWidget *win;
369
370         win = gtk_scrolled_window_new (NULL, NULL);
371         gtk_scrolled_window_set_policy
372                 (GTK_SCROLLED_WINDOW (win),GTK_POLICY_NEVER,
373                  GTK_POLICY_AUTOMATIC);
374         
375         if (needs_viewport)
376                 gtk_scrolled_window_add_with_viewport
377                         (GTK_SCROLLED_WINDOW(win), widget);
378         else
379                 gtk_container_add (GTK_CONTAINER(win),
380                                    widget);
381
382         return win;
383 }
384
385
386 static gboolean
387 on_delete_event (GtkWidget *widget, GdkEvent  *event, ModestMainWindow *self)
388 {
389         save_sizes (self);
390         gtk_widget_destroy (GTK_WIDGET(self));
391
392         return TRUE;
393 }
394
395
396
397
398 GtkWidget*
399 modest_main_window_new (ModestConf *conf, ModestAccountMgr *account_mgr,
400                         ModestWidgetFactory *factory)
401 {
402         GObject *obj;
403         ModestMainWindowPrivate *priv;
404         
405         GtkWidget *main_vbox;
406         GtkWidget *status_hbox;
407         GtkWidget *header_win, *folder_win; 
408         
409         g_return_val_if_fail (factory, NULL);
410         g_return_val_if_fail (conf, NULL);
411
412         obj  = g_object_new(MODEST_TYPE_MAIN_WINDOW, NULL);
413         priv = MODEST_MAIN_WINDOW_GET_PRIVATE(obj);
414
415         g_object_ref (factory);
416         priv->widget_factory = factory;
417
418         g_object_ref (conf);
419         priv->conf = conf;
420         
421         g_object_ref (account_mgr);
422         priv->account_mgr = account_mgr;
423
424
425         /* widgets from factory */
426         priv->folder_view = modest_widget_factory_get_folder_view (factory);
427         priv->header_view = header_view_new (MODEST_MAIN_WINDOW(obj));
428         priv->msg_preview = modest_widget_factory_get_msg_preview (factory);
429
430         folder_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->folder_view),
431                                                  FALSE);
432         header_win = wrapped_in_scrolled_window (GTK_WIDGET(priv->header_view),
433                                                  FALSE);                           
434         /* tool/menubar */
435         priv->menubar = menubar_new (MODEST_MAIN_WINDOW(obj));
436         priv->toolbar = gtk_toolbar_new ();
437
438         /* paned */
439         priv->folder_paned = gtk_vpaned_new ();
440         priv->msg_paned = gtk_vpaned_new ();
441         priv->main_paned = gtk_hpaned_new ();
442         gtk_paned_add1 (GTK_PANED(priv->main_paned), priv->folder_paned);
443         gtk_paned_add2 (GTK_PANED(priv->main_paned), priv->msg_paned);
444 //      gtk_paned_add1 (GTK_PANED(priv->folder_paned),
445 //                      gtk_label_new (_("Favorites")));
446         gtk_paned_add2 (GTK_PANED(priv->folder_paned), folder_win);
447         gtk_paned_add1 (GTK_PANED(priv->msg_paned), header_win);
448         gtk_paned_add2 (GTK_PANED(priv->msg_paned), GTK_WIDGET(priv->msg_preview));
449
450         gtk_widget_show (GTK_WIDGET(priv->header_view));
451         gtk_tree_view_columns_autosize (GTK_TREE_VIEW(priv->header_view));
452
453         
454         /* status bar / progress */
455         status_hbox = gtk_hbox_new (FALSE, 0);
456         gtk_box_pack_start (GTK_BOX(status_hbox),
457                             modest_widget_factory_get_status_bar(factory),
458                             TRUE, TRUE, 0);
459         gtk_box_pack_start (GTK_BOX(status_hbox),
460                             modest_widget_factory_get_progress_bar(factory),
461                             FALSE, FALSE, 0);
462         gtk_box_pack_start (GTK_BOX(status_hbox),
463                           modest_widget_factory_get_online_toggle(factory),
464                           FALSE, FALSE, 0);
465
466         /* putting it all together... */
467         main_vbox = gtk_vbox_new (FALSE, 6);
468         gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
469         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
470         gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_paned, TRUE, TRUE,0);
471         gtk_box_pack_start (GTK_BOX(main_vbox), status_hbox, FALSE, FALSE, 0);
472         
473         gtk_container_add (GTK_CONTAINER(obj), main_vbox);
474         restore_sizes (MODEST_MAIN_WINDOW(obj));        
475
476         gtk_window_set_title (GTK_WINDOW(obj), "Modest");
477         gtk_window_set_icon  (GTK_WINDOW(obj),
478                               modest_icon_factory_get_icon (MODEST_APP_ICON));
479         
480         gtk_widget_show_all (main_vbox);
481         
482         g_signal_connect (G_OBJECT(obj), "delete-event",
483                           G_CALLBACK(on_delete_event), obj);
484         
485         return GTK_WIDGET(obj);
486 }