Remove not used size_limit item in settings dialog
[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 "modest-defs.h"
37 #include "widgets/modest-main-window.h"
38 #include "widgets/modest-msg-edit-window.h"
39 #include "widgets/modest-msg-view-window.h"
40 #include "modest-debug.h"
41 #include <tny-simple-list.h>
42
43
44 /* 'private'/'protected' functions */
45 static void modest_window_mgr_class_init (ModestWindowMgrClass *klass);
46 static void modest_window_mgr_init       (ModestWindowMgr *obj);
47 static void modest_window_mgr_finalize   (GObject *obj);
48
49 static gboolean modest_window_mgr_register_window_default (ModestWindowMgr *self, 
50                                                            ModestWindow *window,
51                                                            ModestWindow *parent);
52 static void modest_window_mgr_unregister_window_default (ModestWindowMgr *self, 
53                                                          ModestWindow *window);
54 static void modest_window_mgr_set_fullscreen_mode_default (ModestWindowMgr *self,
55                                                            gboolean on);
56 static gboolean modest_window_mgr_get_fullscreen_mode_default (ModestWindowMgr *self);
57 static void modest_window_mgr_show_toolbars_default (ModestWindowMgr *self,
58                                                      GType window_type,
59                                                      gboolean show_toolbars,
60                                                      gboolean fullscreen);
61 #ifndef MODEST_TOOLKIT_HILDON2
62 static ModestWindow* modest_window_mgr_get_main_window_default (ModestWindowMgr *self, gboolean show);
63 #endif
64 static GtkWindow *modest_window_mgr_get_modal_default (ModestWindowMgr *self);
65 static void modest_window_mgr_set_modal_default (ModestWindowMgr *self, 
66                                                  GtkWindow *window,
67                                                  GtkWindow *parent);
68 static gboolean modest_window_mgr_close_all_windows_default (ModestWindowMgr *self);
69 static gboolean modest_window_mgr_find_registered_header_default (ModestWindowMgr *self, 
70                                                                   TnyHeader *header,
71                                                                   ModestWindow **win);
72 static gboolean modest_window_mgr_find_registered_message_uid_default (ModestWindowMgr *self, 
73                                                                        const gchar *msg_uid,
74                                                                        ModestWindow **win);
75 static GList *modest_window_mgr_get_window_list_default (ModestWindowMgr *self);
76 static ModestWindow *modest_window_mgr_show_initial_window_default (ModestWindowMgr *self);
77 static ModestWindow *modest_window_mgr_get_current_top_default (ModestWindowMgr *self);
78 static gboolean modest_window_mgr_screen_is_on_default (ModestWindowMgr *self);
79 static ModestWindow *modest_window_mgr_get_folder_window_default (ModestWindowMgr *self);
80 static void modest_window_mgr_create_caches_default (ModestWindowMgr *self);
81 static void modest_window_mgr_on_queue_changed (ModestMailOperationQueue *queue,
82                                                 ModestMailOperation *mail_op,
83                                                 ModestMailOperationQueueNotification type,
84                                                 ModestWindowMgr *self);
85 static void on_mail_operation_started (ModestMailOperation *mail_op,
86                                        gpointer user_data);
87 static void on_mail_operation_finished (ModestMailOperation *mail_op,
88                                         gpointer user_data);
89 static gboolean modest_window_mgr_close_all_but_initial_default (ModestWindowMgr *self);
90
91 /* list my signals  */
92 enum {
93         WINDOW_LIST_EMPTY_SIGNAL,
94         PROGRESS_LIST_CHANGED_SIGNAL,
95         NUM_SIGNALS
96 };
97
98 typedef struct _ModestWindowMgrPrivate ModestWindowMgrPrivate;
99 struct _ModestWindowMgrPrivate {
100         guint         banner_counter;
101
102 #ifndef MODEST_TOOLKIT_HILDON2
103         ModestWindow *main_window;
104 #endif
105         GSList       *windows_that_prevent_hibernation;
106         GSList       *preregistered_uids;
107
108         guint        closing_time;
109
110         GtkWidget    *cached_view;
111         GtkWidget    *cached_editor;
112         guint        idle_load_view_id;
113         guint        idle_load_editor_id;
114
115         guint        queue_change_handler;
116         TnyList      *progress_operations;
117         GSList       *sighandlers;
118 };
119
120 #define MODEST_WINDOW_MGR_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
121                                                MODEST_TYPE_WINDOW_MGR, \
122                                                ModestWindowMgrPrivate))
123 /* globals */
124 static GObjectClass *parent_class = NULL;
125
126 /* uncomment the following if you have defined any signals */
127 static guint signals[NUM_SIGNALS] = {0};
128
129 GType
130 modest_window_mgr_get_type (void)
131 {
132         static GType my_type = 0;
133         if (!my_type) {
134                 static const GTypeInfo my_info = {
135                         sizeof(ModestWindowMgrClass),
136                         NULL,           /* base init */
137                         NULL,           /* base finalize */
138                         (GClassInitFunc) modest_window_mgr_class_init,
139                         NULL,           /* class finalize */
140                         NULL,           /* class data */
141                         sizeof(ModestWindowMgr),
142                         1,              /* n_preallocs */
143                         (GInstanceInitFunc) modest_window_mgr_init,
144                         NULL
145                 };
146                 my_type = g_type_register_static (G_TYPE_OBJECT,
147                                                   "ModestWindowMgr",
148                                                   &my_info, 0);
149         }
150         return my_type;
151 }
152
153 static void
154 modest_window_mgr_class_init (ModestWindowMgrClass *klass)
155 {
156         GObjectClass *gobject_class;
157         ModestWindowMgrClass *mgr_class;
158
159         gobject_class = (GObjectClass*) klass;
160         mgr_class = (ModestWindowMgrClass *) klass;
161
162         parent_class            = g_type_class_peek_parent (klass);
163         gobject_class->finalize = modest_window_mgr_finalize;
164         mgr_class->register_window = modest_window_mgr_register_window_default;
165         mgr_class->unregister_window = modest_window_mgr_unregister_window_default;
166         mgr_class->set_fullscreen_mode = modest_window_mgr_set_fullscreen_mode_default;
167         mgr_class->get_fullscreen_mode = modest_window_mgr_get_fullscreen_mode_default;
168         mgr_class->show_toolbars = modest_window_mgr_show_toolbars_default;
169 #ifndef MODEST_TOOLKIT_HILDON2
170         mgr_class->get_main_window = modest_window_mgr_get_main_window_default;
171 #endif
172         mgr_class->get_modal = modest_window_mgr_get_modal_default;
173         mgr_class->set_modal = modest_window_mgr_set_modal_default;
174         mgr_class->close_all_windows = modest_window_mgr_close_all_windows_default;
175         mgr_class->find_registered_header = modest_window_mgr_find_registered_header_default;
176         mgr_class->find_registered_message_uid = modest_window_mgr_find_registered_message_uid_default;
177         mgr_class->get_window_list = modest_window_mgr_get_window_list_default;
178         mgr_class->show_initial_window = modest_window_mgr_show_initial_window_default;
179         mgr_class->get_current_top = modest_window_mgr_get_current_top_default;
180         mgr_class->screen_is_on = modest_window_mgr_screen_is_on_default;
181         mgr_class->create_caches = modest_window_mgr_create_caches_default;
182         mgr_class->close_all_but_initial = modest_window_mgr_close_all_but_initial_default;
183         mgr_class->get_folder_window = modest_window_mgr_get_folder_window_default;
184
185         g_type_class_add_private (gobject_class, sizeof(ModestWindowMgrPrivate));
186
187
188         /**
189          * ModestWindowMgr::window-list-empty
190          * @self: the #ModestWindowMgr that emits the signal
191          * @user_data: user data set when the signal handler was connected
192          *
193          * Issued whenever the window list becomes empty
194          */
195         signals[WINDOW_LIST_EMPTY_SIGNAL] =
196                 g_signal_new ("window-list-empty",
197                               G_TYPE_FROM_CLASS (gobject_class),
198                               G_SIGNAL_RUN_FIRST,
199                               G_STRUCT_OFFSET (ModestWindowMgrClass, window_list_empty),
200                               NULL, NULL,
201                               g_cclosure_marshal_VOID__VOID,
202                               G_TYPE_NONE, 0);
203
204         /**
205          * ModestWindowMgr::progress-list-changed
206          * @self: the #ModestWindowMgr that emits the signal
207          * @user_data: user data set when the signal handler was connected
208          *
209          * Issued whenever the progress mail operations list becomes changed
210          */
211         signals[PROGRESS_LIST_CHANGED_SIGNAL] =
212                 g_signal_new ("progress-list-changed",
213                               G_TYPE_FROM_CLASS (gobject_class),
214                               G_SIGNAL_RUN_FIRST,
215                               G_STRUCT_OFFSET (ModestWindowMgrClass, progress_list_changed),
216                               NULL, NULL,
217                               g_cclosure_marshal_VOID__VOID,
218                               G_TYPE_NONE, 0);
219 }
220
221 static gboolean
222 idle_load_view (ModestWindowMgr *mgr)
223 {
224         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (mgr);
225         
226         priv->cached_view = g_object_new (MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
227         priv->idle_load_view_id = 0;
228         return FALSE;
229 }
230
231 static gboolean
232 idle_load_editor (ModestWindowMgr *mgr)
233 {
234         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (mgr);
235         
236         priv->cached_editor = g_object_new (MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
237         priv->idle_load_editor_id = 0;
238         return FALSE;
239 }
240
241 static void
242 load_new_view (ModestWindowMgr *self)
243 {
244         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
245         if ((priv->cached_view == NULL) && (priv->idle_load_view_id == 0))
246                 priv->idle_load_view_id = g_timeout_add (2500, (GSourceFunc) idle_load_view, self);
247 }
248
249 static void
250 load_new_editor (ModestWindowMgr *self)
251 {
252         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
253         if ((priv->cached_editor == NULL) && (priv->idle_load_editor_id == 0))
254                 priv->idle_load_editor_id = g_timeout_add (5000, (GSourceFunc) idle_load_editor, self);
255 }
256
257 static void
258 modest_window_mgr_init (ModestWindowMgr *obj)
259 {
260         ModestWindowMgrPrivate *priv;
261
262         priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
263         priv->banner_counter = 0;
264 #ifndef MODEST_TOOLKIT_HILDON2
265         priv->main_window = NULL;
266 #endif
267         priv->preregistered_uids = NULL;
268
269         priv->closing_time = 0;
270
271         priv->cached_view = NULL;
272         priv->cached_editor = NULL;
273
274         priv->windows_that_prevent_hibernation = NULL;
275
276         priv->queue_change_handler = 0;
277         priv->progress_operations = TNY_LIST (tny_simple_list_new ());
278 }
279
280 static void
281 modest_window_mgr_finalize (GObject *obj)
282 {
283         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
284
285         if (priv->idle_load_view_id > 0) {
286                 g_source_remove (priv->idle_load_view_id);
287                 priv->idle_load_view_id = 0;
288         }
289         
290         if (priv->idle_load_editor_id > 0) {
291                 g_source_remove (priv->idle_load_editor_id);
292                 priv->idle_load_editor_id = 0;
293         }
294         
295         if (priv->cached_view) {
296                 gtk_widget_destroy (priv->cached_view);
297                 priv->cached_view = NULL;
298         }
299         if (priv->cached_editor) {
300                 gtk_widget_destroy (priv->cached_editor);
301                 priv->cached_editor = NULL;
302         }
303
304         if (priv->windows_that_prevent_hibernation) {
305                 g_slist_free (priv->windows_that_prevent_hibernation);
306                 priv->cached_editor = NULL;
307         }
308
309         modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
310         priv->sighandlers = NULL;
311
312         if (priv->queue_change_handler > 0) {
313                 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
314                                              priv->queue_change_handler);
315                 priv->queue_change_handler = 0;
316         }
317
318         if (priv->progress_operations) {
319                 g_object_unref (priv->progress_operations);
320                 priv->progress_operations = NULL;
321         }
322
323         g_slist_foreach (priv->preregistered_uids, (GFunc)g_free, NULL);
324         g_slist_free (priv->preregistered_uids);
325
326         G_OBJECT_CLASS(parent_class)->finalize (obj);
327 }
328
329 ModestWindowMgr*
330 modest_window_mgr_new (void)
331 {
332         return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_WINDOW_MGR, NULL));
333 }
334
335
336
337
338 /* do we have uid? */
339 static gboolean
340 has_uid (GSList *list, const gchar *uid)
341 {
342         GSList *cursor = list;
343
344         if (!uid)
345                 return FALSE;
346         
347         while (cursor) {
348                 if (cursor->data && strcmp (cursor->data, uid) == 0)
349                         return TRUE;
350                 cursor = g_slist_next (cursor);
351         }
352         return FALSE;
353 }
354
355
356 /* remove all from the list have have uid = uid */
357 static GSList*
358 remove_uid (GSList *list, const gchar *uid)
359 {
360         GSList *cursor = list, *start = list;
361         
362         if (!uid)
363                 return list;
364         
365         while (cursor) {
366                 GSList *next = g_slist_next (cursor);
367                 if (cursor->data && strcmp (cursor->data, uid) == 0) {
368                         g_free (cursor->data);
369                         start = g_slist_delete_link (start, cursor);
370                 }
371                 cursor = next;
372         }
373         return start;
374 }
375
376
377 static GSList *
378 append_uid (GSList *list, const gchar *uid)
379 {
380         return g_slist_append (list, g_strdup(uid));
381 }
382
383
384
385 void 
386 modest_window_mgr_register_header (ModestWindowMgr *self,  TnyHeader *header, const gchar *alt_uid)
387 {
388         ModestWindowMgrPrivate *priv;
389         gchar* uid;
390         
391         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
392         g_return_if_fail (TNY_IS_HEADER(header));
393                 
394         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
395         if (alt_uid != NULL) {
396                 uid = g_strdup (alt_uid);
397         } else {
398                 uid = modest_tny_folder_get_header_unique_id (header);
399         }
400
401         if (!has_uid (priv->preregistered_uids, uid)) {
402                 MODEST_DEBUG_BLOCK(g_debug ("registering new uid %s", uid););
403                 priv->preregistered_uids = append_uid (priv->preregistered_uids, uid);
404         } else
405                 MODEST_DEBUG_BLOCK(g_debug ("already had uid %s", uid););
406         
407         g_free (uid);
408 }
409
410 void 
411 modest_window_mgr_unregister_header (ModestWindowMgr *self,  TnyHeader *header)
412 {
413         ModestWindowMgrPrivate *priv;
414         gchar* uid;
415         
416         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
417         g_return_if_fail (TNY_IS_HEADER(header));
418                 
419         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
420         uid = modest_tny_folder_get_header_unique_id (header);
421
422         if (!has_uid (priv->preregistered_uids, uid)) {
423                 MODEST_DEBUG_BLOCK(g_debug ("trying to unregister non-existing uid %s", uid););
424                 priv->preregistered_uids = append_uid (priv->preregistered_uids, uid);
425         } else
426                 MODEST_DEBUG_BLOCK(g_debug ("unregistering uid %s", uid););
427         
428         if (has_uid (priv->preregistered_uids, uid)) {
429                 priv->preregistered_uids = remove_uid (priv->preregistered_uids, uid);
430                 if (has_uid (priv->preregistered_uids, uid))
431                         g_debug ("BUG: uid %s NOT removed", uid);
432                 else
433                         MODEST_DEBUG_BLOCK(g_debug ("uid %s removed", uid););
434         }
435                 
436         g_free (uid);
437 }
438
439
440 #define MODEST_WINDOW_HELP_ID_PARAM "help-id"
441
442 void
443 modest_window_mgr_register_help_id (ModestWindowMgr *self, GtkWindow *win, const gchar* help_id)
444 {
445         /* we don't need 'self', but for API consistency... */
446         g_return_if_fail (self && MODEST_IS_WINDOW_MGR(self));
447
448         g_return_if_fail (help_id);
449
450         if (GTK_IS_WINDOW (win)) {
451                 g_object_set_data_full (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM,
452                                         g_strdup(help_id), g_free);
453         }
454 }
455
456
457 const gchar*
458 modest_window_mgr_get_help_id (ModestWindowMgr *self, GtkWindow *win)
459 {
460         /* we don't need 'self', but for API consistency... */
461         g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR (self), NULL);
462         g_return_val_if_fail (win, NULL);
463
464         return g_object_get_data (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM);
465 }
466
467 gboolean
468 modest_window_mgr_close_all_windows (ModestWindowMgr *self)
469 {
470         return MODEST_WINDOW_MGR_GET_CLASS (self)->close_all_windows (self);
471 }
472
473 static gboolean
474 modest_window_mgr_close_all_windows_default (ModestWindowMgr *self)
475 {
476         return TRUE;
477 }
478
479
480 gboolean
481 modest_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
482                                                   ModestWindow **win)
483 {
484         return MODEST_WINDOW_MGR_GET_CLASS (self)->find_registered_header (self, header, win);
485 }
486
487 static gboolean
488 modest_window_mgr_find_registered_header_default (ModestWindowMgr *self, TnyHeader *header,
489                                                   ModestWindow **win)
490 {
491         gchar* uid = NULL;
492
493         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
494         g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
495
496         uid = modest_tny_folder_get_header_unique_id (header);
497
498         if (uid)
499                 return modest_window_mgr_find_registered_message_uid (self, uid, win);
500         else
501                 return FALSE;
502 }
503
504 gboolean
505 modest_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
506                                                ModestWindow **win)
507 {
508         return MODEST_WINDOW_MGR_GET_CLASS (self)->find_registered_message_uid (self, msg_uid, win);
509 }
510
511 static gboolean
512 modest_window_mgr_find_registered_message_uid_default (ModestWindowMgr *self, const gchar *msg_uid,
513                                                        ModestWindow **win)
514 {
515         ModestWindowMgrPrivate *priv = NULL;
516         gchar* uid = NULL;
517         gboolean has_header = FALSE;
518
519         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
520         g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
521
522         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
523
524         if (win)
525                 *win = NULL;
526
527         has_header = has_uid (priv->preregistered_uids, msg_uid);
528         g_free (uid);
529
530         return has_header;
531 }
532
533 GList *
534 modest_window_mgr_get_window_list (ModestWindowMgr *self)
535 {
536         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_window_list (self);
537 }
538
539 static GList *
540 modest_window_mgr_get_window_list_default (ModestWindowMgr *self)
541 {
542         return NULL;
543 }
544
545 gboolean
546 modest_window_mgr_register_window (ModestWindowMgr *self, 
547                                    ModestWindow *window,
548                                    ModestWindow *parent)
549 {
550         gboolean no_windows, retval;
551
552         no_windows = (modest_window_mgr_get_num_windows (self) == 0);
553
554         retval = MODEST_WINDOW_MGR_GET_CLASS (self)->register_window (self, window, parent);
555
556         if  (no_windows) {
557                 /* If this is the first registered window then reset the
558                    status of the TnyDevice as it might be forced to be offline
559                    when modest is running in the background (see
560                    modest_tny_account_store_new()) */
561                 if (tny_device_is_forced (modest_runtime_get_device ()))
562                         tny_device_reset (modest_runtime_get_device ());
563
564                 /* Do also allow modest to shutdown when the
565                    application is closed */
566                 modest_runtime_set_allow_shutdown (TRUE);
567         }
568         return retval;
569 }
570
571 static gboolean
572 modest_window_mgr_register_window_default (ModestWindowMgr *self, 
573                                            ModestWindow *window,
574                                            ModestWindow *parent)
575 {
576         ModestWindowMgrPrivate *priv;
577
578         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
579         g_return_val_if_fail (MODEST_IS_WINDOW (window), FALSE);
580
581         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
582
583         /* We set up the queue change handler */
584         if (priv->queue_change_handler == 0) {
585                 priv->queue_change_handler = g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
586                                                                "queue-changed",
587                                                                G_CALLBACK (modest_window_mgr_on_queue_changed),
588                                                                self);
589         }
590
591
592         /* remove from the list of pre-registered uids */
593         if (MODEST_IS_MSG_VIEW_WINDOW(window)) {
594                 const gchar *uid = modest_msg_view_window_get_message_uid
595                         (MODEST_MSG_VIEW_WINDOW (window));
596
597                 MODEST_DEBUG_BLOCK(g_debug ("registering window for %s", uid ? uid : "<none>"););
598
599                 if (has_uid (priv->preregistered_uids, uid)) {
600                         priv->preregistered_uids = 
601                                 remove_uid (priv->preregistered_uids,
602                                             modest_msg_view_window_get_message_uid
603                                             (MODEST_MSG_VIEW_WINDOW (window)));
604                 }
605         } else if (MODEST_IS_MSG_EDIT_WINDOW(window)) {
606                 const gchar *uid = modest_msg_edit_window_get_message_uid
607                         (MODEST_MSG_EDIT_WINDOW (window));
608
609                 MODEST_DEBUG_BLOCK(g_debug ("registering window for %s", uid););
610
611                 priv->preregistered_uids = 
612                         remove_uid (priv->preregistered_uids,
613                                     modest_msg_edit_window_get_message_uid
614                                     (MODEST_MSG_EDIT_WINDOW (window)));
615         }
616
617         return TRUE;
618 }
619
620 void 
621 modest_window_mgr_unregister_window (ModestWindowMgr *self, 
622                                      ModestWindow *window)
623 {
624         MODEST_WINDOW_MGR_GET_CLASS (self)->unregister_window (self, window);
625 }
626
627 static void 
628 modest_window_mgr_unregister_window_default (ModestWindowMgr *self, 
629                                              ModestWindow *window)
630 {
631         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
632         g_return_if_fail (MODEST_IS_WINDOW (window));
633
634         /* Save state */
635         modest_window_save_state (window);
636
637         /* Disconnect all the window signals */
638         modest_window_disconnect_signals (window);
639         
640         /* Destroy the window */
641         gtk_widget_destroy (GTK_WIDGET (window));
642 }
643
644
645
646 void
647 modest_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
648                                        gboolean on)
649 {
650         MODEST_WINDOW_MGR_GET_CLASS (self)->set_fullscreen_mode (self, on);
651 }
652
653 static void
654 modest_window_mgr_set_fullscreen_mode_default (ModestWindowMgr *self,
655                                                gboolean on)
656 {
657         return;
658 }
659
660 gboolean
661 modest_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
662 {
663         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_fullscreen_mode (self);
664 }
665
666 static gboolean
667 modest_window_mgr_get_fullscreen_mode_default (ModestWindowMgr *self)
668 {
669         return FALSE;
670 }
671
672 void
673 modest_window_mgr_show_toolbars (ModestWindowMgr *self,
674                                  GType window_type,
675                                  gboolean show_toolbars,
676                                  gboolean fullscreen)
677 {
678         return MODEST_WINDOW_MGR_GET_CLASS (self)->show_toolbars (self, window_type, show_toolbars, fullscreen);
679 }
680
681 static void
682 modest_window_mgr_show_toolbars_default (ModestWindowMgr *self,
683                                          GType window_type,
684                                          gboolean show_toolbars,
685                                          gboolean fullscreen)
686 {
687         return;
688 }
689
690 #ifndef MODEST_TOOLKIT_HILDON2
691 void
692 modest_window_mgr_set_main_window (ModestWindowMgr *self, ModestWindow *win)
693 {
694         ModestWindowMgrPrivate *priv;
695
696         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
697
698         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
699         priv->main_window = win;
700 }
701
702 ModestWindow*
703 modest_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show)
704 {
705         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_main_window (self, show);
706 }
707
708 static ModestWindow*
709 modest_window_mgr_get_main_window_default (ModestWindowMgr *self, gboolean show)
710 {
711         return NULL;
712 }
713
714
715 gboolean
716 modest_window_mgr_main_window_exists  (ModestWindowMgr *self)
717 {
718         ModestWindowMgrPrivate *priv;
719
720         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
721         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
722
723         return priv->main_window != NULL;
724 }
725 #endif
726
727 GtkWindow *
728 modest_window_mgr_get_modal (ModestWindowMgr *self)
729 {
730         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_modal (self);
731 }
732
733 static GtkWindow *
734 modest_window_mgr_get_modal_default (ModestWindowMgr *self)
735 {
736         return NULL;
737 }
738
739
740 void
741 modest_window_mgr_set_modal (ModestWindowMgr *self, 
742                              GtkWindow *window,
743                              GtkWindow *parent)
744 {
745         MODEST_WINDOW_MGR_GET_CLASS (self)->set_modal (self, window, parent);
746 }
747
748 static void
749 modest_window_mgr_set_modal_default (ModestWindowMgr *self, 
750                                      GtkWindow *window,
751                                      GtkWindow *parent)
752 {
753         return;
754 }
755
756
757 static void
758 on_nonhibernating_window_hide(GtkWidget *widget, gpointer user_data)
759 {
760         ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
761         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
762         
763         /* Forget this window,
764          * so hibernation will be allowed again if no windows are remembered: */
765         priv->windows_that_prevent_hibernation =
766                 g_slist_remove (priv->windows_that_prevent_hibernation, GTK_WINDOW(widget));
767 }
768
769 static void
770 on_nonhibernating_window_show(GtkWidget *widget, gpointer user_data)
771 {
772         ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
773         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
774         
775         GtkWindow *window = GTK_WINDOW (widget);
776         
777         priv->windows_that_prevent_hibernation = 
778                         g_slist_append (priv->windows_that_prevent_hibernation, window);
779         
780         /* Allow hibernation again when the window has been hidden: */
781         g_signal_connect (window, "hide", 
782                 G_CALLBACK (on_nonhibernating_window_hide), self);
783 }
784
785 void
786 modest_window_mgr_prevent_hibernation_while_window_is_shown (ModestWindowMgr *self,
787                                                                   GtkWindow *window)
788 {
789         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
790         
791         if (GTK_WIDGET_VISIBLE(window)) {
792                 on_nonhibernating_window_show (GTK_WIDGET (window), self);
793         } else {
794                 /* Wait for it to be shown: */
795                 g_signal_connect (window, "show", 
796                         G_CALLBACK (on_nonhibernating_window_show), self);      
797         }
798 }
799
800 gboolean
801 modest_window_mgr_get_hibernation_is_prevented (ModestWindowMgr *self)
802 {
803         g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
804         
805         ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
806         
807         /* Prevent hibernation if any open windows are currently 
808          * preventing hibernation: */
809         return (g_slist_length (priv->windows_that_prevent_hibernation) > 0);
810 }
811
812
813 void
814 modest_window_mgr_save_state_for_all_windows (ModestWindowMgr *self)
815 {
816         GList *window_list;
817         GList *node;
818         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
819         
820         /* Iterate over all windows */
821         window_list = modest_window_mgr_get_window_list (self);
822         node = window_list;
823         while (node) {
824                 ModestWindow *window = MODEST_WINDOW (node->data);
825                 if (window) {
826                         /* This calls the vfunc, 
827                          * so each window can do its own thing: */
828                         modest_window_save_state (window);
829                 }
830
831                 node = g_list_next (node);
832         }
833         g_list_free (window_list);
834 }
835
836 guint
837 modest_window_mgr_get_num_windows (ModestWindowMgr *self)
838 {
839         ModestWindowMgrPrivate *priv;
840         gint num_windows = 0;
841         GList *window_list;
842
843         g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), -1);
844
845         priv =  MODEST_WINDOW_MGR_GET_PRIVATE(self);
846
847         window_list = modest_window_mgr_get_window_list (self);
848
849         if (window_list) {
850                 num_windows = g_list_length (window_list);
851                 g_list_free (window_list);
852         }
853
854 #ifndef MODEST_TOOLKIT_HILDON2
855         /* Do not take into account the main window if it was hidden */
856         if (num_windows && priv->main_window && !GTK_WIDGET_VISIBLE (priv->main_window))
857                 num_windows--;
858 #endif
859
860         return num_windows + priv->banner_counter;
861 }
862
863 GtkWidget *   
864 modest_window_mgr_get_msg_edit_window (ModestWindowMgr *self)
865 {
866         GtkWidget *result;
867         ModestWindowMgrPrivate *priv;
868
869         g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL);
870
871         priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
872                 
873         if (priv->cached_editor) {
874                 result = priv->cached_editor;
875                 priv->cached_editor = NULL;
876                 load_new_editor (self);
877         } else {
878                 result = g_object_new (MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
879         }
880
881         return result;
882 }
883
884 GtkWidget *   
885 modest_window_mgr_get_msg_view_window (ModestWindowMgr *self)
886 {
887         GtkWidget *result;
888         ModestWindowMgrPrivate *priv;
889
890         g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL);
891         
892         priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
893
894         if (priv->cached_view) {
895                 result = priv->cached_view;
896                 priv->cached_view = NULL;
897                 load_new_view (self);
898         } else {
899                 result = g_object_new (MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
900         }
901
902         return result;
903 }
904
905 void
906 modest_window_mgr_register_banner (ModestWindowMgr *self)
907 {
908         ModestWindowMgrPrivate *priv;
909
910         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
911         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
912
913         priv->banner_counter++;
914 }
915
916 void
917 modest_window_mgr_unregister_banner (ModestWindowMgr *self)
918 {
919         ModestWindowMgrPrivate *priv;
920
921         g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
922         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
923
924         priv->banner_counter--;
925         if (modest_window_mgr_get_num_windows (self) == 0)
926                 g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0);
927 }
928
929 ModestWindow *
930 modest_window_mgr_show_initial_window (ModestWindowMgr *self)
931 {
932         ModestWindow *window = NULL;
933
934         /* Call the children */
935         window = MODEST_WINDOW_MGR_GET_CLASS (self)->show_initial_window (self);
936
937         if (window) {
938                 ModestAccountMgr *mgr;
939
940                 /* Show the initial window */
941                 gtk_widget_show (GTK_WIDGET (window));
942
943                 /* If there are no accounts then show the account wizard */
944                 mgr = modest_runtime_get_account_mgr();
945                 if (!modest_account_mgr_has_accounts (mgr, TRUE)) {
946                         if (!modest_ui_actions_run_account_setup_wizard (window)) {
947                                 g_debug ("%s: couldn't show account setup wizard", __FUNCTION__);
948                         }
949                 }
950         }
951
952         return window;
953 }
954
955 static ModestWindow *
956 modest_window_mgr_show_initial_window_default (ModestWindowMgr *self)
957 {
958 #ifndef MODEST_TOOLKIT_HILDON2
959         /* By default it returns the main window creating it if
960            needed */
961         return modest_window_mgr_get_main_window (self, TRUE);
962 #else
963         return NULL;
964 #endif
965 }
966
967
968 ModestWindow *
969 modest_window_mgr_get_current_top (ModestWindowMgr *self) 
970 {
971         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_current_top (self);
972 }
973
974
975 static ModestWindow *
976 modest_window_mgr_get_current_top_default (ModestWindowMgr *self)
977 {
978         g_return_val_if_reached (NULL);
979 }
980
981 gboolean
982 modest_window_mgr_screen_is_on (ModestWindowMgr *self)
983 {
984         return MODEST_WINDOW_MGR_GET_CLASS (self)->screen_is_on (self);
985 }
986
987 static gboolean
988 modest_window_mgr_screen_is_on_default (ModestWindowMgr *self)
989 {
990         /* Default implementation is assuming screen is always on */
991
992         return TRUE;
993 }
994
995 void
996 modest_window_mgr_create_caches (ModestWindowMgr *mgr)
997 {
998         MODEST_WINDOW_MGR_GET_CLASS (mgr)->create_caches (mgr);
999 }
1000
1001 static void
1002 modest_window_mgr_create_caches_default (ModestWindowMgr *self)
1003 {
1004         load_new_editor (self);
1005         load_new_view (self);
1006 }
1007
1008 static gboolean
1009 tny_list_find (TnyList *list, GObject *item)
1010 {
1011         TnyIterator *iterator;
1012         gboolean found = FALSE;
1013
1014         for (iterator = tny_list_create_iterator (list);
1015              !tny_iterator_is_done (iterator) && !found;
1016              tny_iterator_next (iterator)) {
1017                 GObject *current = tny_iterator_get_current (iterator);
1018                 if (current == item)
1019                         found = TRUE;
1020                 g_object_unref (current);
1021         }
1022         g_object_unref (iterator);
1023         
1024         return found;
1025 }
1026
1027 static void
1028 modest_window_mgr_on_queue_changed (ModestMailOperationQueue *queue,
1029                                     ModestMailOperation *mail_op,
1030                                     ModestMailOperationQueueNotification type,
1031                                     ModestWindowMgr *self)
1032 {       
1033         ModestWindowMgrPrivate *priv;
1034
1035         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1036
1037         /* We register to track progress */
1038         if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
1039                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
1040                                                                G_OBJECT (mail_op),
1041                                                                "operation-started",
1042                                                                G_CALLBACK (on_mail_operation_started),
1043                                                                self);
1044                 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
1045                                                                G_OBJECT (mail_op),
1046                                                                "operation-finished",
1047                                                                G_CALLBACK (on_mail_operation_finished),
1048                                                                self);
1049         } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
1050                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
1051                                                                   G_OBJECT (mail_op),
1052                                                                   "operation-started");
1053                 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
1054                                                                   G_OBJECT (mail_op),
1055                                                                   "operation-finished");
1056                 if (tny_list_find  (priv->progress_operations, G_OBJECT (mail_op))) {
1057                         tny_list_remove (priv->progress_operations, G_OBJECT (mail_op));
1058                         g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0);
1059                 }
1060         }
1061 }
1062
1063 static void 
1064 on_mail_operation_started (ModestMailOperation *mail_op,
1065                            gpointer user_data)
1066 {
1067         ModestWindowMgr *self;
1068         ModestWindowMgrPrivate *priv;
1069         ModestMailOperationTypeOperation op_type;
1070
1071         self = MODEST_WINDOW_MGR (user_data);
1072         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1073
1074         /* First we check if the operation is a send receive operation,
1075          * If now, we don't handle this */
1076         op_type = modest_mail_operation_get_type_operation (mail_op);
1077         if (op_type != MODEST_MAIL_OPERATION_TYPE_SEND &&
1078             op_type != MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
1079                 return;
1080         }
1081
1082         if (!tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) {
1083                 tny_list_prepend (priv->progress_operations, G_OBJECT (mail_op));
1084                 g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0);
1085         }
1086 }
1087
1088 static void 
1089 on_mail_operation_finished (ModestMailOperation *mail_op,
1090                             gpointer user_data)
1091 {
1092         ModestWindowMgr *self;
1093         ModestWindowMgrPrivate *priv;
1094
1095         self = MODEST_WINDOW_MGR (user_data);
1096         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1097
1098         if (tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) {
1099                 tny_list_remove (priv->progress_operations, G_OBJECT (mail_op));
1100                 g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0);
1101         }
1102 }
1103
1104 TnyList *
1105 modest_window_mgr_get_progress_operations (ModestWindowMgr *self)
1106 {
1107         ModestWindowMgrPrivate *priv;
1108
1109         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1110
1111         return tny_list_copy (priv->progress_operations);
1112 }
1113
1114 gboolean 
1115 modest_window_mgr_has_progress_operation (ModestWindowMgr *self)
1116 {
1117         ModestWindowMgrPrivate *priv;
1118
1119         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1120
1121         return tny_list_get_length (priv->progress_operations) > 0;
1122 }
1123
1124 gboolean 
1125 modest_window_mgr_has_progress_operation_on_account (ModestWindowMgr *self,
1126                                                      const gchar *account_name)
1127 {
1128         ModestWindowMgrPrivate *priv;
1129         gint account_ops = 0;
1130         TnyIterator *iterator;
1131
1132         priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1133
1134         if (account_name == NULL)
1135                 return 0;
1136
1137         for (iterator = tny_list_create_iterator (priv->progress_operations);
1138              !tny_iterator_is_done (iterator);
1139              tny_iterator_next (iterator)) {
1140                 ModestMailOperation *mail_op; 
1141                 TnyAccount *account;
1142
1143                 mail_op= MODEST_MAIL_OPERATION (tny_iterator_get_current (iterator));
1144                 account = modest_mail_operation_get_account (mail_op);
1145
1146                 if (account != NULL) {
1147                         const gchar *current_name;
1148
1149                         current_name = tny_account_get_id (account);
1150                         if (current_name && strcmp (current_name, account_name) == 0)
1151                                 account_ops ++;
1152                         g_object_unref (account);
1153                 }
1154
1155                 g_object_unref (mail_op);
1156         }
1157         g_object_unref (iterator);
1158
1159         return account_ops;
1160 }
1161
1162 /* 'Protected method' must be only called by children */
1163 gboolean
1164 _modest_window_mgr_close_active_modals (ModestWindowMgr *self)
1165 {
1166         GtkWidget *modal;
1167
1168         /* Exit if there are no windows */
1169         if (!modest_window_mgr_get_num_windows (self)) {
1170                 g_warning ("%s: there are no windows to close", __FUNCTION__);
1171                 return FALSE;
1172         }
1173
1174         /* Check that there is no active modal dialog */
1175         modal = (GtkWidget *) modest_window_mgr_get_modal (self);
1176         while (modal && GTK_IS_DIALOG (modal)) {
1177                 GtkWidget *parent;
1178
1179 #if defined(MODEST_TOOLKIT_HILDON2) || defined(MODEST_TOOLKIT_HILDON)
1180 #include <hildon/hildon.h>
1181                 /* If it's a hildon note then don't try to close it as
1182                    this is the default behaviour of WM, delete event
1183                    is not issued for this kind of notes as we want the
1184                    user to always click on a button */
1185                 if (HILDON_IS_NOTE (modal)) {
1186                         gtk_window_present (GTK_WINDOW (modal));
1187                         return FALSE;
1188                 }
1189 #endif
1190
1191                 /* Get the parent */
1192                 parent = (GtkWidget *) gtk_window_get_transient_for (GTK_WINDOW (modal));
1193
1194                 /* Try to close it */
1195                 gtk_dialog_response (GTK_DIALOG (modal), GTK_RESPONSE_DELETE_EVENT);
1196
1197                 /* Maybe the dialog was not closed, because a close
1198                    confirmation dialog for example. Then ignore the
1199                    register process */
1200                 if (GTK_IS_WINDOW (modal)) {
1201                         gtk_window_present (GTK_WINDOW (modal));
1202                         return FALSE;
1203                 }
1204
1205                 /* Get next modal */
1206                 modal = parent;
1207         }
1208         return TRUE;
1209 }
1210
1211 gboolean
1212 modest_window_mgr_close_all_but_initial (ModestWindowMgr *self)
1213 {
1214         return MODEST_WINDOW_MGR_GET_CLASS (self)->close_all_but_initial (self);
1215 }
1216
1217 static gboolean
1218 modest_window_mgr_close_all_but_initial_default (ModestWindowMgr *self)
1219 {
1220         /* Empty default implementation */
1221         return FALSE;
1222 }
1223
1224 ModestWindow *
1225 modest_window_mgr_get_folder_window (ModestWindowMgr *self)
1226 {
1227         return MODEST_WINDOW_MGR_GET_CLASS (self)->get_folder_window (self);
1228 }
1229
1230 static ModestWindow *
1231 modest_window_mgr_get_folder_window_default (ModestWindowMgr *self)
1232 {
1233         /* Default implementation returns NULL always */
1234
1235         return NULL;
1236 }
1237