* when the window-manager is asked for the main_window, and none such
[modest] / src / widgets / modest-window-mgr.c
1 /* Copyright (c) 2006,2007 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 <string.h>
31 #include "modest-window-mgr.h"
32 #include "modest-runtime.h"
33 #include "modest-tny-folder.h"
34 #include "modest-ui-actions.h"
35 #include "modest-platform.h"
36 #include "widgets/modest-main-window.h"
37 #include "widgets/modest-msg-edit-window.h"
38 #include "widgets/modest-msg-view-window.h"
39
40
41 /* 'private'/'protected' functions */
42 static void modest_window_mgr_class_init (ModestWindowMgrClass *klass);
43 static void modest_window_mgr_init       (ModestWindowMgr *obj);
44 static void modest_window_mgr_finalize   (GObject *obj);
45
46 static gboolean on_window_destroy            (ModestWindow *window,
47                                               GdkEvent *event,
48                                               ModestWindowMgr *self);
49
50 /* list my signals  */
51 enum {
52         /* MY_SIGNAL_1, */
53         /* MY_SIGNAL_2, */
54         LAST_SIGNAL
55 };
56
57 typedef struct _ModestWindowMgrPrivate ModestWindowMgrPrivate;
58 struct _ModestWindowMgrPrivate {
59         GList        *window_list;
60         ModestWindow *main_window;
61         gboolean     fullscreen_mode;
62         gboolean     show_toolbars;
63         gboolean     show_toolbars_fullscreen;
64         
65         GSList       *windows_that_prevent_hibernation;
66         GSList       *preregistered_uids;
67         GHashTable   *destroy_handlers;
68         GHashTable   *viewer_handlers;
69 };
70 #define MODEST_WINDOW_MGR_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
71                                                MODEST_TYPE_WINDOW_MGR, \
72                                                ModestWindowMgrPrivate))
73 /* globals */
74 static GObjectClass *parent_class = NULL;
75
76 /* uncomment the following if you have defined any signals */
77 /* static guint signals[LAST_SIGNAL] = {0}; */
78
79 GType
80 modest_window_mgr_get_type (void)
81 {
82         static GType my_type = 0;
83         if (!my_type) {
84                 static const GTypeInfo my_info = {
85                         sizeof(ModestWindowMgrClass),
86                         NULL,           /* base init */
87                         NULL,           /* base finalize */
88                         (GClassInitFunc) modest_window_mgr_class_init,
89                         NULL,           /* class finalize */
90                         NULL,           /* class data */
91                         sizeof(ModestWindowMgr),
92                         1,              /* n_preallocs */
93                         (GInstanceInitFunc) modest_window_mgr_init,
94                         NULL
95                 };
96                 my_type = g_type_register_static (G_TYPE_OBJECT,
97                                                   "ModestWindowMgr",
98                                                   &my_info, 0);
99         }
100         return my_type;
101 }
102
103 static void
104 modest_window_mgr_class_init (ModestWindowMgrClass *klass)
105 {
106         GObjectClass *gobject_class;
107         gobject_class = (GObjectClass*) klass;
108
109         parent_class            = g_type_class_peek_parent (klass);
110         gobject_class->finalize = modest_window_mgr_finalize;
111
112         g_type_class_add_private (gobject_class, sizeof(ModestWindowMgrPrivate));
113 }
114
115 static void
116 modest_window_mgr_init (ModestWindowMgr *obj)
117 {
118         ModestWindowMgrPrivate *priv;
119
120         priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
121         priv->window_list = NULL;
122         priv->main_window = NULL;
123         priv->fullscreen_mode = FALSE;
124
125         priv->preregistered_uids = NULL;
126
127         /* Could not initialize it from gconf, singletons are not
128            ready yet */
129         priv->show_toolbars = FALSE;
130         priv->show_toolbars_fullscreen = FALSE;
131         priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);   
132         priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
133 }
134
135 static void
136 modest_window_mgr_finalize (GObject *obj)
137 {
138         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
139
140         if (priv->window_list) {
141                 GList *iter = priv->window_list;
142                 /* unregister pending windows */
143                 while (iter) {
144                         modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), 
145                                                              MODEST_WINDOW (iter->data));
146                         iter = g_list_next (iter);
147                 }
148                 g_list_free (priv->window_list);
149                 priv->window_list = NULL;
150         }
151
152         g_slist_foreach (priv->preregistered_uids, (GFunc)g_free, NULL);
153         g_slist_free (priv->preregistered_uids);
154
155         
156         /* Free the hash table with the handlers */
157         if (priv->destroy_handlers) {
158                 g_hash_table_destroy (priv->destroy_handlers);
159                 priv->destroy_handlers = NULL;
160         }
161
162         if (priv->viewer_handlers) {
163                 g_hash_table_destroy (priv->viewer_handlers);
164                 priv->viewer_handlers = NULL;
165         }
166
167         /* Do not unref priv->main_window because it does not hold a
168            new reference */
169
170         G_OBJECT_CLASS(parent_class)->finalize (obj);
171 }
172
173 ModestWindowMgr*
174 modest_window_mgr_new (void)
175 {
176         return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_WINDOW_MGR, NULL));
177 }
178
179
180
181
182 /* do we have uid? */
183 static gboolean
184 has_uid (GSList *list, const gchar *uid)
185 {
186         GSList *cursor = list;
187
188         if (!uid)
189                 return FALSE;
190         
191         while (cursor) {
192                 if (cursor->data && strcmp (cursor->data, uid) == 0)
193                         return TRUE;
194                 cursor = g_slist_next (cursor);
195         }
196         return FALSE;
197 }
198
199
200 /* remove all from the list have have uid = uid */
201 static GSList*
202 remove_uid (GSList *list, const gchar *uid)
203 {
204         GSList *cursor = list, *start = list;
205         
206         if (!uid)
207                 return FALSE;
208         
209         while (cursor) {
210                 GSList *next = g_slist_next (cursor);
211                 if (cursor->data && strcmp (cursor->data, uid) == 0) {
212                         g_free (cursor->data);
213                         start = g_slist_delete_link (start, cursor);
214                 }
215                 cursor = next;
216         }
217         return start;
218 }
219
220
221 static GSList *
222 append_uid (GSList *list, const gchar *uid)
223 {
224         return g_slist_append (list, g_strdup(uid));
225 }
226
227
228
229 void 
230 modest_window_mgr_register_header (ModestWindowMgr *self,  TnyHeader *header)
231 {
232         ModestWindowMgrPrivate *priv;
233         gchar* uid;
234         
235         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
236         g_return_if_fail (TNY_IS_HEADER(header));
237                 
238         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
239         uid = modest_tny_folder_get_header_unique_id (header);
240
241
242         if (!has_uid (priv->preregistered_uids, uid)) {
243                 g_debug ("registering new uid %s", uid);
244                 priv->preregistered_uids = append_uid (priv->preregistered_uids, uid);
245         } else
246                 g_debug ("already had uid %s", uid);
247
248         g_free (uid);
249 }
250
251 void 
252 modest_window_mgr_unregister_header (ModestWindowMgr *self,  TnyHeader *header)
253 {
254         ModestWindowMgrPrivate *priv;
255         gchar* uid;
256         
257         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
258         g_return_if_fail (TNY_IS_HEADER(header));
259                 
260         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
261         uid = modest_tny_folder_get_header_unique_id (header);
262         
263         if (!has_uid (priv->preregistered_uids, uid)) {
264                 g_debug ("trying to unregister non-existing uid %s", uid);
265                 priv->preregistered_uids = append_uid (priv->preregistered_uids, uid);
266         } else
267                 g_debug ("unregistering uid %s", uid);
268
269         if (has_uid (priv->preregistered_uids, uid)) {
270                 priv->preregistered_uids = remove_uid (priv->preregistered_uids, uid);
271                 if (has_uid (priv->preregistered_uids, uid))
272                         g_debug ("BUG: uid %s NOT removed", uid);
273                 else
274                         g_debug ("uid %s removed", uid);
275         }
276
277         g_free (uid);
278 }
279
280 static gint
281 compare_msguids (ModestWindow *win,
282                  const gchar *uid)
283 {
284         const gchar *msg_uid;
285
286         if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win)))
287                 return 1;
288
289         /* Get message uid from msg window */
290         if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
291                 msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win));
292         } else {
293                 msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
294         }
295         
296         if (msg_uid && uid &&!strcmp (msg_uid, uid))
297                 return 0;
298         else
299                 return 1;
300 }
301
302
303
304 gboolean
305 modest_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
306                                           ModestWindow **win)
307 {
308         ModestWindowMgrPrivate *priv;
309         gchar* uid;
310         gboolean has_header, has_window = FALSE;
311         GList *item = NULL;
312
313         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
314         g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
315         
316         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
317
318         uid = modest_tny_folder_get_header_unique_id (header);
319         
320         if (win)
321                 *win = NULL;
322         
323 /*      g_debug ("windows in list: %d", g_list_length (priv->window_list)); */
324 /*      g_debug ("headers in list: %d", g_slist_length (priv->preregistered_uids)); */
325
326         has_header = has_uid (priv->preregistered_uids, uid);
327                 
328         item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids);
329         if (item) {
330                 has_window = TRUE;
331                 if (win) {
332                         if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) && 
333                             (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
334                                 g_debug ("not a valid window!");
335                         else {
336                                 g_debug ("found a window");
337                                 *win = MODEST_WINDOW (item->data);
338                         }
339                 }
340         }
341
342         g_free (uid);
343         return has_header || has_window;
344 }
345
346
347
348 void 
349 modest_window_mgr_register_window (ModestWindowMgr *self, 
350                                    ModestWindow *window)
351 {
352         static gboolean first_time = TRUE;
353         GList *win;
354         gboolean show;
355         ModestWindowMgrPrivate *priv;
356         gint *handler_id;
357
358         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
359         g_return_if_fail (MODEST_IS_WINDOW (window));
360
361         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
362
363         win = g_list_find (priv->window_list, window);
364         if (win) {
365                 g_warning ("Trying to register an already registered window");
366                 return;
367         }
368         
369         /* Check that it's not a second main window */
370         if (MODEST_IS_MAIN_WINDOW (window)) {
371                 if (priv->main_window) {
372                         g_warning ("Trying to register a second main window");
373                         return;
374                 } else {
375                         priv->main_window = window;
376                 }
377         }
378
379         /* remove from the list of pre-registered uids */
380         if (MODEST_IS_MSG_VIEW_WINDOW(window)) {
381                 const gchar *uid = modest_msg_view_window_get_message_uid
382                         (MODEST_MSG_VIEW_WINDOW (window));
383
384                 g_debug ("registering window for %s", uid);
385                                 
386                 if (!has_uid (priv->preregistered_uids, uid)) 
387                         g_debug ("weird: no uid for window (%s)", uid);
388
389                 priv->preregistered_uids = 
390                         remove_uid (priv->preregistered_uids,
391                                     modest_msg_view_window_get_message_uid
392                                     (MODEST_MSG_VIEW_WINDOW (window)));
393         } else if (MODEST_IS_MSG_EDIT_WINDOW(window)) {
394                 const gchar *uid = modest_msg_edit_window_get_message_uid
395                         (MODEST_MSG_EDIT_WINDOW (window));
396
397                 g_debug ("registering window for %s", uid);
398                                 
399                 if (!has_uid (priv->preregistered_uids, uid)) 
400                         g_debug ("weird: no uid for window (%s)", uid);
401
402                 priv->preregistered_uids = 
403                         remove_uid (priv->preregistered_uids,
404                                     modest_msg_edit_window_get_message_uid
405                                     (MODEST_MSG_EDIT_WINDOW (window)));
406         }
407         
408         /* Add to list. Keep a reference to the window */
409         g_object_ref (window);
410         priv->window_list = g_list_prepend (priv->window_list, window);
411
412         /* Listen to object destruction */
413         handler_id = g_malloc0 (sizeof (gint));
414         *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
415         g_hash_table_insert (priv->destroy_handlers, window, handler_id);
416
417         /* If there is a msg view window, let the main window listen the msg-changed signal */
418         if (MODEST_IS_MSG_VIEW_WINDOW(window) && priv->main_window) {
419                 gulong *handler;
420                 handler = g_malloc0 (sizeof (gulong));
421                 *handler = g_signal_connect (window, "msg-changed", 
422                                              G_CALLBACK (modest_main_window_on_msg_view_window_msg_changed), 
423                                              priv->main_window);
424                 g_hash_table_insert (priv->viewer_handlers, window, handler);
425         }
426
427         /* Put into fullscreen if needed */
428         if (priv->fullscreen_mode)
429                 gtk_window_fullscreen (GTK_WINDOW (window));
430
431         /* Fill caches */
432         if (first_time) {
433                 ModestConf *conf = modest_runtime_get_conf ();
434                 priv->show_toolbars = 
435                         modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR, NULL);
436                 priv->show_toolbars_fullscreen = 
437                         modest_conf_get_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, NULL);
438                 first_time = FALSE;
439         }
440
441         /* Show/hide toolbar */
442         if (priv->fullscreen_mode)
443                 show = priv->show_toolbars_fullscreen;
444         else
445                 show = priv->show_toolbars;
446         modest_window_show_toolbar (window, show);
447 }
448
449 static gboolean
450 on_window_destroy (ModestWindow *window, 
451                    GdkEvent *event,
452                    ModestWindowMgr *self)
453 {
454         /* Specific stuff first */
455         if (MODEST_IS_MAIN_WINDOW (window)) {
456                 ModestWindowMgrPrivate *priv;
457                 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
458
459                 /* If more than one window already opened */
460                 if (g_list_length (priv->window_list) > 1) {
461
462                         /* If the user wants to close all the windows */
463                         if (modest_main_window_close_all (MODEST_MAIN_WINDOW (window))) {
464                                 GList *iter = priv->window_list;
465                                 do {
466                                         if (iter->data != window) {
467                                                 GList *tmp = iter->next;
468                                                 on_window_destroy (MODEST_WINDOW (iter->data),
469                                                                    event,
470                                                                    self);
471                                                 iter = tmp;
472                                         } else {
473                                                 iter = g_list_next (iter);
474                                         }
475                                 } while (iter);
476                         }
477                 }
478         }
479         else {
480                 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
481                         gboolean sent = FALSE;
482                         gint response = GTK_RESPONSE_ACCEPT;
483                         sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
484                         /* Save currently edited message to Drafts if it was not sent */
485                         if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
486                                 
487                                 response =
488                                         modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
489                                                                                  _("mcen_nc_no_email_message_modified_save_changes"));
490                                 /* Save to drafts */
491                                 if (response != GTK_RESPONSE_CANCEL)                            
492                                         modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window));
493                                 
494                         } 
495                 }
496         }
497
498         /* Save configuration state (TODO: why edit window does not require this function ?) */
499         if (!MODEST_IS_MSG_EDIT_WINDOW (window)) 
500                 modest_window_save_state (MODEST_WINDOW(window));
501
502
503         /* Unregister window */
504         modest_window_mgr_unregister_window (self, window);
505         
506         return FALSE;
507 }
508
509 static void
510 disconnect_msg_changed (gpointer key, 
511                         gpointer value, 
512                         gpointer user_data)
513 {
514         gulong *handler_id;
515
516         handler_id = (gulong *) value;
517         g_signal_handler_disconnect (G_OBJECT (key), *handler_id);
518 }
519
520
521 void 
522 modest_window_mgr_unregister_window (ModestWindowMgr *self, 
523                                      ModestWindow *window)
524 {
525         GList *win;
526         ModestWindowMgrPrivate *priv;
527         gulong *tmp, handler_id;
528
529         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
530         g_return_if_fail (MODEST_IS_WINDOW (window));
531
532         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
533
534         win = g_list_find (priv->window_list, window);
535         if (!win) {
536                 g_warning ("Trying to unregister a window that has not being registered yet");
537                 return;
538         }
539
540         /* If it's the main window unset it */
541         if (priv->main_window == window) {
542                 priv->main_window = NULL;
543
544                 /* Disconnect all emissions of msg-changed */
545                 g_hash_table_foreach (priv->viewer_handlers, 
546                                       disconnect_msg_changed, 
547                                       NULL);
548                 g_hash_table_destroy (priv->viewer_handlers);
549                 priv->viewer_handlers = NULL;
550         }
551
552         /* Remove the viewer window handler from the hash table. The
553            HashTable could not exist if the main window was closeed
554            when there were other windows remaining */
555         if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
556                 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
557                 g_signal_handler_disconnect (window, *tmp);
558                 g_hash_table_remove (priv->viewer_handlers, window);
559         }
560
561         /* Save state */
562         modest_window_save_state (window);
563
564         /* Remove from list & hash table */
565         priv->window_list = g_list_remove_link (priv->window_list, win);
566         tmp = g_hash_table_lookup (priv->destroy_handlers, window);
567         handler_id = *tmp;
568         g_hash_table_remove (priv->destroy_handlers, window);
569
570         /* Disconnect the "delete-event" handler, we won't need it anymore */
571         g_signal_handler_disconnect (window, handler_id);
572
573         /* Disconnect all the window signals */
574         modest_window_disconnect_signals (window);
575         
576         /* Destroy the window */
577         gtk_widget_destroy (win->data);
578         
579         /* If there are no more windows registered then exit program */
580         if (priv->window_list == NULL) {
581                 ModestConf *conf = modest_runtime_get_conf ();
582
583                 /* Save show toolbar status */
584                 modest_conf_set_bool (conf, MODEST_CONF_SHOW_TOOLBAR_FULLSCREEN, 
585                                       priv->show_toolbars_fullscreen, NULL);
586                 modest_conf_set_bool (conf, MODEST_CONF_SHOW_TOOLBAR, 
587                                       priv->show_toolbars, NULL);
588
589                 /* Quit main loop */
590                 /* FIXME: do we ever need to do this here? */
591                 if (gtk_main_level() > 0)
592                         gtk_main_quit ();
593         }
594 }
595
596 void
597 modest_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
598                                        gboolean on)
599 {
600         ModestWindowMgrPrivate *priv;
601         GList *win = NULL;
602
603         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
604
605         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
606
607         /* If there is no change do nothing */
608         if (priv->fullscreen_mode == on)
609                 return;
610
611         priv->fullscreen_mode = on;
612
613         /* Update windows */
614         win = priv->window_list;
615         while (win) {
616                 if (on) {
617                         gtk_window_fullscreen (GTK_WINDOW (win->data));
618                         modest_window_show_toolbar (MODEST_WINDOW (win->data), 
619                                                     priv->show_toolbars_fullscreen);
620                 } else {
621                         gtk_window_unfullscreen (GTK_WINDOW (win->data));
622                         modest_window_show_toolbar (MODEST_WINDOW (win->data), 
623                                                     priv->show_toolbars);
624                 }
625                 win = g_list_next (win);
626         }
627 }
628
629 gboolean
630 modest_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
631 {
632         ModestWindowMgrPrivate *priv;
633
634         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
635
636         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
637
638         return priv->fullscreen_mode;
639 }
640
641 void 
642 modest_window_mgr_show_toolbars (ModestWindowMgr *self,
643                                  gboolean show_toolbars,
644                                  gboolean fullscreen)
645 {
646         ModestWindowMgrPrivate *priv;
647
648         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
649
650         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
651
652         /* If nothing changes then return. Otherwise cache it, do not
653            save to GConf for the moment, it will be done when all
654            windows become unregistered in order to avoid unnecessary
655            ModestConf calls */
656         if (fullscreen) {
657                 if (priv->show_toolbars_fullscreen == show_toolbars)
658                         return;
659                 else
660                         priv->show_toolbars_fullscreen = show_toolbars;
661         } else {
662                 if (priv->show_toolbars == show_toolbars)
663                         return;
664                 else
665                         priv->show_toolbars = show_toolbars;
666         }
667
668         /* Apply now if the view mode is the right one */
669         if ((fullscreen && priv->fullscreen_mode) ||
670             (!fullscreen && !priv->fullscreen_mode)) {
671
672                 GList *win = priv->window_list;
673
674                 while (win) {
675                         modest_window_show_toolbar (MODEST_WINDOW (win->data),
676                                                     show_toolbars);
677                         win = g_list_next (win);
678                 }
679         }
680 }
681
682 ModestWindow*  
683 modest_window_mgr_get_main_window (ModestWindowMgr *self)
684 {
685         ModestWindowMgrPrivate *priv;
686         
687         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL);
688         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
689
690         /* create the main window, if it hasn't been created yet */
691         if (!priv->main_window) {
692                 g_debug ("%s: creating main window\n", __FUNCTION__);
693                 modest_window_mgr_register_window (self, modest_main_window_new ());
694         }
695         
696         return priv->main_window;
697 }
698
699 static void
700 on_nonhibernating_window_hide(GtkWidget *widget, gpointer user_data)
701 {
702         ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
703         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
704         
705         /* Forget this window,
706          * so hibernation will be allowed again if no windows are remembered: */
707         priv->windows_that_prevent_hibernation =
708                 g_slist_remove (priv->windows_that_prevent_hibernation, GTK_WINDOW(widget));
709 }
710
711 static void
712 on_nonhibernating_window_show(GtkWidget *widget, gpointer user_data)
713 {
714         ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
715         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
716         
717         GtkWindow *window = GTK_WINDOW (widget);
718         
719         priv->windows_that_prevent_hibernation = 
720                         g_slist_append (priv->windows_that_prevent_hibernation, window);
721         
722         /* Allow hibernation again when the window has been hidden: */
723         g_signal_connect (window, "hide", 
724                 G_CALLBACK (on_nonhibernating_window_hide), self);
725 }
726
727 void modest_window_mgr_prevent_hibernation_while_window_is_shown (ModestWindowMgr *self,
728                                                                   GtkWindow *window)
729 {
730         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
731         
732         if (GTK_WIDGET_VISIBLE(window)) {
733                 on_nonhibernating_window_show (GTK_WIDGET (window), self);
734         } else {
735                 /* Wait for it to be shown: */
736                 g_signal_connect (window, "show", 
737                         G_CALLBACK (on_nonhibernating_window_show), self);      
738         }
739 }
740
741 gboolean modest_window_mgr_get_hibernation_is_prevented (ModestWindowMgr *self)
742 {
743         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
744         
745         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
746         
747         /* Prevent hibernation if any open windows are currently 
748          * preventing hibernation: */
749         return (g_slist_length (priv->windows_that_prevent_hibernation) > 0);
750 }
751
752
753 void modest_window_mgr_save_state_for_all_windows (ModestWindowMgr *self)
754 {
755         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
756         
757         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
758
759         /* Iterate over all windows */
760         GList *win = priv->window_list;
761         while (win) {
762                 ModestWindow *window = MODEST_WINDOW (win->data);
763                 if (window) {
764                         /* This calls the vfunc, 
765                          * so each window can do its own thing: */
766                         modest_window_save_state (window);
767                 }       
768                 
769                 win = g_list_next (win);
770         }
771 }