Now window manager takes care of display state (fixes NB#97123).
[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 "modest-debug.h"
40
41
42 /* 'private'/'protected' functions */
43 static void modest_window_mgr_class_init (ModestWindowMgrClass *klass);
44 static void modest_window_mgr_init       (ModestWindowMgr *obj);
45 static void modest_window_mgr_finalize   (GObject *obj);
46
47 static gboolean modest_window_mgr_register_window_default (ModestWindowMgr *self, 
48                                                            ModestWindow *window,
49                                                            ModestWindow *parent);
50 static void modest_window_mgr_unregister_window_default (ModestWindowMgr *self, 
51                                                          ModestWindow *window);
52 static void modest_window_mgr_set_fullscreen_mode_default (ModestWindowMgr *self,
53                                                            gboolean on);
54 static gboolean modest_window_mgr_get_fullscreen_mode_default (ModestWindowMgr *self);
55 static void modest_window_mgr_show_toolbars_default (ModestWindowMgr *self,
56                                                      GType window_type,
57                                                      gboolean show_toolbars,
58                                                      gboolean fullscreen);
59 static ModestWindow* modest_window_mgr_get_main_window_default (ModestWindowMgr *self, gboolean show);
60 static GtkWindow *modest_window_mgr_get_modal_default (ModestWindowMgr *self);
61 static void modest_window_mgr_set_modal_default (ModestWindowMgr *self, 
62                                                  GtkWindow *window,
63                                                  GtkWindow *parent);
64 static gboolean modest_window_mgr_close_all_windows_default (ModestWindowMgr *self);
65 static gboolean modest_window_mgr_find_registered_header_default (ModestWindowMgr *self, 
66                                                                   TnyHeader *header,
67                                                                   ModestWindow **win);
68 static GList *modest_window_mgr_get_window_list_default (ModestWindowMgr *self);
69 static ModestWindow *modest_window_mgr_show_initial_window_default (ModestWindowMgr *self);
70 static ModestWindow *modest_window_mgr_get_current_top_default (ModestWindowMgr *self);
71 static gboolean modest_window_mgr_screen_is_on_default (ModestWindowMgr *self);
72
73 /* list my signals  */
74 enum {
75         WINDOW_LIST_EMPTY_SIGNAL,
76         NUM_SIGNALS
77 };
78
79 typedef struct _ModestWindowMgrPrivate ModestWindowMgrPrivate;
80 struct _ModestWindowMgrPrivate {
81         guint         banner_counter;
82
83         ModestWindow *main_window;
84
85         GSList       *windows_that_prevent_hibernation;
86         GSList       *preregistered_uids;
87         
88         guint        closing_time;
89
90         GtkWidget    *cached_view;
91         GtkWidget    *cached_editor;
92         guint        idle_load_view_id;
93         guint        idle_load_editor_id;
94 };
95
96 #define MODEST_WINDOW_MGR_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
97                                                MODEST_TYPE_WINDOW_MGR, \
98                                                ModestWindowMgrPrivate))
99 /* globals */
100 static GObjectClass *parent_class = NULL;
101
102 /* uncomment the following if you have defined any signals */
103 static guint signals[NUM_SIGNALS] = {0};
104
105 GType
106 modest_window_mgr_get_type (void)
107 {
108         static GType my_type = 0;
109         if (!my_type) {
110                 static const GTypeInfo my_info = {
111                         sizeof(ModestWindowMgrClass),
112                         NULL,           /* base init */
113                         NULL,           /* base finalize */
114                         (GClassInitFunc) modest_window_mgr_class_init,
115                         NULL,           /* class finalize */
116                         NULL,           /* class data */
117                         sizeof(ModestWindowMgr),
118                         1,              /* n_preallocs */
119                         (GInstanceInitFunc) modest_window_mgr_init,
120                         NULL
121                 };
122                 my_type = g_type_register_static (G_TYPE_OBJECT,
123                                                   "ModestWindowMgr",
124                                                   &my_info, 0);
125         }
126         return my_type;
127 }
128
129 static void
130 modest_window_mgr_class_init (ModestWindowMgrClass *klass)
131 {
132         GObjectClass *gobject_class;
133         ModestWindowMgrClass *mgr_class;
134
135         gobject_class = (GObjectClass*) klass;
136         mgr_class = (ModestWindowMgrClass *) klass;
137
138         parent_class            = g_type_class_peek_parent (klass);
139         gobject_class->finalize = modest_window_mgr_finalize;
140         mgr_class->register_window = modest_window_mgr_register_window_default;
141         mgr_class->unregister_window = modest_window_mgr_unregister_window_default;
142         mgr_class->set_fullscreen_mode = modest_window_mgr_set_fullscreen_mode_default;
143         mgr_class->get_fullscreen_mode = modest_window_mgr_get_fullscreen_mode_default;
144         mgr_class->show_toolbars = modest_window_mgr_show_toolbars_default;
145         mgr_class->get_main_window = modest_window_mgr_get_main_window_default;
146         mgr_class->get_modal = modest_window_mgr_get_modal_default;
147         mgr_class->set_modal = modest_window_mgr_set_modal_default;
148         mgr_class->close_all_windows = modest_window_mgr_close_all_windows_default;
149         mgr_class->find_registered_header = modest_window_mgr_find_registered_header_default;
150         mgr_class->get_window_list = modest_window_mgr_get_window_list_default;
151         mgr_class->show_initial_window = modest_window_mgr_show_initial_window_default;
152         mgr_class->get_current_top = modest_window_mgr_get_current_top_default;
153         mgr_class->screen_is_on = modest_window_mgr_screen_is_on_default;
154
155         g_type_class_add_private (gobject_class, sizeof(ModestWindowMgrPrivate));
156
157
158         /**
159          * ModestWindowMgr::window-list-empty
160          * @self: the #ModestWindowMgr that emits the signal
161          * @user_data: user data set when the signal handler was connected
162          *
163          * Issued whenever the window list becomes empty
164          */
165         signals[WINDOW_LIST_EMPTY_SIGNAL] =
166                 g_signal_new ("window-list-empty",
167                               G_TYPE_FROM_CLASS (gobject_class),
168                               G_SIGNAL_RUN_FIRST,
169                               G_STRUCT_OFFSET (ModestWindowMgrClass, window_list_empty),
170                               NULL, NULL,
171                               g_cclosure_marshal_VOID__VOID,
172                               G_TYPE_NONE, 0);
173 }
174
175 static gboolean
176 idle_load_view (ModestWindowMgr *mgr)
177 {
178         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (mgr);
179         
180         priv->cached_view = g_object_new (MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
181         priv->idle_load_view_id = 0;
182         return FALSE;
183 }
184
185 static gboolean
186 idle_load_editor (ModestWindowMgr *mgr)
187 {
188         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (mgr);
189         
190         priv->cached_editor = g_object_new (MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
191         priv->idle_load_editor_id = 0;
192         return FALSE;
193 }
194
195 static void
196 load_new_view (ModestWindowMgr *self)
197 {
198         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
199         if ((priv->cached_view == NULL) && (priv->idle_load_view_id == 0))
200                 priv->idle_load_view_id = g_idle_add ((GSourceFunc) idle_load_view, self);
201 }
202
203 static void
204 load_new_editor (ModestWindowMgr *self)
205 {
206         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
207         if ((priv->cached_editor == NULL) && (priv->idle_load_editor_id == 0))
208                 priv->idle_load_editor_id = g_idle_add ((GSourceFunc) idle_load_editor, self);
209 }
210
211 static void
212 modest_window_mgr_init (ModestWindowMgr *obj)
213 {
214         ModestWindowMgrPrivate *priv;
215
216         priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
217         priv->banner_counter = 0;
218         priv->main_window = NULL;
219
220         priv->preregistered_uids = NULL;
221
222         priv->closing_time = 0;
223
224         priv->cached_view = NULL;
225         priv->cached_editor = NULL;
226
227         priv->windows_that_prevent_hibernation = NULL;
228 }
229
230 static void
231 modest_window_mgr_finalize (GObject *obj)
232 {
233         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
234
235         if (priv->idle_load_view_id > 0) {
236                 g_source_remove (priv->idle_load_view_id);
237                 priv->idle_load_view_id = 0;
238         }
239         
240         if (priv->idle_load_editor_id > 0) {
241                 g_source_remove (priv->idle_load_editor_id);
242                 priv->idle_load_editor_id = 0;
243         }
244         
245         if (priv->cached_view) {
246                 gtk_widget_destroy (priv->cached_view);
247                 priv->cached_view = NULL;
248         }
249         if (priv->cached_editor) {
250                 gtk_widget_destroy (priv->cached_editor);
251                 priv->cached_editor = NULL;
252         }
253
254         if (priv->windows_that_prevent_hibernation) {
255                 g_slist_free (priv->windows_that_prevent_hibernation);
256                 priv->cached_editor = NULL;
257         }
258
259         g_slist_foreach (priv->preregistered_uids, (GFunc)g_free, NULL);
260         g_slist_free (priv->preregistered_uids);
261
262         G_OBJECT_CLASS(parent_class)->finalize (obj);
263 }
264
265 ModestWindowMgr*
266 modest_window_mgr_new (void)
267 {
268         return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_WINDOW_MGR, NULL));
269 }
270
271
272
273
274 /* do we have uid? */
275 static gboolean
276 has_uid (GSList *list, const gchar *uid)
277 {
278         GSList *cursor = list;
279
280         if (!uid)
281                 return FALSE;
282         
283         while (cursor) {
284                 if (cursor->data && strcmp (cursor->data, uid) == 0)
285                         return TRUE;
286                 cursor = g_slist_next (cursor);
287         }
288         return FALSE;
289 }
290
291
292 /* remove all from the list have have uid = uid */
293 static GSList*
294 remove_uid (GSList *list, const gchar *uid)
295 {
296         GSList *cursor = list, *start = list;
297         
298         if (!uid)
299                 return list;
300         
301         while (cursor) {
302                 GSList *next = g_slist_next (cursor);
303                 if (cursor->data && strcmp (cursor->data, uid) == 0) {
304                         g_free (cursor->data);
305                         start = g_slist_delete_link (start, cursor);
306                 }
307                 cursor = next;
308         }
309         return start;
310 }
311
312
313 static GSList *
314 append_uid (GSList *list, const gchar *uid)
315 {
316         return g_slist_append (list, g_strdup(uid));
317 }
318
319
320
321 void 
322 modest_window_mgr_register_header (ModestWindowMgr *self,  TnyHeader *header, const gchar *alt_uid)
323 {
324         ModestWindowMgrPrivate *priv;
325         gchar* uid;
326         
327         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
328         g_return_if_fail (TNY_IS_HEADER(header));
329                 
330         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
331         uid = modest_tny_folder_get_header_unique_id (header);
332
333         if (uid == NULL)
334                 uid = g_strdup (alt_uid);
335         
336         if (!has_uid (priv->preregistered_uids, uid)) {
337                 MODEST_DEBUG_BLOCK(g_debug ("registering new uid %s", uid););
338                 priv->preregistered_uids = append_uid (priv->preregistered_uids, uid);
339         } else
340                 MODEST_DEBUG_BLOCK(g_debug ("already had uid %s", uid););
341         
342         g_free (uid);
343 }
344
345 void 
346 modest_window_mgr_unregister_header (ModestWindowMgr *self,  TnyHeader *header)
347 {
348         ModestWindowMgrPrivate *priv;
349         gchar* uid;
350         
351         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
352         g_return_if_fail (TNY_IS_HEADER(header));
353                 
354         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
355         uid = modest_tny_folder_get_header_unique_id (header);
356
357         if (!has_uid (priv->preregistered_uids, uid)) {
358                 MODEST_DEBUG_BLOCK(g_debug ("trying to unregister non-existing uid %s", uid););
359                 priv->preregistered_uids = append_uid (priv->preregistered_uids, uid);
360         } else
361                 MODEST_DEBUG_BLOCK(g_debug ("unregistering uid %s", uid););
362         
363         if (has_uid (priv->preregistered_uids, uid)) {
364                 priv->preregistered_uids = remove_uid (priv->preregistered_uids, uid);
365                 if (has_uid (priv->preregistered_uids, uid))
366                         g_debug ("BUG: uid %s NOT removed", uid);
367                 else
368                         MODEST_DEBUG_BLOCK(g_debug ("uid %s removed", uid););
369         }
370                 
371         g_free (uid);
372 }
373
374
375 #define MODEST_WINDOW_HELP_ID_PARAM "help-id"
376
377 void
378 modest_window_mgr_register_help_id (ModestWindowMgr *self, GtkWindow *win, const gchar* help_id)
379 {
380         /* we don't need 'self', but for API consistency... */
381         g_return_if_fail (self && MODEST_IS_WINDOW_MGR(self));
382
383         g_return_if_fail (win && GTK_IS_WINDOW(win));
384         g_return_if_fail (help_id);
385         
386         g_object_set_data_full (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM,
387                                 g_strdup(help_id), g_free);
388 }
389
390
391 const gchar*
392 modest_window_mgr_get_help_id (ModestWindowMgr *self, GtkWindow *win)
393 {
394         /* we don't need 'self', but for API consistency... */
395         g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR (self), NULL);
396         g_return_val_if_fail (win, NULL);
397
398         return g_object_get_data (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM);
399 }
400
401 gboolean
402 modest_window_mgr_close_all_windows (ModestWindowMgr *self)
403 {
404         return MODEST_WINDOW_MGR_GET_CLASS (self)->close_all_windows (self);
405 }
406
407 static gboolean
408 modest_window_mgr_close_all_windows_default (ModestWindowMgr *self)
409 {
410         return TRUE;
411 }
412
413
414 gboolean
415 modest_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
416                                                   ModestWindow **win)
417 {
418         return MODEST_WINDOW_MGR_GET_CLASS (self)->find_registered_header (self, header, win);
419 }
420
421 static gboolean
422 modest_window_mgr_find_registered_header_default (ModestWindowMgr *self, TnyHeader *header,
423                                                   ModestWindow **win)
424 {
425         ModestWindowMgrPrivate *priv = NULL;
426         gchar* uid = NULL;
427         gboolean has_header = FALSE;
428
429         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
430         g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
431         
432         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
433
434         uid = modest_tny_folder_get_header_unique_id (header);
435         
436         if (win)
437                 *win = NULL;
438
439         has_header = has_uid (priv->preregistered_uids, uid);
440
441         return has_header;
442 }
443
444 GList *
445 modest_window_mgr_get_window_list (ModestWindowMgr *self)
446 {
447         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_window_list (self);
448 }
449
450 static GList *
451 modest_window_mgr_get_window_list_default (ModestWindowMgr *self)
452 {
453         return NULL;
454 }
455
456 gboolean
457 modest_window_mgr_register_window (ModestWindowMgr *self, 
458                                    ModestWindow *window,
459                                    ModestWindow *parent)
460 {
461         return MODEST_WINDOW_MGR_GET_CLASS (self)->register_window (self, window, parent);
462 }
463
464 static gboolean
465 modest_window_mgr_register_window_default (ModestWindowMgr *self, 
466                                            ModestWindow *window,
467                                            ModestWindow *parent)
468 {
469         ModestWindowMgrPrivate *priv;
470
471         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
472         g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
473
474         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
475
476         /* Check that it's not a second main window */
477         if (MODEST_IS_MAIN_WINDOW (window)) {
478                 if (priv->main_window) {
479                         g_warning ("%s: trying to register a second main window",
480                                    __FUNCTION__);
481                         return FALSE;
482                 } else {
483                         priv->main_window = window;
484                         load_new_view (self);
485                         load_new_editor (self);
486                 }
487         }
488
489         /* remove from the list of pre-registered uids */
490         if (MODEST_IS_MSG_VIEW_WINDOW(window)) {
491                 const gchar *uid = modest_msg_view_window_get_message_uid
492                         (MODEST_MSG_VIEW_WINDOW (window));
493
494                 if (!has_uid (priv->preregistered_uids, uid)) 
495                         g_debug ("weird: no uid for window (%s)", uid);
496                 
497                 MODEST_DEBUG_BLOCK(g_debug ("registering window for %s", uid ? uid : "<none>"););
498                 
499                 priv->preregistered_uids = 
500                         remove_uid (priv->preregistered_uids,
501                                     modest_msg_view_window_get_message_uid
502                                     (MODEST_MSG_VIEW_WINDOW (window)));
503         } else if (MODEST_IS_MSG_EDIT_WINDOW(window)) {
504                 const gchar *uid = modest_msg_edit_window_get_message_uid
505                         (MODEST_MSG_EDIT_WINDOW (window));
506                 
507                 MODEST_DEBUG_BLOCK(g_debug ("registering window for %s", uid););
508
509                 priv->preregistered_uids = 
510                         remove_uid (priv->preregistered_uids,
511                                     modest_msg_edit_window_get_message_uid
512                                     (MODEST_MSG_EDIT_WINDOW (window)));
513         }
514
515         return TRUE;
516 }
517
518 void 
519 modest_window_mgr_unregister_window (ModestWindowMgr *self, 
520                                      ModestWindow *window)
521 {
522         MODEST_WINDOW_MGR_GET_CLASS (self)->unregister_window (self, window);
523 }
524
525 static void 
526 modest_window_mgr_unregister_window_default (ModestWindowMgr *self, 
527                                              ModestWindow *window)
528 {
529         ModestWindowMgrPrivate *priv;
530
531         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
532         g_return_if_fail (MODEST_IS_WINDOW (window));
533
534         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
535
536         /* Save state */
537         modest_window_save_state (window);
538
539         /* Disconnect all the window signals */
540         modest_window_disconnect_signals (window);
541         
542         /* Destroy the window */
543         gtk_widget_destroy (GTK_WIDGET (window));
544 }
545
546
547
548 void
549 modest_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
550                                        gboolean on)
551 {
552         MODEST_WINDOW_MGR_GET_CLASS (self)->set_fullscreen_mode (self, on);
553 }
554
555 static void
556 modest_window_mgr_set_fullscreen_mode_default (ModestWindowMgr *self,
557                                                gboolean on)
558 {
559         return;
560 }
561
562 gboolean
563 modest_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
564 {
565         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_fullscreen_mode (self);
566 }
567
568 static gboolean
569 modest_window_mgr_get_fullscreen_mode_default (ModestWindowMgr *self)
570 {
571         return FALSE;
572 }
573
574 void 
575 modest_window_mgr_show_toolbars (ModestWindowMgr *self,
576                                  GType window_type,
577                                  gboolean show_toolbars,
578                                  gboolean fullscreen)
579 {
580         return MODEST_WINDOW_MGR_GET_CLASS (self)->show_toolbars (self, window_type, show_toolbars, fullscreen);
581 }
582
583 static void 
584 modest_window_mgr_show_toolbars_default (ModestWindowMgr *self,
585                                          GType window_type,
586                                          gboolean show_toolbars,
587                                          gboolean fullscreen)
588 {
589         return;
590 }
591
592 void
593 modest_window_mgr_set_main_window (ModestWindowMgr *self, ModestWindow *win)
594 {
595         ModestWindowMgrPrivate *priv;
596         
597         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
598
599         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
600         priv->main_window = win;
601 }
602
603 ModestWindow*  
604 modest_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show)
605 {
606         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_main_window (self, show);
607 }
608
609 static ModestWindow*  
610 modest_window_mgr_get_main_window_default (ModestWindowMgr *self, gboolean show)
611 {
612         ModestWindowMgrPrivate *priv;
613         
614         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL);
615
616         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
617         if (priv->main_window)
618                 return priv->main_window;
619
620         if (show) 
621                 return modest_main_window_new ();
622         else return NULL;
623 }
624
625
626 gboolean
627 modest_window_mgr_main_window_exists  (ModestWindowMgr *self)
628 {
629         ModestWindowMgrPrivate *priv;
630         
631         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
632         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
633
634         return priv->main_window != NULL;
635 }
636
637
638 GtkWindow *
639 modest_window_mgr_get_modal (ModestWindowMgr *self)
640 {
641         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_modal (self);
642 }
643
644 static GtkWindow *
645 modest_window_mgr_get_modal_default (ModestWindowMgr *self)
646 {
647         return NULL;
648 }
649
650
651 void
652 modest_window_mgr_set_modal (ModestWindowMgr *self, 
653                              GtkWindow *window,
654                              GtkWindow *parent)
655 {
656         MODEST_WINDOW_MGR_GET_CLASS (self)->set_modal (self, window, parent);
657 }
658
659 static void
660 modest_window_mgr_set_modal_default (ModestWindowMgr *self, 
661                                      GtkWindow *window,
662                                      GtkWindow *parent)
663 {
664         return;
665 }
666
667
668 static void
669 on_nonhibernating_window_hide(GtkWidget *widget, gpointer user_data)
670 {
671         ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
672         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
673         
674         /* Forget this window,
675          * so hibernation will be allowed again if no windows are remembered: */
676         priv->windows_that_prevent_hibernation =
677                 g_slist_remove (priv->windows_that_prevent_hibernation, GTK_WINDOW(widget));
678 }
679
680 static void
681 on_nonhibernating_window_show(GtkWidget *widget, gpointer user_data)
682 {
683         ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
684         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
685         
686         GtkWindow *window = GTK_WINDOW (widget);
687         
688         priv->windows_that_prevent_hibernation = 
689                         g_slist_append (priv->windows_that_prevent_hibernation, window);
690         
691         /* Allow hibernation again when the window has been hidden: */
692         g_signal_connect (window, "hide", 
693                 G_CALLBACK (on_nonhibernating_window_hide), self);
694 }
695
696 void
697 modest_window_mgr_prevent_hibernation_while_window_is_shown (ModestWindowMgr *self,
698                                                                   GtkWindow *window)
699 {
700         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
701         
702         if (GTK_WIDGET_VISIBLE(window)) {
703                 on_nonhibernating_window_show (GTK_WIDGET (window), self);
704         } else {
705                 /* Wait for it to be shown: */
706                 g_signal_connect (window, "show", 
707                         G_CALLBACK (on_nonhibernating_window_show), self);      
708         }
709 }
710
711 gboolean
712 modest_window_mgr_get_hibernation_is_prevented (ModestWindowMgr *self)
713 {
714         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
715         
716         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
717         
718         /* Prevent hibernation if any open windows are currently 
719          * preventing hibernation: */
720         return (g_slist_length (priv->windows_that_prevent_hibernation) > 0);
721 }
722
723
724 void
725 modest_window_mgr_save_state_for_all_windows (ModestWindowMgr *self)
726 {
727         GList *window_list;
728         GList *node;
729         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
730         
731         /* Iterate over all windows */
732         window_list = modest_window_mgr_get_window_list (self);
733         node = window_list;
734         while (node) {
735                 ModestWindow *window = MODEST_WINDOW (node->data);
736                 if (window) {
737                         /* This calls the vfunc, 
738                          * so each window can do its own thing: */
739                         modest_window_save_state (window);
740                 }
741
742                 node = g_list_next (node);
743         }
744         g_list_free (window_list);
745 }
746
747 guint
748 modest_window_mgr_get_num_windows (ModestWindowMgr *self)
749 {
750         ModestWindowMgrPrivate *priv;
751         gint num_windows = 0;
752         GList *window_list;
753
754         g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), -1);
755
756         priv =  MODEST_WINDOW_MGR_GET_PRIVATE(self);
757
758         window_list = modest_window_mgr_get_window_list (self);
759
760         if (window_list) {
761                 num_windows = g_list_length (window_list);
762                 g_list_free (window_list);
763         }
764
765         /* Do not take into account the main window if it was hidden */
766         if (num_windows && priv->main_window && !GTK_WIDGET_VISIBLE (priv->main_window))
767                 num_windows--;
768
769         return num_windows + priv->banner_counter;
770 }
771
772 GtkWidget *   
773 modest_window_mgr_get_msg_edit_window (ModestWindowMgr *self)
774 {
775         GtkWidget *result;
776         ModestWindowMgrPrivate *priv;
777
778         g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL);
779
780         priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
781                 
782         if (priv->cached_editor) {
783                 result = priv->cached_editor;
784                 priv->cached_editor = NULL;
785                 load_new_editor (self);
786         } else {
787                 result = g_object_new (MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
788         }
789
790         return result;
791 }
792
793 GtkWidget *   
794 modest_window_mgr_get_msg_view_window (ModestWindowMgr *self)
795 {
796         GtkWidget *result;
797         ModestWindowMgrPrivate *priv;
798
799         g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL);
800         
801         priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
802
803         if (priv->cached_view) {
804                 result = priv->cached_view;
805                 priv->cached_view = NULL;
806                 load_new_view (self);
807         } else {
808                 result = g_object_new (MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
809         }
810
811         return result;
812 }
813
814 void
815 modest_window_mgr_register_banner (ModestWindowMgr *self)
816 {
817         ModestWindowMgrPrivate *priv;
818
819         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
820         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
821
822         priv->banner_counter++;
823 }
824
825 void
826 modest_window_mgr_unregister_banner (ModestWindowMgr *self)
827 {
828         ModestWindowMgrPrivate *priv;
829
830         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
831         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
832
833         priv->banner_counter--;
834         if (modest_window_mgr_get_num_windows (self) == 0)
835                 g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0);
836 }
837
838 ModestWindow *
839 modest_window_mgr_show_initial_window (ModestWindowMgr *self)
840 {
841         ModestWindow *window = NULL;
842
843         /* Call the children */
844         window = MODEST_WINDOW_MGR_GET_CLASS (self)->show_initial_window (self);
845
846         if (window) {
847                 ModestAccountMgr *mgr;
848
849                 /* Show the initial window */
850                 gtk_widget_show (GTK_WIDGET (window));
851
852                 /* If there are no accounts then show the account wizard */
853                 mgr = modest_runtime_get_account_mgr();
854                 if (!modest_account_mgr_has_accounts (mgr, TRUE))
855                         modest_ui_actions_run_account_setup_wizard (window);
856         }
857
858         return window;
859 }
860
861 static ModestWindow *
862 modest_window_mgr_show_initial_window_default (ModestWindowMgr *self)
863 {
864         /* By default it returns the main window creating it if
865            needed */
866         return modest_window_mgr_get_main_window (self, TRUE);
867 }
868
869
870 ModestWindow *
871 modest_window_mgr_get_current_top (ModestWindowMgr *self) 
872 {
873         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_current_top (self);
874 }
875
876
877 static ModestWindow *
878 modest_window_mgr_get_current_top_default (ModestWindowMgr *self)
879 {
880         g_return_val_if_reached (NULL);
881 }
882
883 gboolean
884 modest_window_mgr_screen_is_on (ModestWindowMgr *self)
885 {
886         return MODEST_WINDOW_MGR_GET_CLASS (self)->screen_is_on (self);
887 }
888
889 static gboolean
890 modest_window_mgr_screen_is_on_default (ModestWindowMgr *self)
891 {
892         /* Default implementation is assuming screen is always on */
893
894         return TRUE;
895 }