1 /* Copyright (c) 2006,2007 Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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.
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.
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>
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);
49 static gboolean modest_window_mgr_register_window_default (ModestWindowMgr *self,
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,
56 static gboolean modest_window_mgr_get_fullscreen_mode_default (ModestWindowMgr *self);
57 static void modest_window_mgr_show_toolbars_default (ModestWindowMgr *self,
59 gboolean show_toolbars,
61 static ModestWindow* modest_window_mgr_get_main_window_default (ModestWindowMgr *self, gboolean show);
62 static GtkWindow *modest_window_mgr_get_modal_default (ModestWindowMgr *self);
63 static void modest_window_mgr_set_modal_default (ModestWindowMgr *self,
66 static gboolean modest_window_mgr_close_all_windows_default (ModestWindowMgr *self);
67 static gboolean modest_window_mgr_find_registered_header_default (ModestWindowMgr *self,
70 static gboolean modest_window_mgr_find_registered_message_uid_default (ModestWindowMgr *self,
73 static GList *modest_window_mgr_get_window_list_default (ModestWindowMgr *self);
74 static ModestWindow *modest_window_mgr_show_initial_window_default (ModestWindowMgr *self);
75 static ModestWindow *modest_window_mgr_get_current_top_default (ModestWindowMgr *self);
76 static gboolean modest_window_mgr_screen_is_on_default (ModestWindowMgr *self);
77 static void modest_window_mgr_create_caches_default (ModestWindowMgr *self);
78 static void modest_window_mgr_on_queue_changed (ModestMailOperationQueue *queue,
79 ModestMailOperation *mail_op,
80 ModestMailOperationQueueNotification type,
81 ModestWindowMgr *self);
82 static void on_mail_operation_started (ModestMailOperation *mail_op,
84 static void on_mail_operation_finished (ModestMailOperation *mail_op,
86 static gboolean modest_window_mgr_close_all_but_initial_default (ModestWindowMgr *self);
90 WINDOW_LIST_EMPTY_SIGNAL,
91 PROGRESS_LIST_CHANGED_SIGNAL,
95 typedef struct _ModestWindowMgrPrivate ModestWindowMgrPrivate;
96 struct _ModestWindowMgrPrivate {
99 ModestWindow *main_window;
101 GSList *windows_that_prevent_hibernation;
102 GSList *preregistered_uids;
106 GtkWidget *cached_view;
107 GtkWidget *cached_editor;
108 guint idle_load_view_id;
109 guint idle_load_editor_id;
111 guint queue_change_handler;
112 TnyList *progress_operations;
116 #define MODEST_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
117 MODEST_TYPE_WINDOW_MGR, \
118 ModestWindowMgrPrivate))
120 static GObjectClass *parent_class = NULL;
122 /* uncomment the following if you have defined any signals */
123 static guint signals[NUM_SIGNALS] = {0};
126 modest_window_mgr_get_type (void)
128 static GType my_type = 0;
130 static const GTypeInfo my_info = {
131 sizeof(ModestWindowMgrClass),
132 NULL, /* base init */
133 NULL, /* base finalize */
134 (GClassInitFunc) modest_window_mgr_class_init,
135 NULL, /* class finalize */
136 NULL, /* class data */
137 sizeof(ModestWindowMgr),
139 (GInstanceInitFunc) modest_window_mgr_init,
142 my_type = g_type_register_static (G_TYPE_OBJECT,
150 modest_window_mgr_class_init (ModestWindowMgrClass *klass)
152 GObjectClass *gobject_class;
153 ModestWindowMgrClass *mgr_class;
155 gobject_class = (GObjectClass*) klass;
156 mgr_class = (ModestWindowMgrClass *) klass;
158 parent_class = g_type_class_peek_parent (klass);
159 gobject_class->finalize = modest_window_mgr_finalize;
160 mgr_class->register_window = modest_window_mgr_register_window_default;
161 mgr_class->unregister_window = modest_window_mgr_unregister_window_default;
162 mgr_class->set_fullscreen_mode = modest_window_mgr_set_fullscreen_mode_default;
163 mgr_class->get_fullscreen_mode = modest_window_mgr_get_fullscreen_mode_default;
164 mgr_class->show_toolbars = modest_window_mgr_show_toolbars_default;
165 mgr_class->get_main_window = modest_window_mgr_get_main_window_default;
166 mgr_class->get_modal = modest_window_mgr_get_modal_default;
167 mgr_class->set_modal = modest_window_mgr_set_modal_default;
168 mgr_class->close_all_windows = modest_window_mgr_close_all_windows_default;
169 mgr_class->find_registered_header = modest_window_mgr_find_registered_header_default;
170 mgr_class->find_registered_message_uid = modest_window_mgr_find_registered_message_uid_default;
171 mgr_class->get_window_list = modest_window_mgr_get_window_list_default;
172 mgr_class->show_initial_window = modest_window_mgr_show_initial_window_default;
173 mgr_class->get_current_top = modest_window_mgr_get_current_top_default;
174 mgr_class->screen_is_on = modest_window_mgr_screen_is_on_default;
175 mgr_class->create_caches = modest_window_mgr_create_caches_default;
176 mgr_class->close_all_but_initial = modest_window_mgr_close_all_but_initial_default;
178 g_type_class_add_private (gobject_class, sizeof(ModestWindowMgrPrivate));
182 * ModestWindowMgr::window-list-empty
183 * @self: the #ModestWindowMgr that emits the signal
184 * @user_data: user data set when the signal handler was connected
186 * Issued whenever the window list becomes empty
188 signals[WINDOW_LIST_EMPTY_SIGNAL] =
189 g_signal_new ("window-list-empty",
190 G_TYPE_FROM_CLASS (gobject_class),
192 G_STRUCT_OFFSET (ModestWindowMgrClass, window_list_empty),
194 g_cclosure_marshal_VOID__VOID,
198 * ModestWindowMgr::progress-list-changed
199 * @self: the #ModestWindowMgr that emits the signal
200 * @user_data: user data set when the signal handler was connected
202 * Issued whenever the progress mail operations list becomes changed
204 signals[PROGRESS_LIST_CHANGED_SIGNAL] =
205 g_signal_new ("progress-list-changed",
206 G_TYPE_FROM_CLASS (gobject_class),
208 G_STRUCT_OFFSET (ModestWindowMgrClass, progress_list_changed),
210 g_cclosure_marshal_VOID__VOID,
215 idle_load_view (ModestWindowMgr *mgr)
217 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (mgr);
219 priv->cached_view = g_object_new (MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
220 priv->idle_load_view_id = 0;
225 idle_load_editor (ModestWindowMgr *mgr)
227 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (mgr);
229 priv->cached_editor = g_object_new (MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
230 priv->idle_load_editor_id = 0;
235 load_new_view (ModestWindowMgr *self)
237 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
238 if ((priv->cached_view == NULL) && (priv->idle_load_view_id == 0))
239 priv->idle_load_view_id = g_timeout_add (2500, (GSourceFunc) idle_load_view, self);
243 load_new_editor (ModestWindowMgr *self)
245 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
246 if ((priv->cached_editor == NULL) && (priv->idle_load_editor_id == 0))
247 priv->idle_load_editor_id = g_timeout_add (5000, (GSourceFunc) idle_load_editor, self);
251 modest_window_mgr_init (ModestWindowMgr *obj)
253 ModestWindowMgrPrivate *priv;
255 priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
256 priv->banner_counter = 0;
257 priv->main_window = NULL;
259 priv->preregistered_uids = NULL;
261 priv->closing_time = 0;
263 priv->cached_view = NULL;
264 priv->cached_editor = NULL;
266 priv->windows_that_prevent_hibernation = NULL;
268 priv->queue_change_handler = 0;
269 priv->progress_operations = TNY_LIST (tny_simple_list_new ());
273 modest_window_mgr_finalize (GObject *obj)
275 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE(obj);
277 if (priv->idle_load_view_id > 0) {
278 g_source_remove (priv->idle_load_view_id);
279 priv->idle_load_view_id = 0;
282 if (priv->idle_load_editor_id > 0) {
283 g_source_remove (priv->idle_load_editor_id);
284 priv->idle_load_editor_id = 0;
287 if (priv->cached_view) {
288 gtk_widget_destroy (priv->cached_view);
289 priv->cached_view = NULL;
291 if (priv->cached_editor) {
292 gtk_widget_destroy (priv->cached_editor);
293 priv->cached_editor = NULL;
296 if (priv->windows_that_prevent_hibernation) {
297 g_slist_free (priv->windows_that_prevent_hibernation);
298 priv->cached_editor = NULL;
301 modest_signal_mgr_disconnect_all_and_destroy (priv->sighandlers);
302 priv->sighandlers = NULL;
304 if (priv->queue_change_handler > 0) {
305 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
306 priv->queue_change_handler);
307 priv->queue_change_handler = 0;
310 if (priv->progress_operations) {
311 g_object_unref (priv->progress_operations);
312 priv->progress_operations = NULL;
315 g_slist_foreach (priv->preregistered_uids, (GFunc)g_free, NULL);
316 g_slist_free (priv->preregistered_uids);
318 G_OBJECT_CLASS(parent_class)->finalize (obj);
322 modest_window_mgr_new (void)
324 return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_WINDOW_MGR, NULL));
330 /* do we have uid? */
332 has_uid (GSList *list, const gchar *uid)
334 GSList *cursor = list;
340 if (cursor->data && strcmp (cursor->data, uid) == 0)
342 cursor = g_slist_next (cursor);
348 /* remove all from the list have have uid = uid */
350 remove_uid (GSList *list, const gchar *uid)
352 GSList *cursor = list, *start = list;
358 GSList *next = g_slist_next (cursor);
359 if (cursor->data && strcmp (cursor->data, uid) == 0) {
360 g_free (cursor->data);
361 start = g_slist_delete_link (start, cursor);
370 append_uid (GSList *list, const gchar *uid)
372 return g_slist_append (list, g_strdup(uid));
378 modest_window_mgr_register_header (ModestWindowMgr *self, TnyHeader *header, const gchar *alt_uid)
380 ModestWindowMgrPrivate *priv;
383 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
384 g_return_if_fail (TNY_IS_HEADER(header));
386 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
387 if (alt_uid != NULL) {
388 uid = g_strdup (alt_uid);
390 uid = modest_tny_folder_get_header_unique_id (header);
393 if (!has_uid (priv->preregistered_uids, uid)) {
394 MODEST_DEBUG_BLOCK(g_debug ("registering new uid %s", uid););
395 priv->preregistered_uids = append_uid (priv->preregistered_uids, uid);
397 MODEST_DEBUG_BLOCK(g_debug ("already had uid %s", uid););
403 modest_window_mgr_unregister_header (ModestWindowMgr *self, TnyHeader *header)
405 ModestWindowMgrPrivate *priv;
408 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
409 g_return_if_fail (TNY_IS_HEADER(header));
411 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
412 uid = modest_tny_folder_get_header_unique_id (header);
414 if (!has_uid (priv->preregistered_uids, uid)) {
415 MODEST_DEBUG_BLOCK(g_debug ("trying to unregister non-existing uid %s", uid););
416 priv->preregistered_uids = append_uid (priv->preregistered_uids, uid);
418 MODEST_DEBUG_BLOCK(g_debug ("unregistering uid %s", uid););
420 if (has_uid (priv->preregistered_uids, uid)) {
421 priv->preregistered_uids = remove_uid (priv->preregistered_uids, uid);
422 if (has_uid (priv->preregistered_uids, uid))
423 g_debug ("BUG: uid %s NOT removed", uid);
425 MODEST_DEBUG_BLOCK(g_debug ("uid %s removed", uid););
432 #define MODEST_WINDOW_HELP_ID_PARAM "help-id"
435 modest_window_mgr_register_help_id (ModestWindowMgr *self, GtkWindow *win, const gchar* help_id)
437 /* we don't need 'self', but for API consistency... */
438 g_return_if_fail (self && MODEST_IS_WINDOW_MGR(self));
440 g_return_if_fail (win && GTK_IS_WINDOW(win));
441 g_return_if_fail (help_id);
443 g_object_set_data_full (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM,
444 g_strdup(help_id), g_free);
449 modest_window_mgr_get_help_id (ModestWindowMgr *self, GtkWindow *win)
451 /* we don't need 'self', but for API consistency... */
452 g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR (self), NULL);
453 g_return_val_if_fail (win, NULL);
455 return g_object_get_data (G_OBJECT(win), MODEST_WINDOW_HELP_ID_PARAM);
459 modest_window_mgr_close_all_windows (ModestWindowMgr *self)
461 return MODEST_WINDOW_MGR_GET_CLASS (self)->close_all_windows (self);
465 modest_window_mgr_close_all_windows_default (ModestWindowMgr *self)
472 modest_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
475 return MODEST_WINDOW_MGR_GET_CLASS (self)->find_registered_header (self, header, win);
479 modest_window_mgr_find_registered_header_default (ModestWindowMgr *self, TnyHeader *header,
484 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
485 g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
487 uid = modest_tny_folder_get_header_unique_id (header);
490 return modest_window_mgr_find_registered_message_uid (self, uid, win);
496 modest_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
499 return MODEST_WINDOW_MGR_GET_CLASS (self)->find_registered_message_uid (self, msg_uid, win);
503 modest_window_mgr_find_registered_message_uid_default (ModestWindowMgr *self, const gchar *msg_uid,
506 ModestWindowMgrPrivate *priv = NULL;
508 gboolean has_header = FALSE;
510 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
511 g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
513 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
518 has_header = has_uid (priv->preregistered_uids, msg_uid);
525 modest_window_mgr_get_window_list (ModestWindowMgr *self)
527 return MODEST_WINDOW_MGR_GET_CLASS (self)->get_window_list (self);
531 modest_window_mgr_get_window_list_default (ModestWindowMgr *self)
537 modest_window_mgr_register_window (ModestWindowMgr *self,
538 ModestWindow *window,
539 ModestWindow *parent)
541 gboolean no_windows, retval;
543 no_windows = (modest_window_mgr_get_num_windows (self) == 0);
545 retval = MODEST_WINDOW_MGR_GET_CLASS (self)->register_window (self, window, parent);
548 /* If this is the first registered window then reset the
549 status of the TnyDevice as it might be forced to be offline
550 when modest is running in the background (see
551 modest_tny_account_store_new()) */
552 if (tny_device_is_forced (modest_runtime_get_device ()))
553 tny_device_reset (modest_runtime_get_device ());
555 /* Do also allow modest to shutdown when the
556 application is closed */
557 modest_runtime_set_allow_shutdown (TRUE);
564 modest_window_mgr_register_window_default (ModestWindowMgr *self,
565 ModestWindow *window,
566 ModestWindow *parent)
568 ModestWindowMgrPrivate *priv;
570 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
571 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
573 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
575 /* We set up the queue change handler */
576 if (priv->queue_change_handler == 0) {
577 priv->queue_change_handler = g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
579 G_CALLBACK (modest_window_mgr_on_queue_changed),
583 /* Check that it's not a second main window */
584 if (MODEST_IS_MAIN_WINDOW (window)) {
585 if (priv->main_window) {
586 g_warning ("%s: trying to register a second main window",
590 priv->main_window = window;
594 /* remove from the list of pre-registered uids */
595 if (MODEST_IS_MSG_VIEW_WINDOW(window)) {
596 const gchar *uid = modest_msg_view_window_get_message_uid
597 (MODEST_MSG_VIEW_WINDOW (window));
599 MODEST_DEBUG_BLOCK(g_debug ("registering window for %s", uid ? uid : "<none>"););
601 if (has_uid (priv->preregistered_uids, uid)) {
602 priv->preregistered_uids =
603 remove_uid (priv->preregistered_uids,
604 modest_msg_view_window_get_message_uid
605 (MODEST_MSG_VIEW_WINDOW (window)));
607 } else if (MODEST_IS_MSG_EDIT_WINDOW(window)) {
608 const gchar *uid = modest_msg_edit_window_get_message_uid
609 (MODEST_MSG_EDIT_WINDOW (window));
611 MODEST_DEBUG_BLOCK(g_debug ("registering window for %s", uid););
613 priv->preregistered_uids =
614 remove_uid (priv->preregistered_uids,
615 modest_msg_edit_window_get_message_uid
616 (MODEST_MSG_EDIT_WINDOW (window)));
623 modest_window_mgr_unregister_window (ModestWindowMgr *self,
624 ModestWindow *window)
626 MODEST_WINDOW_MGR_GET_CLASS (self)->unregister_window (self, window);
630 modest_window_mgr_unregister_window_default (ModestWindowMgr *self,
631 ModestWindow *window)
633 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
634 g_return_if_fail (MODEST_IS_WINDOW (window));
637 modest_window_save_state (window);
639 /* Disconnect all the window signals */
640 modest_window_disconnect_signals (window);
642 /* Destroy the window */
643 gtk_widget_destroy (GTK_WIDGET (window));
649 modest_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
652 MODEST_WINDOW_MGR_GET_CLASS (self)->set_fullscreen_mode (self, on);
656 modest_window_mgr_set_fullscreen_mode_default (ModestWindowMgr *self,
663 modest_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
665 return MODEST_WINDOW_MGR_GET_CLASS (self)->get_fullscreen_mode (self);
669 modest_window_mgr_get_fullscreen_mode_default (ModestWindowMgr *self)
675 modest_window_mgr_show_toolbars (ModestWindowMgr *self,
677 gboolean show_toolbars,
680 return MODEST_WINDOW_MGR_GET_CLASS (self)->show_toolbars (self, window_type, show_toolbars, fullscreen);
684 modest_window_mgr_show_toolbars_default (ModestWindowMgr *self,
686 gboolean show_toolbars,
693 modest_window_mgr_set_main_window (ModestWindowMgr *self, ModestWindow *win)
695 ModestWindowMgrPrivate *priv;
697 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
699 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
700 priv->main_window = win;
704 modest_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show)
706 return MODEST_WINDOW_MGR_GET_CLASS (self)->get_main_window (self, show);
710 modest_window_mgr_get_main_window_default (ModestWindowMgr *self, gboolean show)
712 ModestWindowMgrPrivate *priv;
714 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL);
716 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
717 if (priv->main_window)
718 return priv->main_window;
721 return modest_main_window_new ();
727 modest_window_mgr_main_window_exists (ModestWindowMgr *self)
729 ModestWindowMgrPrivate *priv;
731 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
732 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
734 return priv->main_window != NULL;
739 modest_window_mgr_get_modal (ModestWindowMgr *self)
741 return MODEST_WINDOW_MGR_GET_CLASS (self)->get_modal (self);
745 modest_window_mgr_get_modal_default (ModestWindowMgr *self)
752 modest_window_mgr_set_modal (ModestWindowMgr *self,
756 MODEST_WINDOW_MGR_GET_CLASS (self)->set_modal (self, window, parent);
760 modest_window_mgr_set_modal_default (ModestWindowMgr *self,
769 on_nonhibernating_window_hide(GtkWidget *widget, gpointer user_data)
771 ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
772 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
774 /* Forget this window,
775 * so hibernation will be allowed again if no windows are remembered: */
776 priv->windows_that_prevent_hibernation =
777 g_slist_remove (priv->windows_that_prevent_hibernation, GTK_WINDOW(widget));
781 on_nonhibernating_window_show(GtkWidget *widget, gpointer user_data)
783 ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
784 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
786 GtkWindow *window = GTK_WINDOW (widget);
788 priv->windows_that_prevent_hibernation =
789 g_slist_append (priv->windows_that_prevent_hibernation, window);
791 /* Allow hibernation again when the window has been hidden: */
792 g_signal_connect (window, "hide",
793 G_CALLBACK (on_nonhibernating_window_hide), self);
797 modest_window_mgr_prevent_hibernation_while_window_is_shown (ModestWindowMgr *self,
800 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
802 if (GTK_WIDGET_VISIBLE(window)) {
803 on_nonhibernating_window_show (GTK_WIDGET (window), self);
805 /* Wait for it to be shown: */
806 g_signal_connect (window, "show",
807 G_CALLBACK (on_nonhibernating_window_show), self);
812 modest_window_mgr_get_hibernation_is_prevented (ModestWindowMgr *self)
814 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
816 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
818 /* Prevent hibernation if any open windows are currently
819 * preventing hibernation: */
820 return (g_slist_length (priv->windows_that_prevent_hibernation) > 0);
825 modest_window_mgr_save_state_for_all_windows (ModestWindowMgr *self)
829 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
831 /* Iterate over all windows */
832 window_list = modest_window_mgr_get_window_list (self);
835 ModestWindow *window = MODEST_WINDOW (node->data);
837 /* This calls the vfunc,
838 * so each window can do its own thing: */
839 modest_window_save_state (window);
842 node = g_list_next (node);
844 g_list_free (window_list);
848 modest_window_mgr_get_num_windows (ModestWindowMgr *self)
850 ModestWindowMgrPrivate *priv;
851 gint num_windows = 0;
854 g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), -1);
856 priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
858 window_list = modest_window_mgr_get_window_list (self);
861 num_windows = g_list_length (window_list);
862 g_list_free (window_list);
865 /* Do not take into account the main window if it was hidden */
866 if (num_windows && priv->main_window && !GTK_WIDGET_VISIBLE (priv->main_window))
869 return num_windows + priv->banner_counter;
873 modest_window_mgr_get_msg_edit_window (ModestWindowMgr *self)
876 ModestWindowMgrPrivate *priv;
878 g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL);
880 priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
882 if (priv->cached_editor) {
883 result = priv->cached_editor;
884 priv->cached_editor = NULL;
885 load_new_editor (self);
887 result = g_object_new (MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
894 modest_window_mgr_get_msg_view_window (ModestWindowMgr *self)
897 ModestWindowMgrPrivate *priv;
899 g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL);
901 priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
903 if (priv->cached_view) {
904 result = priv->cached_view;
905 priv->cached_view = NULL;
906 load_new_view (self);
908 result = g_object_new (MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
915 modest_window_mgr_register_banner (ModestWindowMgr *self)
917 ModestWindowMgrPrivate *priv;
919 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
920 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
922 priv->banner_counter++;
926 modest_window_mgr_unregister_banner (ModestWindowMgr *self)
928 ModestWindowMgrPrivate *priv;
930 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
931 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
933 priv->banner_counter--;
934 if (modest_window_mgr_get_num_windows (self) == 0)
935 g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0);
939 modest_window_mgr_show_initial_window (ModestWindowMgr *self)
941 ModestWindow *window = NULL;
943 /* Call the children */
944 window = MODEST_WINDOW_MGR_GET_CLASS (self)->show_initial_window (self);
947 ModestAccountMgr *mgr;
949 /* Show the initial window */
950 gtk_widget_show (GTK_WIDGET (window));
952 /* If there are no accounts then show the account wizard */
953 mgr = modest_runtime_get_account_mgr();
954 if (!modest_account_mgr_has_accounts (mgr, TRUE)) {
955 if (!modest_ui_actions_run_account_setup_wizard (window)) {
956 g_debug ("%s: couldn't show account setup wizard", __FUNCTION__);
964 static ModestWindow *
965 modest_window_mgr_show_initial_window_default (ModestWindowMgr *self)
967 /* By default it returns the main window creating it if
969 return modest_window_mgr_get_main_window (self, TRUE);
974 modest_window_mgr_get_current_top (ModestWindowMgr *self)
976 return MODEST_WINDOW_MGR_GET_CLASS (self)->get_current_top (self);
980 static ModestWindow *
981 modest_window_mgr_get_current_top_default (ModestWindowMgr *self)
983 g_return_val_if_reached (NULL);
987 modest_window_mgr_screen_is_on (ModestWindowMgr *self)
989 return MODEST_WINDOW_MGR_GET_CLASS (self)->screen_is_on (self);
993 modest_window_mgr_screen_is_on_default (ModestWindowMgr *self)
995 /* Default implementation is assuming screen is always on */
1001 modest_window_mgr_create_caches (ModestWindowMgr *mgr)
1003 MODEST_WINDOW_MGR_GET_CLASS (mgr)->create_caches (mgr);
1007 modest_window_mgr_create_caches_default (ModestWindowMgr *self)
1009 load_new_editor (self);
1010 load_new_view (self);
1014 tny_list_find (TnyList *list, GObject *item)
1016 TnyIterator *iterator;
1017 gboolean found = FALSE;
1019 for (iterator = tny_list_create_iterator (list);
1020 !tny_iterator_is_done (iterator) && !found;
1021 tny_iterator_next (iterator)) {
1022 GObject *current = tny_iterator_get_current (iterator);
1023 if (current == item)
1025 g_object_unref (current);
1027 g_object_unref (iterator);
1033 modest_window_mgr_on_queue_changed (ModestMailOperationQueue *queue,
1034 ModestMailOperation *mail_op,
1035 ModestMailOperationQueueNotification type,
1036 ModestWindowMgr *self)
1038 ModestWindowMgrPrivate *priv;
1040 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1042 /* We register to track progress */
1043 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
1044 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
1046 "operation-started",
1047 G_CALLBACK (on_mail_operation_started),
1049 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
1051 "operation-finished",
1052 G_CALLBACK (on_mail_operation_finished),
1054 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
1055 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
1057 "operation-started");
1058 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
1060 "operation-finished");
1061 if (tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) {
1062 tny_list_remove (priv->progress_operations, G_OBJECT (mail_op));
1063 g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0);
1069 on_mail_operation_started (ModestMailOperation *mail_op,
1072 ModestWindowMgr *self;
1073 ModestWindowMgrPrivate *priv;
1074 ModestMailOperationTypeOperation op_type;
1076 self = MODEST_WINDOW_MGR (user_data);
1077 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1079 /* First we check if the operation is a send receive operation,
1080 * If now, we don't handle this */
1081 op_type = modest_mail_operation_get_type_operation (mail_op);
1082 if (op_type != MODEST_MAIL_OPERATION_TYPE_SEND &&
1083 op_type != MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
1087 if (!tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) {
1088 tny_list_prepend (priv->progress_operations, G_OBJECT (mail_op));
1089 g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0);
1094 on_mail_operation_finished (ModestMailOperation *mail_op,
1097 ModestWindowMgr *self;
1098 ModestWindowMgrPrivate *priv;
1100 self = MODEST_WINDOW_MGR (user_data);
1101 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1103 if (tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) {
1104 tny_list_remove (priv->progress_operations, G_OBJECT (mail_op));
1105 g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0);
1110 modest_window_mgr_get_progress_operations (ModestWindowMgr *self)
1112 ModestWindowMgrPrivate *priv;
1114 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1116 return tny_list_copy (priv->progress_operations);
1120 modest_window_mgr_has_progress_operation (ModestWindowMgr *self)
1122 ModestWindowMgrPrivate *priv;
1124 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1126 return tny_list_get_length (priv->progress_operations) > 0;
1130 modest_window_mgr_has_progress_operation_on_account (ModestWindowMgr *self,
1131 const gchar *account_name)
1133 ModestWindowMgrPrivate *priv;
1134 gint account_ops = 0;
1135 TnyIterator *iterator;
1137 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1139 if (account_name == NULL)
1142 for (iterator = tny_list_create_iterator (priv->progress_operations);
1143 !tny_iterator_is_done (iterator);
1144 tny_iterator_next (iterator)) {
1145 ModestMailOperation *mail_op;
1146 TnyAccount *account;
1148 mail_op= MODEST_MAIL_OPERATION (tny_iterator_get_current (iterator));
1149 account = modest_mail_operation_get_account (mail_op);
1151 if (account != NULL) {
1152 const gchar *current_name;
1154 current_name = tny_account_get_id (account);
1155 if (current_name && strcmp (current_name, account_name) == 0)
1157 g_object_unref (account);
1160 g_object_unref (mail_op);
1162 g_object_unref (iterator);
1167 /* 'Protected method' must be only called by children */
1169 _modest_window_mgr_close_active_modals (ModestWindowMgr *self)
1173 /* Exit if there are no windows */
1174 if (!modest_window_mgr_get_num_windows (self)) {
1175 g_warning ("%s: there are no windows to close", __FUNCTION__);
1179 /* Check that there is no active modal dialog */
1180 modal = (GtkWidget *) modest_window_mgr_get_modal (self);
1181 while (modal && GTK_IS_DIALOG (modal)) {
1184 #if defined(MODEST_TOOLKIT_HILDON2) || defined(MODEST_TOOLKIT_HILDON)
1185 #include <hildon/hildon.h>
1186 /* If it's a hildon note then don't try to close it as
1187 this is the default behaviour of WM, delete event
1188 is not issued for this kind of notes as we want the
1189 user to always click on a button */
1190 if (HILDON_IS_NOTE (modal)) {
1191 gtk_window_present (GTK_WINDOW (modal));
1196 /* Get the parent */
1197 parent = (GtkWidget *) gtk_window_get_transient_for (GTK_WINDOW (modal));
1199 /* Try to close it */
1200 gtk_dialog_response (GTK_DIALOG (modal), GTK_RESPONSE_DELETE_EVENT);
1202 /* Maybe the dialog was not closed, because a close
1203 confirmation dialog for example. Then ignore the
1205 if (GTK_IS_WINDOW (modal)) {
1206 gtk_window_present (GTK_WINDOW (modal));
1210 /* Get next modal */
1217 modest_window_mgr_close_all_but_initial (ModestWindowMgr *self)
1219 return MODEST_WINDOW_MGR_GET_CLASS (self)->close_all_but_initial (self);
1223 modest_window_mgr_close_all_but_initial_default (ModestWindowMgr *self)
1225 /* Empty default implementation */