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);
563 modest_window_mgr_register_window_default (ModestWindowMgr *self,
564 ModestWindow *window,
565 ModestWindow *parent)
567 ModestWindowMgrPrivate *priv;
569 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
570 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
572 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
574 /* We set up the queue change handler */
575 if (priv->queue_change_handler == 0) {
576 priv->queue_change_handler = g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
578 G_CALLBACK (modest_window_mgr_on_queue_changed),
582 /* Check that it's not a second main window */
583 if (MODEST_IS_MAIN_WINDOW (window)) {
584 if (priv->main_window) {
585 g_warning ("%s: trying to register a second main window",
589 priv->main_window = window;
593 /* remove from the list of pre-registered uids */
594 if (MODEST_IS_MSG_VIEW_WINDOW(window)) {
595 const gchar *uid = modest_msg_view_window_get_message_uid
596 (MODEST_MSG_VIEW_WINDOW (window));
598 MODEST_DEBUG_BLOCK(g_debug ("registering window for %s", uid ? uid : "<none>"););
600 if (has_uid (priv->preregistered_uids, uid)) {
601 priv->preregistered_uids =
602 remove_uid (priv->preregistered_uids,
603 modest_msg_view_window_get_message_uid
604 (MODEST_MSG_VIEW_WINDOW (window)));
606 } else if (MODEST_IS_MSG_EDIT_WINDOW(window)) {
607 const gchar *uid = modest_msg_edit_window_get_message_uid
608 (MODEST_MSG_EDIT_WINDOW (window));
610 MODEST_DEBUG_BLOCK(g_debug ("registering window for %s", uid););
612 priv->preregistered_uids =
613 remove_uid (priv->preregistered_uids,
614 modest_msg_edit_window_get_message_uid
615 (MODEST_MSG_EDIT_WINDOW (window)));
622 modest_window_mgr_unregister_window (ModestWindowMgr *self,
623 ModestWindow *window)
625 MODEST_WINDOW_MGR_GET_CLASS (self)->unregister_window (self, window);
629 modest_window_mgr_unregister_window_default (ModestWindowMgr *self,
630 ModestWindow *window)
632 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
633 g_return_if_fail (MODEST_IS_WINDOW (window));
636 modest_window_save_state (window);
638 /* Disconnect all the window signals */
639 modest_window_disconnect_signals (window);
641 /* Destroy the window */
642 gtk_widget_destroy (GTK_WIDGET (window));
648 modest_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
651 MODEST_WINDOW_MGR_GET_CLASS (self)->set_fullscreen_mode (self, on);
655 modest_window_mgr_set_fullscreen_mode_default (ModestWindowMgr *self,
662 modest_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
664 return MODEST_WINDOW_MGR_GET_CLASS (self)->get_fullscreen_mode (self);
668 modest_window_mgr_get_fullscreen_mode_default (ModestWindowMgr *self)
674 modest_window_mgr_show_toolbars (ModestWindowMgr *self,
676 gboolean show_toolbars,
679 return MODEST_WINDOW_MGR_GET_CLASS (self)->show_toolbars (self, window_type, show_toolbars, fullscreen);
683 modest_window_mgr_show_toolbars_default (ModestWindowMgr *self,
685 gboolean show_toolbars,
692 modest_window_mgr_set_main_window (ModestWindowMgr *self, ModestWindow *win)
694 ModestWindowMgrPrivate *priv;
696 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
698 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
699 priv->main_window = win;
703 modest_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show)
705 return MODEST_WINDOW_MGR_GET_CLASS (self)->get_main_window (self, show);
709 modest_window_mgr_get_main_window_default (ModestWindowMgr *self, gboolean show)
711 ModestWindowMgrPrivate *priv;
713 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL);
715 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
716 if (priv->main_window)
717 return priv->main_window;
720 return modest_main_window_new ();
726 modest_window_mgr_main_window_exists (ModestWindowMgr *self)
728 ModestWindowMgrPrivate *priv;
730 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
731 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
733 return priv->main_window != NULL;
738 modest_window_mgr_get_modal (ModestWindowMgr *self)
740 return MODEST_WINDOW_MGR_GET_CLASS (self)->get_modal (self);
744 modest_window_mgr_get_modal_default (ModestWindowMgr *self)
751 modest_window_mgr_set_modal (ModestWindowMgr *self,
755 MODEST_WINDOW_MGR_GET_CLASS (self)->set_modal (self, window, parent);
759 modest_window_mgr_set_modal_default (ModestWindowMgr *self,
768 on_nonhibernating_window_hide(GtkWidget *widget, gpointer user_data)
770 ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
771 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
773 /* Forget this window,
774 * so hibernation will be allowed again if no windows are remembered: */
775 priv->windows_that_prevent_hibernation =
776 g_slist_remove (priv->windows_that_prevent_hibernation, GTK_WINDOW(widget));
780 on_nonhibernating_window_show(GtkWidget *widget, gpointer user_data)
782 ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data);
783 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
785 GtkWindow *window = GTK_WINDOW (widget);
787 priv->windows_that_prevent_hibernation =
788 g_slist_append (priv->windows_that_prevent_hibernation, window);
790 /* Allow hibernation again when the window has been hidden: */
791 g_signal_connect (window, "hide",
792 G_CALLBACK (on_nonhibernating_window_hide), self);
796 modest_window_mgr_prevent_hibernation_while_window_is_shown (ModestWindowMgr *self,
799 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
801 if (GTK_WIDGET_VISIBLE(window)) {
802 on_nonhibernating_window_show (GTK_WIDGET (window), self);
804 /* Wait for it to be shown: */
805 g_signal_connect (window, "show",
806 G_CALLBACK (on_nonhibernating_window_show), self);
811 modest_window_mgr_get_hibernation_is_prevented (ModestWindowMgr *self)
813 g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE);
815 ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
817 /* Prevent hibernation if any open windows are currently
818 * preventing hibernation: */
819 return (g_slist_length (priv->windows_that_prevent_hibernation) > 0);
824 modest_window_mgr_save_state_for_all_windows (ModestWindowMgr *self)
828 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
830 /* Iterate over all windows */
831 window_list = modest_window_mgr_get_window_list (self);
834 ModestWindow *window = MODEST_WINDOW (node->data);
836 /* This calls the vfunc,
837 * so each window can do its own thing: */
838 modest_window_save_state (window);
841 node = g_list_next (node);
843 g_list_free (window_list);
847 modest_window_mgr_get_num_windows (ModestWindowMgr *self)
849 ModestWindowMgrPrivate *priv;
850 gint num_windows = 0;
853 g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), -1);
855 priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
857 window_list = modest_window_mgr_get_window_list (self);
860 num_windows = g_list_length (window_list);
861 g_list_free (window_list);
864 /* Do not take into account the main window if it was hidden */
865 if (num_windows && priv->main_window && !GTK_WIDGET_VISIBLE (priv->main_window))
868 return num_windows + priv->banner_counter;
872 modest_window_mgr_get_msg_edit_window (ModestWindowMgr *self)
875 ModestWindowMgrPrivate *priv;
877 g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL);
879 priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
881 if (priv->cached_editor) {
882 result = priv->cached_editor;
883 priv->cached_editor = NULL;
884 load_new_editor (self);
886 result = g_object_new (MODEST_TYPE_MSG_EDIT_WINDOW, NULL);
893 modest_window_mgr_get_msg_view_window (ModestWindowMgr *self)
896 ModestWindowMgrPrivate *priv;
898 g_return_val_if_fail (self && MODEST_IS_WINDOW_MGR(self), NULL);
900 priv = MODEST_WINDOW_MGR_GET_PRIVATE(self);
902 if (priv->cached_view) {
903 result = priv->cached_view;
904 priv->cached_view = NULL;
905 load_new_view (self);
907 result = g_object_new (MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
914 modest_window_mgr_register_banner (ModestWindowMgr *self)
916 ModestWindowMgrPrivate *priv;
918 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
919 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
921 priv->banner_counter++;
925 modest_window_mgr_unregister_banner (ModestWindowMgr *self)
927 ModestWindowMgrPrivate *priv;
929 g_return_if_fail (MODEST_IS_WINDOW_MGR (self));
930 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
932 priv->banner_counter--;
933 if (modest_window_mgr_get_num_windows (self) == 0)
934 g_signal_emit (self, signals[WINDOW_LIST_EMPTY_SIGNAL], 0);
938 modest_window_mgr_show_initial_window (ModestWindowMgr *self)
940 ModestWindow *window = NULL;
942 /* Call the children */
943 window = MODEST_WINDOW_MGR_GET_CLASS (self)->show_initial_window (self);
946 ModestAccountMgr *mgr;
948 /* Show the initial window */
949 gtk_widget_show (GTK_WIDGET (window));
951 /* If there are no accounts then show the account wizard */
952 mgr = modest_runtime_get_account_mgr();
953 if (!modest_account_mgr_has_accounts (mgr, TRUE)) {
954 if (!modest_ui_actions_run_account_setup_wizard (window)) {
955 g_debug ("%s: couldn't show account setup wizard", __FUNCTION__);
963 static ModestWindow *
964 modest_window_mgr_show_initial_window_default (ModestWindowMgr *self)
966 /* By default it returns the main window creating it if
968 return modest_window_mgr_get_main_window (self, TRUE);
973 modest_window_mgr_get_current_top (ModestWindowMgr *self)
975 return MODEST_WINDOW_MGR_GET_CLASS (self)->get_current_top (self);
979 static ModestWindow *
980 modest_window_mgr_get_current_top_default (ModestWindowMgr *self)
982 g_return_val_if_reached (NULL);
986 modest_window_mgr_screen_is_on (ModestWindowMgr *self)
988 return MODEST_WINDOW_MGR_GET_CLASS (self)->screen_is_on (self);
992 modest_window_mgr_screen_is_on_default (ModestWindowMgr *self)
994 /* Default implementation is assuming screen is always on */
1000 modest_window_mgr_create_caches (ModestWindowMgr *mgr)
1002 MODEST_WINDOW_MGR_GET_CLASS (mgr)->create_caches (mgr);
1006 modest_window_mgr_create_caches_default (ModestWindowMgr *self)
1008 load_new_editor (self);
1009 load_new_view (self);
1013 tny_list_find (TnyList *list, GObject *item)
1015 TnyIterator *iterator;
1016 gboolean found = FALSE;
1018 for (iterator = tny_list_create_iterator (list);
1019 !tny_iterator_is_done (iterator) && !found;
1020 tny_iterator_next (iterator)) {
1021 GObject *current = tny_iterator_get_current (iterator);
1022 if (current == item)
1024 g_object_unref (current);
1026 g_object_unref (iterator);
1032 modest_window_mgr_on_queue_changed (ModestMailOperationQueue *queue,
1033 ModestMailOperation *mail_op,
1034 ModestMailOperationQueueNotification type,
1035 ModestWindowMgr *self)
1037 ModestWindowMgrPrivate *priv;
1039 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1041 /* We register to track progress */
1042 if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED) {
1043 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
1045 "operation-started",
1046 G_CALLBACK (on_mail_operation_started),
1048 priv->sighandlers = modest_signal_mgr_connect (priv->sighandlers,
1050 "operation-finished",
1051 G_CALLBACK (on_mail_operation_finished),
1053 } else if (type == MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED) {
1054 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
1056 "operation-started");
1057 priv->sighandlers = modest_signal_mgr_disconnect (priv->sighandlers,
1059 "operation-finished");
1060 if (tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) {
1061 tny_list_remove (priv->progress_operations, G_OBJECT (mail_op));
1062 g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0);
1068 on_mail_operation_started (ModestMailOperation *mail_op,
1071 ModestWindowMgr *self;
1072 ModestWindowMgrPrivate *priv;
1073 ModestMailOperationTypeOperation op_type;
1075 self = MODEST_WINDOW_MGR (user_data);
1076 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1078 /* First we check if the operation is a send receive operation,
1079 * If now, we don't handle this */
1080 op_type = modest_mail_operation_get_type_operation (mail_op);
1081 if (op_type != MODEST_MAIL_OPERATION_TYPE_SEND &&
1082 op_type != MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
1086 if (!tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) {
1087 tny_list_prepend (priv->progress_operations, G_OBJECT (mail_op));
1088 g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0);
1093 on_mail_operation_finished (ModestMailOperation *mail_op,
1096 ModestWindowMgr *self;
1097 ModestWindowMgrPrivate *priv;
1099 self = MODEST_WINDOW_MGR (user_data);
1100 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1102 if (tny_list_find (priv->progress_operations, G_OBJECT (mail_op))) {
1103 tny_list_remove (priv->progress_operations, G_OBJECT (mail_op));
1104 g_signal_emit (self, signals[PROGRESS_LIST_CHANGED_SIGNAL], 0);
1109 modest_window_mgr_get_progress_operations (ModestWindowMgr *self)
1111 ModestWindowMgrPrivate *priv;
1113 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1115 return tny_list_copy (priv->progress_operations);
1119 modest_window_mgr_has_progress_operation (ModestWindowMgr *self)
1121 ModestWindowMgrPrivate *priv;
1123 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1125 return tny_list_get_length (priv->progress_operations) > 0;
1129 modest_window_mgr_has_progress_operation_on_account (ModestWindowMgr *self,
1130 const gchar *account_name)
1132 ModestWindowMgrPrivate *priv;
1133 gint account_ops = 0;
1134 TnyIterator *iterator;
1136 priv = MODEST_WINDOW_MGR_GET_PRIVATE (self);
1138 if (account_name == NULL)
1141 for (iterator = tny_list_create_iterator (priv->progress_operations);
1142 !tny_iterator_is_done (iterator);
1143 tny_iterator_next (iterator)) {
1144 ModestMailOperation *mail_op;
1145 TnyAccount *account;
1147 mail_op= MODEST_MAIL_OPERATION (tny_iterator_get_current (iterator));
1148 account = modest_mail_operation_get_account (mail_op);
1150 if (account != NULL) {
1151 const gchar *current_name;
1153 current_name = tny_account_get_id (account);
1154 if (current_name && strcmp (current_name, account_name) == 0)
1156 g_object_unref (account);
1159 g_object_unref (mail_op);
1161 g_object_unref (iterator);
1166 /* 'Protected method' must be only called by children */
1168 _modest_window_mgr_close_active_modals (ModestWindowMgr *self)
1172 /* Exit if there are no windows */
1173 if (!modest_window_mgr_get_num_windows (self)) {
1174 g_warning ("%s: there are no windows to close", __FUNCTION__);
1178 /* Check that there is no active modal dialog */
1179 modal = (GtkWidget *) modest_window_mgr_get_modal (self);
1180 while (modal && GTK_IS_DIALOG (modal)) {
1183 #if defined(MODEST_TOOLKIT_HILDON2) || defined(MODEST_TOOLKIT_HILDON)
1184 #include <hildon/hildon.h>
1185 /* If it's a hildon note then don't try to close it as
1186 this is the default behaviour of WM, delete event
1187 is not issued for this kind of notes as we want the
1188 user to always click on a button */
1189 if (HILDON_IS_NOTE (modal)) {
1190 gtk_window_present (GTK_WINDOW (modal));
1195 /* Get the parent */
1196 parent = (GtkWidget *) gtk_window_get_transient_for (GTK_WINDOW (modal));
1198 /* Try to close it */
1199 gtk_dialog_response (GTK_DIALOG (modal), GTK_RESPONSE_DELETE_EVENT);
1201 /* Maybe the dialog was not closed, because a close
1202 confirmation dialog for example. Then ignore the
1204 if (GTK_IS_WINDOW (modal)) {
1205 gtk_window_present (GTK_WINDOW (modal));
1209 /* Get next modal */
1216 modest_window_mgr_close_all_but_initial (ModestWindowMgr *self)
1218 return MODEST_WINDOW_MGR_GET_CLASS (self)->close_all_but_initial (self);
1222 modest_window_mgr_close_all_but_initial_default (ModestWindowMgr *self)
1224 /* Empty default implementation */