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