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