1 /* Copyright (c) 2008, 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 <hildon/hildon.h>
32 #include "modest-hildon2-window.h"
33 #include "modest-hildon2-window-mgr.h"
34 #include "modest-msg-edit-window.h"
35 #include "modest-mailboxes-window.h"
36 #include "modest-header-window.h"
37 #include "modest-main-window.h"
38 #include "modest-window-mgr-priv.h"
39 #include "modest-conf.h"
40 #include "modest-defs.h"
41 #include "modest-signal-mgr.h"
42 #include "modest-runtime.h"
43 #include "modest-platform.h"
44 #include "modest-ui-actions.h"
45 #include "modest-debug.h"
46 #include "modest-tny-folder.h"
47 #include "modest-folder-window.h"
48 #include "modest-accounts-window.h"
49 #include "modest-maemo-utils.h"
50 #include "modest-utils.h"
51 #include "modest-tny-msg.h"
52 #include "modest-tny-account.h"
53 #include <tny-merge-folder.h>
55 /* 'private'/'protected' functions */
56 static void modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass);
57 static void modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj);
58 static void modest_hildon2_window_mgr_finalize (GObject *obj);
60 static gboolean on_window_destroy (ModestWindow *window,
62 ModestHildon2WindowMgr *self);
64 static gboolean modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
66 ModestWindow *parent);
67 static void modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
68 ModestWindow *window);
69 static void modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
71 static gboolean modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self);
72 static void modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
74 gboolean show_toolbars,
76 static GtkWindow *modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self);
77 static void modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
80 static gboolean modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self,
83 static gboolean modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self,
86 static GList *modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self);
87 static gboolean modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self);
88 static gboolean modest_hildon2_window_mgr_close_all_but_initial (ModestWindowMgr *self);
89 static gboolean window_has_modals (ModestWindow *window);
90 static ModestWindow *modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self);
91 static ModestWindow *modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self);
92 static gboolean modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self);
93 static void modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self);
94 static void osso_display_event_cb (osso_display_state_t state,
96 static void on_account_removed (TnyAccountStore *acc_store,
100 typedef struct _ModestHildon2WindowMgrPrivate ModestHildon2WindowMgrPrivate;
101 struct _ModestHildon2WindowMgrPrivate {
104 GQueue *modal_windows;
106 gboolean fullscreen_mode;
108 GHashTable *destroy_handlers;
109 GHashTable *viewer_handlers;
110 GSList *window_state_uids;
114 GSList *modal_handler_uids;
115 ModestWindow *current_top;
117 gulong accounts_handler;
120 osso_display_state_t display_state;
122 #define MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
123 MODEST_TYPE_HILDON2_WINDOW_MGR, \
124 ModestHildon2WindowMgrPrivate))
126 static GObjectClass *parent_class = NULL;
129 modest_hildon2_window_mgr_get_type (void)
131 static GType my_type = 0;
133 static const GTypeInfo my_info = {
134 sizeof(ModestHildon2WindowMgrClass),
135 NULL, /* base init */
136 NULL, /* base finalize */
137 (GClassInitFunc) modest_hildon2_window_mgr_class_init,
138 NULL, /* class finalize */
139 NULL, /* class data */
140 sizeof(ModestHildon2WindowMgr),
142 (GInstanceInitFunc) modest_hildon2_window_mgr_instance_init,
145 my_type = g_type_register_static (MODEST_TYPE_WINDOW_MGR,
146 "ModestHildon2WindowMgr",
153 modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass)
155 GObjectClass *gobject_class;
156 ModestWindowMgrClass *mgr_class;
158 gobject_class = (GObjectClass*) klass;
159 mgr_class = (ModestWindowMgrClass *) klass;
161 parent_class = g_type_class_peek_parent (klass);
162 gobject_class->finalize = modest_hildon2_window_mgr_finalize;
163 mgr_class->register_window = modest_hildon2_window_mgr_register_window;
164 mgr_class->unregister_window = modest_hildon2_window_mgr_unregister_window;
165 mgr_class->set_fullscreen_mode = modest_hildon2_window_mgr_set_fullscreen_mode;
166 mgr_class->get_fullscreen_mode = modest_hildon2_window_mgr_get_fullscreen_mode;
167 mgr_class->show_toolbars = modest_hildon2_window_mgr_show_toolbars;
168 mgr_class->get_modal = modest_hildon2_window_mgr_get_modal;
169 mgr_class->set_modal = modest_hildon2_window_mgr_set_modal;
170 mgr_class->find_registered_header = modest_hildon2_window_mgr_find_registered_header;
171 mgr_class->find_registered_message_uid = modest_hildon2_window_mgr_find_registered_message_uid;
172 mgr_class->get_window_list = modest_hildon2_window_mgr_get_window_list;
173 mgr_class->close_all_windows = modest_hildon2_window_mgr_close_all_windows;
174 mgr_class->close_all_but_initial = modest_hildon2_window_mgr_close_all_but_initial;
175 mgr_class->show_initial_window = modest_hildon2_window_mgr_show_initial_window;
176 mgr_class->get_current_top = modest_hildon2_window_mgr_get_current_top;
177 mgr_class->screen_is_on = modest_hildon2_window_mgr_screen_is_on;
178 mgr_class->create_caches = modest_hildon2_window_mgr_create_caches;
180 g_type_class_add_private (gobject_class, sizeof(ModestHildon2WindowMgrPrivate));
185 modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj)
187 ModestHildon2WindowMgrPrivate *priv;
189 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
190 priv->window_list = NULL;
191 priv->fullscreen_mode = FALSE;
192 priv->window_state_uids = NULL;
194 priv->modal_windows = g_queue_new ();
195 priv->queue_lock = g_mutex_new ();
197 /* Could not initialize it from gconf, singletons are not
199 priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
200 priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
202 priv->closing_time = 0;
204 priv->modal_handler_uids = NULL;
205 priv->display_state = OSSO_DISPLAY_ON;
207 /* Listen for changes in the screen, we don't want to show a
208 led pattern when the display is on for example */
209 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
210 osso_display_event_cb,
216 modest_hildon2_window_mgr_finalize (GObject *obj)
218 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
219 ModestTnyAccountStore *acc_store;
221 modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids);
222 priv->window_state_uids = NULL;
224 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
227 acc_store = modest_runtime_get_account_store ();
228 if (acc_store && g_signal_handler_is_connected (acc_store, priv->accounts_handler))
229 g_signal_handler_disconnect (acc_store, priv->accounts_handler);
231 if (priv->window_list) {
232 GList *iter = priv->window_list;
233 /* unregister pending windows */
235 ModestWindow *window = (ModestWindow *) iter->data;
236 iter = g_list_next (iter);
237 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), window);
239 g_list_free (priv->window_list);
240 priv->window_list = NULL;
243 /* Free the hash table with the handlers */
244 if (priv->destroy_handlers) {
245 g_hash_table_destroy (priv->destroy_handlers);
246 priv->destroy_handlers = NULL;
249 if (priv->viewer_handlers) {
250 g_hash_table_destroy (priv->viewer_handlers);
251 priv->viewer_handlers = NULL;
254 modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids);
255 priv->modal_handler_uids = NULL;
257 if (priv->modal_windows) {
258 g_mutex_lock (priv->queue_lock);
259 g_queue_free (priv->modal_windows);
260 priv->modal_windows = NULL;
261 g_mutex_unlock (priv->queue_lock);
263 g_mutex_free (priv->queue_lock);
265 G_OBJECT_CLASS(parent_class)->finalize (obj);
269 modest_hildon2_window_mgr_new (void)
271 return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_HILDON2_WINDOW_MGR, NULL));
275 modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self)
277 ModestHildon2WindowMgrPrivate *priv = NULL;
278 gboolean ret_value = FALSE;
280 HildonWindowStack *stack;
281 gboolean failed = FALSE;
283 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
284 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
286 stack = hildon_window_stack_get_default ();
288 while ((window = hildon_window_stack_peek (stack)) != NULL) {
289 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &ret_value);
290 if (ret_value == TRUE) {
300 compare_msguids (ModestWindow *win,
303 const gchar *msg_uid;
305 if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win)))
308 /* Get message uid from msg window */
309 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
310 msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win));
311 if (msg_uid && uid &&!strcmp (msg_uid, uid))
314 msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
317 if (msg_uid && uid &&!strcmp (msg_uid, uid))
324 compare_headers (ModestWindow *win,
327 TnyHeader *my_header;
330 if (!MODEST_IS_MSG_VIEW_WINDOW (win))
333 /* Get message uid from msg window */
334 my_header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
336 if (my_header == header)
338 g_object_unref (my_header);
345 modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
348 ModestHildon2WindowMgrPrivate *priv = NULL;
350 gboolean has_header, has_window = FALSE;
353 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
354 g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
356 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
358 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_header (self, header, win);
360 uid = modest_tny_folder_get_header_unique_id (header);
362 item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids);
366 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
367 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
368 g_debug ("not a valid window!");
370 g_debug ("found a window");
371 *win = MODEST_WINDOW (item->data);
377 return has_header || has_window;
381 modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
384 ModestHildon2WindowMgrPrivate *priv = NULL;
385 gboolean has_header, has_window = FALSE;
388 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
389 g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
391 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
393 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_message_uid (self, msg_uid, win);
395 item = g_list_find_custom (priv->window_list, msg_uid, (GCompareFunc) compare_msguids);
399 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
400 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
401 g_debug ("not a valid window!");
403 g_debug ("found a window");
404 *win = MODEST_WINDOW (item->data);
409 return has_header || has_window;
413 modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self)
415 ModestHildon2WindowMgrPrivate *priv;
417 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
418 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
420 return g_list_copy (priv->window_list);
424 modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
425 ModestWindow *window,
426 ModestWindow *parent)
429 ModestHildon2WindowMgrPrivate *priv;
431 HildonWindowStack *stack;
432 gboolean nested_msg = FALSE;
433 ModestWindow *current_top;
435 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
436 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
438 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
440 /* Try to close active modal dialogs */
441 if (modest_window_mgr_get_num_windows (self) &&
442 !_modest_window_mgr_close_active_modals (self))
445 stack = hildon_window_stack_get_default ();
446 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
448 win = g_list_find (priv->window_list, window);
450 /* this is for the case we want to register the window
451 and it was already registered */
452 gtk_window_present (GTK_WINDOW (window));
456 /* Do not allow standalone editors or standalone viewers */
458 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
459 MODEST_IS_MSG_EDIT_WINDOW (window)))
460 modest_window_mgr_show_initial_window (self);
462 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
466 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
468 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
471 uid = modest_tny_folder_get_header_unique_id (header);
472 /* Embedded messages do not have uid */
474 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
475 g_debug ("%s found another view window showing the same header", __FUNCTION__);
477 g_object_unref (header);
482 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
483 g_debug ("%s found another view window showing the same header", __FUNCTION__);
484 g_object_unref (header);
489 g_object_unref (header);
492 /* Do not go backwards */
493 if ((MODEST_IS_MSG_VIEW_WINDOW (current_top) ||
494 MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
495 MODEST_IS_HEADER_WINDOW (current_top)) &&
496 (MODEST_IS_FOLDER_WINDOW (window) ||
497 MODEST_IS_ACCOUNTS_WINDOW (window) ||
498 MODEST_IS_MAILBOXES_WINDOW (window))) {
499 gtk_window_present (GTK_WINDOW (current_top));
503 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_FOLDER_WINDOW (window)) {
506 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
509 gtk_window_present (GTK_WINDOW (current_top));
512 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
515 if (MODEST_IS_MAILBOXES_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
516 gtk_window_present (GTK_WINDOW (current_top));
520 /* Mailboxes window can not replace folder windows */
521 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
522 gtk_window_present (GTK_WINDOW (current_top));
526 /* Trying to open a folders window and a mailboxes window at
527 the same time from the accounts window is not allowed */
528 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
529 MODEST_IS_FOLDER_WINDOW (window) &&
530 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
531 gtk_window_present (GTK_WINDOW (window));
535 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
536 g_debug ("Trying to register a second header window is not allowed");
537 gtk_window_present (GTK_WINDOW (current_top));
541 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
544 /* Add to list. Keep a reference to the window */
545 g_object_ref (window);
546 priv->window_list = g_list_prepend (priv->window_list, window);
548 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
549 MODEST_IS_MSG_VIEW_WINDOW (parent);
551 /* Close views if they're being shown. Nevertheless we must
552 allow nested messages */
554 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
555 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
558 /* If the current view has modal dialogs then
559 we fail to register the new view */
560 if ((current_top != NULL) &&
561 window_has_modals (MODEST_WINDOW (current_top))) {
562 /* Window on top but it has opened dialogs */
566 /* Close the current view */
567 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
569 /* Cancelled closing top window, then we fail to register */
574 /* Listen to object destruction */
575 handler_id = g_malloc0 (sizeof (gint));
576 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
577 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
579 /* Show toolbar always */
580 modest_window_show_toolbar (window, TRUE);
584 /* Add to list. Keep a reference to the window */
585 priv->window_list = g_list_remove (priv->window_list, window);
586 g_object_unref (window);
587 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
589 gtk_window_present (GTK_WINDOW (current_top));
594 cancel_window_operations (ModestWindow *window)
596 GSList* pending_ops = NULL;
598 /* cancel open and receive operations */
599 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
601 while (pending_ops != NULL) {
602 ModestMailOperationTypeOperation type;
603 GSList* tmp_list = NULL;
605 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
606 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
607 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
608 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
609 modest_mail_operation_cancel (pending_ops->data);
611 g_object_unref (G_OBJECT (pending_ops->data));
612 tmp_list = pending_ops;
613 pending_ops = g_slist_next (pending_ops);
614 g_slist_free_1 (tmp_list);
619 window_has_modals (ModestWindow *window)
623 gboolean retvalue = FALSE;
625 /* First we fetch all toplevels */
626 toplevels = gtk_window_list_toplevels ();
627 for (node = toplevels; node != NULL; node = g_list_next (node)) {
628 if (GTK_IS_WINDOW (node->data) &&
629 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (window) &&
630 GTK_WIDGET_VISIBLE (node->data)) {
635 g_list_free (toplevels);
640 on_window_destroy (ModestWindow *window,
642 ModestHildon2WindowMgr *self)
644 gboolean no_propagate = FALSE;
646 /* Do not close the window if it has modals on top */
647 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
650 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
651 gboolean sent = FALSE;
652 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
653 /* Save currently edited message to Drafts if it was not sent */
654 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
655 ModestMsgEditWindow *edit_window;
658 edit_window = MODEST_MSG_EDIT_WINDOW (window);
659 data = modest_msg_edit_window_get_msg_data (edit_window);
663 guint64 parts_size, available_size, expected_size;
665 available_size = modest_utils_get_available_space (NULL);
666 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
667 expected_size = modest_tny_msg_estimate_size (data->plain_body,
671 modest_msg_edit_window_free_msg_data (edit_window, data);
674 /* If there is not enough space
675 available for saving the message
676 then show an error and close the
677 window without saving */
678 if (expected_size >= available_size) {
679 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
680 _("mail_in_ui_save_error"),
683 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
687 g_warning ("Edit window without message data. This is probably a bug");
692 /* Unregister window */
693 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
694 no_propagate = FALSE;
700 modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
701 ModestWindow *window)
704 ModestHildon2WindowMgrPrivate *priv;
705 gulong *tmp, handler_id;
708 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
709 g_return_if_fail (MODEST_IS_WINDOW (window));
711 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
713 win = g_list_find (priv->window_list, window);
715 g_debug ("Trying to unregister a window that has not being registered yet");
719 /* Remove the viewer window handler from the hash table. The
720 HashTable could not exist if the main window was closed
721 when there were other windows remaining */
722 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
723 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
724 /* If the viewer was created without a main window
725 (for example when opening a message through D-Bus
726 the viewer handlers was not registered */
728 g_signal_handler_disconnect (window, *tmp);
729 g_hash_table_remove (priv->viewer_handlers, window);
733 /* Remove from list & hash table */
734 priv->window_list = g_list_remove_link (priv->window_list, win);
735 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
738 g_hash_table_remove (priv->destroy_handlers, window);
740 /* cancel open and receive operations */
741 cancel_window_operations (window);
743 /* Disconnect the "window-state-event" handler, we won't need it anymore */
744 if (priv->window_state_uids) {
745 priv->window_state_uids =
746 modest_signal_mgr_disconnect (priv->window_state_uids,
748 "notify::is-topmost");
751 /* Disconnect the "delete-event" handler, we won't need it anymore */
752 g_signal_handler_disconnect (window, handler_id);
754 /* Destroy the window */
755 g_object_unref (win->data);
758 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
760 /* We have to get the number of windows here in order not to
761 emit the signal too many times */
762 num_windows = modest_window_mgr_get_num_windows (self);
764 /* If there are no more windows registered emit the signal */
765 if (num_windows == 0)
766 g_signal_emit_by_name (self, "window-list-empty");
771 modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
774 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
780 modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
786 modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
788 gboolean show_toolbars,
791 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
797 look_for_transient (gconstpointer a,
800 GtkWindow *win, *child;
805 child = (GtkWindow *) b;
806 win = (GtkWindow *) a;
808 if ((gtk_window_get_transient_for (win) == child) &&
809 GTK_WIDGET_VISIBLE (win))
816 modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self)
818 ModestHildon2WindowMgrPrivate *priv;
819 GList *toplevel_list;
820 GtkWidget *current_top, *toplevel;
821 HildonWindowStack *stack;
823 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
824 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
826 /* Get current top */
827 stack = hildon_window_stack_get_default ();
828 current_top = hildon_window_stack_peek (stack);
829 toplevel = current_top;
830 toplevel_list = gtk_window_list_toplevels ();
835 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
837 toplevel = (GtkWidget *) parent_link->data;
842 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
843 return (GtkWindow *) toplevel;
850 modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
854 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
855 g_return_if_fail (GTK_IS_WINDOW (window));
857 gtk_window_set_modal (window, TRUE);
858 gtk_window_set_transient_for (window, parent);
859 gtk_window_set_destroy_with_parent (window, TRUE);
863 close_all_but_first (gpointer data)
867 HildonWindowStack *stack;
869 stack = hildon_window_stack_get_default ();
870 g_return_if_fail (stack);
872 num_windows = hildon_window_stack_size (stack);
874 for (i = 0; i < (num_windows - 1); i++) {
875 GtkWidget *current_top;
878 current_top = hildon_window_stack_peek (stack);
879 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
884 on_idle_close_all_but_first (gpointer data)
886 gdk_threads_enter ();
887 close_all_but_first (data);
888 gdk_threads_leave ();
894 on_account_removed (TnyAccountStore *acc_store,
898 HildonWindowStack *stack;
899 ModestWindow *current_top;
901 /* Ignore transport account removals */
902 if (TNY_IS_TRANSPORT_ACCOUNT (account))
905 stack = hildon_window_stack_get_default ();
906 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
908 /* if we're showing the header view of the currently deleted
909 account, or the outbox and we deleted the last account,
910 then close the window */
912 (MODEST_IS_HEADER_WINDOW (current_top) ||
913 MODEST_IS_FOLDER_WINDOW (current_top))) {
914 const gchar *acc_name;
916 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
918 /* We emit it in an idle, because sometimes this
919 function could called when the account settings
920 dialog is about to close but still there. That
921 modal dialog would otherwise, prevent the
922 windows from being closed */
923 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
924 g_idle_add (on_idle_close_all_but_first, NULL);
928 static ModestWindow *
929 modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self)
931 ModestWindow *initial_window = NULL;
932 ModestHildon2WindowMgrPrivate *priv;
934 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
936 /* Connect to the account store "account-removed" signal". We
937 do this here because in the init the singletons are still
938 not initialized properly */
939 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
940 priv->accounts_handler)) {
941 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
943 G_CALLBACK (on_account_removed),
947 /* Return accounts window */
948 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
949 modest_window_mgr_register_window (self, initial_window, NULL);
951 return initial_window;
955 static ModestWindow *
956 modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self)
958 HildonWindowStack *stack;
959 stack = hildon_window_stack_get_default ();
960 return (ModestWindow *) hildon_window_stack_peek (stack);
964 find_folder_window (gconstpointer a,
967 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
971 modest_hildon2_window_mgr_get_folder_window (ModestHildon2WindowMgr *self)
973 ModestHildon2WindowMgrPrivate *priv;
976 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
978 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
980 window = g_list_find_custom (priv->window_list,
984 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
988 modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self)
990 ModestHildon2WindowMgrPrivate *priv = NULL;
992 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
994 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
996 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
1000 modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self)
1002 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
1004 modest_accounts_window_pre_create ();
1006 MODEST_WINDOW_MGR_CLASS(parent_class)->create_caches (self);
1010 osso_display_event_cb (osso_display_state_t state,
1013 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (data);
1015 priv->display_state = state;
1017 /* Stop blinking if the screen becomes on */
1018 if (priv->display_state == OSSO_DISPLAY_ON)
1019 modest_platform_remove_new_mail_notifications (TRUE);
1023 modest_hildon2_window_mgr_close_all_but_initial (ModestWindowMgr *self)
1027 /* Exit if there are no windows */
1028 if (!modest_window_mgr_get_num_windows (self)) {
1029 g_warning ("%s: unable to close, there are no windows", __FUNCTION__);
1033 /* Close active modals */
1034 if (!_modest_window_mgr_close_active_modals (self)) {
1035 g_debug ("%s: unable to close some dialogs", __FUNCTION__);
1039 /* Close all but first */
1040 top = modest_window_mgr_get_current_top (self);
1041 if (!MODEST_IS_ACCOUNTS_WINDOW (top))
1042 close_all_but_first (NULL);
1044 /* If some cannot be closed return */
1045 top = modest_window_mgr_get_current_top (self);
1046 if (!MODEST_IS_ACCOUNTS_WINDOW (top)) {
1047 g_debug ("%s: could not close some windows", __FUNCTION__);