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