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-conf.h"
39 #include "modest-defs.h"
40 #include "modest-signal-mgr.h"
41 #include "modest-runtime.h"
42 #include "modest-platform.h"
43 #include "modest-ui-actions.h"
44 #include "modest-debug.h"
45 #include "modest-tny-folder.h"
46 #include "modest-folder-window.h"
47 #include "modest-accounts-window.h"
48 #include "modest-maemo-utils.h"
49 #include "modest-utils.h"
50 #include "modest-tny-msg.h"
51 #include "modest-tny-account.h"
52 #include <tny-merge-folder.h>
54 /* 'private'/'protected' functions */
55 static void modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass);
56 static void modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj);
57 static void modest_hildon2_window_mgr_finalize (GObject *obj);
59 static gboolean on_window_destroy (ModestWindow *window,
61 ModestHildon2WindowMgr *self);
63 static gboolean modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
65 ModestWindow *parent);
66 static void modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
67 ModestWindow *window);
68 static void modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
70 static gboolean modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self);
71 static void modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
73 gboolean show_toolbars,
75 static GtkWindow *modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self);
76 static void modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
79 static gboolean modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self,
82 static gboolean modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self,
85 static GList *modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self);
86 static gboolean modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self);
87 static gboolean window_has_modals (ModestWindow *window);
88 static ModestWindow *modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self);
89 static ModestWindow *modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self);
90 static gboolean modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self);
91 static void modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self);
92 static void osso_display_event_cb (osso_display_state_t state,
94 static void on_account_removed (TnyAccountStore *acc_store,
98 typedef struct _ModestHildon2WindowMgrPrivate ModestHildon2WindowMgrPrivate;
99 struct _ModestHildon2WindowMgrPrivate {
102 GQueue *modal_windows;
104 gboolean fullscreen_mode;
106 GHashTable *destroy_handlers;
107 GHashTable *viewer_handlers;
108 GSList *window_state_uids;
112 GSList *modal_handler_uids;
113 ModestWindow *current_top;
115 gulong accounts_handler;
118 osso_display_state_t display_state;
120 #define MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
121 MODEST_TYPE_HILDON2_WINDOW_MGR, \
122 ModestHildon2WindowMgrPrivate))
124 static GObjectClass *parent_class = NULL;
127 modest_hildon2_window_mgr_get_type (void)
129 static GType my_type = 0;
131 static const GTypeInfo my_info = {
132 sizeof(ModestHildon2WindowMgrClass),
133 NULL, /* base init */
134 NULL, /* base finalize */
135 (GClassInitFunc) modest_hildon2_window_mgr_class_init,
136 NULL, /* class finalize */
137 NULL, /* class data */
138 sizeof(ModestHildon2WindowMgr),
140 (GInstanceInitFunc) modest_hildon2_window_mgr_instance_init,
143 my_type = g_type_register_static (MODEST_TYPE_WINDOW_MGR,
144 "ModestHildon2WindowMgr",
151 modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass)
153 GObjectClass *gobject_class;
154 ModestWindowMgrClass *mgr_class;
156 gobject_class = (GObjectClass*) klass;
157 mgr_class = (ModestWindowMgrClass *) klass;
159 parent_class = g_type_class_peek_parent (klass);
160 gobject_class->finalize = modest_hildon2_window_mgr_finalize;
161 mgr_class->register_window = modest_hildon2_window_mgr_register_window;
162 mgr_class->unregister_window = modest_hildon2_window_mgr_unregister_window;
163 mgr_class->set_fullscreen_mode = modest_hildon2_window_mgr_set_fullscreen_mode;
164 mgr_class->get_fullscreen_mode = modest_hildon2_window_mgr_get_fullscreen_mode;
165 mgr_class->show_toolbars = modest_hildon2_window_mgr_show_toolbars;
166 mgr_class->get_modal = modest_hildon2_window_mgr_get_modal;
167 mgr_class->set_modal = modest_hildon2_window_mgr_set_modal;
168 mgr_class->find_registered_header = modest_hildon2_window_mgr_find_registered_header;
169 mgr_class->find_registered_message_uid = modest_hildon2_window_mgr_find_registered_message_uid;
170 mgr_class->get_window_list = modest_hildon2_window_mgr_get_window_list;
171 mgr_class->close_all_windows = modest_hildon2_window_mgr_close_all_windows;
172 mgr_class->show_initial_window = modest_hildon2_window_mgr_show_initial_window;
173 mgr_class->get_current_top = modest_hildon2_window_mgr_get_current_top;
174 mgr_class->screen_is_on = modest_hildon2_window_mgr_screen_is_on;
175 mgr_class->create_caches = modest_hildon2_window_mgr_create_caches;
177 g_type_class_add_private (gobject_class, sizeof(ModestHildon2WindowMgrPrivate));
182 modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj)
184 ModestHildon2WindowMgrPrivate *priv;
186 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
187 priv->window_list = NULL;
188 priv->fullscreen_mode = FALSE;
189 priv->window_state_uids = NULL;
191 priv->modal_windows = g_queue_new ();
192 priv->queue_lock = g_mutex_new ();
194 /* Could not initialize it from gconf, singletons are not
196 priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
197 priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
199 priv->closing_time = 0;
201 priv->modal_handler_uids = NULL;
202 priv->display_state = OSSO_DISPLAY_ON;
204 /* Listen for changes in the screen, we don't want to show a
205 led pattern when the display is on for example */
206 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
207 osso_display_event_cb,
213 modest_hildon2_window_mgr_finalize (GObject *obj)
215 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
216 ModestTnyAccountStore *acc_store;
218 modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids);
219 priv->window_state_uids = NULL;
221 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
224 acc_store = modest_runtime_get_account_store ();
225 if (acc_store && g_signal_handler_is_connected (acc_store, priv->accounts_handler))
226 g_signal_handler_disconnect (acc_store, priv->accounts_handler);
228 if (priv->window_list) {
229 GList *iter = priv->window_list;
230 /* unregister pending windows */
232 ModestWindow *window = (ModestWindow *) iter->data;
233 iter = g_list_next (iter);
234 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), window);
236 g_list_free (priv->window_list);
237 priv->window_list = NULL;
240 /* Free the hash table with the handlers */
241 if (priv->destroy_handlers) {
242 g_hash_table_destroy (priv->destroy_handlers);
243 priv->destroy_handlers = NULL;
246 if (priv->viewer_handlers) {
247 g_hash_table_destroy (priv->viewer_handlers);
248 priv->viewer_handlers = NULL;
251 modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids);
252 priv->modal_handler_uids = NULL;
254 if (priv->modal_windows) {
255 g_mutex_lock (priv->queue_lock);
256 g_queue_free (priv->modal_windows);
257 priv->modal_windows = NULL;
258 g_mutex_unlock (priv->queue_lock);
260 g_mutex_free (priv->queue_lock);
262 G_OBJECT_CLASS(parent_class)->finalize (obj);
266 modest_hildon2_window_mgr_new (void)
268 return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_HILDON2_WINDOW_MGR, NULL));
272 modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self)
274 ModestHildon2WindowMgrPrivate *priv = NULL;
275 gboolean ret_value = FALSE;
277 HildonWindowStack *stack;
278 gboolean failed = FALSE;
280 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
281 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
283 stack = hildon_window_stack_get_default ();
285 while ((window = hildon_window_stack_peek (stack)) != NULL) {
286 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &ret_value);
287 if (ret_value == TRUE) {
297 compare_msguids (ModestWindow *win,
300 const gchar *msg_uid;
302 if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win)))
305 /* Get message uid from msg window */
306 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
307 msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win));
308 if (msg_uid && uid &&!strcmp (msg_uid, uid))
311 msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
314 if (msg_uid && uid &&!strcmp (msg_uid, uid))
321 compare_headers (ModestWindow *win,
324 TnyHeader *my_header;
327 if (!MODEST_IS_MSG_VIEW_WINDOW (win))
330 /* Get message uid from msg window */
331 my_header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
333 if (my_header == header)
335 g_object_unref (my_header);
342 modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
345 ModestHildon2WindowMgrPrivate *priv = NULL;
347 gboolean has_header, has_window = FALSE;
350 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
351 g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
353 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
355 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_header (self, header, win);
357 uid = modest_tny_folder_get_header_unique_id (header);
359 item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids);
363 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
364 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
365 g_debug ("not a valid window!");
367 g_debug ("found a window");
368 *win = MODEST_WINDOW (item->data);
374 return has_header || has_window;
378 modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
381 ModestHildon2WindowMgrPrivate *priv = NULL;
382 gboolean has_header, has_window = FALSE;
385 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
386 g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
388 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
390 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_message_uid (self, msg_uid, win);
392 item = g_list_find_custom (priv->window_list, msg_uid, (GCompareFunc) compare_msguids);
396 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
397 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
398 g_debug ("not a valid window!");
400 g_debug ("found a window");
401 *win = MODEST_WINDOW (item->data);
406 return has_header || has_window;
410 modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self)
412 ModestHildon2WindowMgrPrivate *priv;
414 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
415 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
417 return g_list_copy (priv->window_list);
421 modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
422 ModestWindow *window,
423 ModestWindow *parent)
426 ModestHildon2WindowMgrPrivate *priv;
428 HildonWindowStack *stack;
429 gboolean nested_msg = FALSE;
430 ModestWindow *current_top;
433 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
434 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
436 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
438 /* Check that there is no active modal dialog */
439 modal = (GtkWidget *) modest_window_mgr_get_modal (self);
440 while (modal && GTK_IS_DIALOG (modal)) {
443 /* If it's a hildon note then don't try to close it as
444 this is the default behaviour of WM, delete event
445 is not issued for this kind of notes as we want the
446 user to always click on a button */
447 if (HILDON_IS_NOTE (modal)) {
448 gtk_window_present (GTK_WINDOW (modal));
453 parent = (GtkWidget *) gtk_window_get_transient_for (GTK_WINDOW (modal));
455 /* Try to close it */
456 gtk_dialog_response (GTK_DIALOG (modal), GTK_RESPONSE_DELETE_EVENT);
458 /* Maybe the dialog was not closed, because a close
459 confirmation dialog for example. Then ignore the
461 if (GTK_IS_WINDOW (modal)) {
462 gtk_window_present (GTK_WINDOW (modal));
470 stack = hildon_window_stack_get_default ();
471 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
473 win = g_list_find (priv->window_list, window);
475 /* this is for the case we want to register the window
476 and it was already registered */
477 gtk_window_present (GTK_WINDOW (window));
481 /* Do not allow standalone editors or standalone viewers */
483 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
484 MODEST_IS_MSG_EDIT_WINDOW (window)))
485 modest_window_mgr_show_initial_window (self);
487 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
491 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
493 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
496 uid = modest_tny_folder_get_header_unique_id (header);
497 /* Embedded messages do not have uid */
499 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
500 g_debug ("%s found another view window showing the same header", __FUNCTION__);
502 g_object_unref (header);
507 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
508 g_debug ("%s found another view window showing the same header", __FUNCTION__);
509 g_object_unref (header);
514 g_object_unref (header);
517 /* Do not go backwards */
518 if ((MODEST_IS_MSG_VIEW_WINDOW (current_top) ||
519 MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
520 MODEST_IS_HEADER_WINDOW (current_top)) &&
521 (MODEST_IS_FOLDER_WINDOW (window) ||
522 MODEST_IS_ACCOUNTS_WINDOW (window) ||
523 MODEST_IS_MAILBOXES_WINDOW (window))) {
524 gtk_window_present (GTK_WINDOW (current_top));
528 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_FOLDER_WINDOW (window)) {
531 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
534 gtk_window_present (GTK_WINDOW (current_top));
537 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
540 if (MODEST_IS_MAILBOXES_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
541 gtk_window_present (GTK_WINDOW (current_top));
545 /* Mailboxes window can not replace folder windows */
546 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
547 gtk_window_present (GTK_WINDOW (current_top));
551 /* Trying to open a folders window and a mailboxes window at
552 the same time from the accounts window is not allowed */
553 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
554 MODEST_IS_FOLDER_WINDOW (window) &&
555 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
556 gtk_window_present (GTK_WINDOW (window));
560 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
561 g_debug ("Trying to register a second header window is not allowed");
562 gtk_window_present (GTK_WINDOW (current_top));
566 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
569 /* Add to list. Keep a reference to the window */
570 g_object_ref (window);
571 priv->window_list = g_list_prepend (priv->window_list, window);
573 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
574 MODEST_IS_MSG_VIEW_WINDOW (parent);
576 /* Close views if they're being shown. Nevertheless we must
577 allow nested messages */
579 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
580 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
583 /* If the current view has modal dialogs then
584 we fail to register the new view */
585 if ((current_top != NULL) &&
586 window_has_modals (MODEST_WINDOW (current_top))) {
587 /* Window on top but it has opened dialogs */
591 /* Close the current view */
592 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
594 /* Cancelled closing top window, then we fail to register */
599 /* Listen to object destruction */
600 handler_id = g_malloc0 (sizeof (gint));
601 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
602 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
604 /* Show toolbar always */
605 modest_window_show_toolbar (window, TRUE);
609 /* Add to list. Keep a reference to the window */
610 priv->window_list = g_list_remove (priv->window_list, window);
611 g_object_unref (window);
612 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
614 gtk_window_present (GTK_WINDOW (current_top));
619 cancel_window_operations (ModestWindow *window)
621 GSList* pending_ops = NULL;
623 /* cancel open and receive operations */
624 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
626 while (pending_ops != NULL) {
627 ModestMailOperationTypeOperation type;
628 GSList* tmp_list = NULL;
630 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
631 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
632 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
633 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
634 modest_mail_operation_cancel (pending_ops->data);
636 g_object_unref (G_OBJECT (pending_ops->data));
637 tmp_list = pending_ops;
638 pending_ops = g_slist_next (pending_ops);
639 g_slist_free_1 (tmp_list);
644 window_has_modals (ModestWindow *window)
648 gboolean retvalue = FALSE;
650 /* First we fetch all toplevels */
651 toplevels = gtk_window_list_toplevels ();
652 for (node = toplevels; node != NULL; node = g_list_next (node)) {
653 if (GTK_IS_WINDOW (node->data) &&
654 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (window) &&
655 GTK_WIDGET_VISIBLE (node->data)) {
660 g_list_free (toplevels);
665 on_window_destroy (ModestWindow *window,
667 ModestHildon2WindowMgr *self)
669 gboolean no_propagate = FALSE;
671 /* Do not close the window if it has modals on top */
672 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
675 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
676 gboolean sent = FALSE;
677 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
678 /* Save currently edited message to Drafts if it was not sent */
679 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
680 ModestMsgEditWindow *edit_window;
683 edit_window = MODEST_MSG_EDIT_WINDOW (window);
684 data = modest_msg_edit_window_get_msg_data (edit_window);
688 guint64 parts_size, available_size, expected_size;
690 available_size = modest_utils_get_available_space (NULL);
691 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
692 expected_size = modest_tny_msg_estimate_size (data->plain_body,
696 modest_msg_edit_window_free_msg_data (edit_window, data);
699 /* If there is not enough space
700 available for saving the message
701 then show an error and close the
702 window without saving */
703 if (expected_size >= available_size) {
704 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
705 _("mail_in_ui_save_error"),
708 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
712 g_warning ("Edit window without message data. This is probably a bug");
717 /* Unregister window */
718 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
719 no_propagate = FALSE;
725 modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
726 ModestWindow *window)
729 ModestHildon2WindowMgrPrivate *priv;
730 gulong *tmp, handler_id;
733 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
734 g_return_if_fail (MODEST_IS_WINDOW (window));
736 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
738 win = g_list_find (priv->window_list, window);
740 g_debug ("Trying to unregister a window that has not being registered yet");
744 /* Remove the viewer window handler from the hash table. The
745 HashTable could not exist if the main window was closed
746 when there were other windows remaining */
747 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
748 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
749 /* If the viewer was created without a main window
750 (for example when opening a message through D-Bus
751 the viewer handlers was not registered */
753 g_signal_handler_disconnect (window, *tmp);
754 g_hash_table_remove (priv->viewer_handlers, window);
758 /* Remove from list & hash table */
759 priv->window_list = g_list_remove_link (priv->window_list, win);
760 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
763 g_hash_table_remove (priv->destroy_handlers, window);
765 /* cancel open and receive operations */
766 cancel_window_operations (window);
768 /* Disconnect the "window-state-event" handler, we won't need it anymore */
769 if (priv->window_state_uids) {
770 priv->window_state_uids =
771 modest_signal_mgr_disconnect (priv->window_state_uids,
773 "notify::is-topmost");
776 /* Disconnect the "delete-event" handler, we won't need it anymore */
777 g_signal_handler_disconnect (window, handler_id);
779 /* Destroy the window */
780 g_object_unref (win->data);
783 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
785 /* We have to get the number of windows here in order not to
786 emit the signal too many times */
787 num_windows = modest_window_mgr_get_num_windows (self);
789 /* If there are no more windows registered emit the signal */
790 if (num_windows == 0)
791 g_signal_emit_by_name (self, "window-list-empty");
796 modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
799 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
805 modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
811 modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
813 gboolean show_toolbars,
816 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
822 look_for_transient (gconstpointer a,
825 GtkWindow *win, *child;
830 child = (GtkWindow *) b;
831 win = (GtkWindow *) a;
833 if ((gtk_window_get_transient_for (win) == child) &&
834 GTK_WIDGET_VISIBLE (win))
841 modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self)
843 ModestHildon2WindowMgrPrivate *priv;
844 GList *toplevel_list;
845 GtkWidget *current_top, *toplevel;
846 HildonWindowStack *stack;
848 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
849 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
851 /* Get current top */
852 stack = hildon_window_stack_get_default ();
853 current_top = hildon_window_stack_peek (stack);
854 toplevel = current_top;
855 toplevel_list = gtk_window_list_toplevels ();
860 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
862 toplevel = (GtkWidget *) parent_link->data;
867 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
868 return (GtkWindow *) toplevel;
875 modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
879 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
880 g_return_if_fail (GTK_IS_WINDOW (window));
882 gtk_window_set_modal (window, TRUE);
883 gtk_window_set_transient_for (window, parent);
884 gtk_window_set_destroy_with_parent (window, TRUE);
888 on_idle_close_all_but_first (gpointer data)
892 HildonWindowStack *stack;
894 stack = hildon_window_stack_get_default ();
895 g_return_val_if_fail (stack, FALSE);
897 num_windows = hildon_window_stack_size (stack);
899 for (i = 0; i < (num_windows - 1); i++) {
900 GtkWidget *current_top;
903 current_top = hildon_window_stack_peek (stack);
904 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
910 on_account_removed (TnyAccountStore *acc_store,
914 HildonWindowStack *stack;
915 ModestWindow *current_top;
917 /* Ignore transport account removals */
918 if (TNY_IS_TRANSPORT_ACCOUNT (account))
921 stack = hildon_window_stack_get_default ();
922 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
924 /* if we're showing the header view of the currently deleted
925 account, or the outbox and we deleted the last account,
926 then close the window */
928 (MODEST_IS_HEADER_WINDOW (current_top) ||
929 MODEST_IS_FOLDER_WINDOW (current_top))) {
930 const gchar *acc_name;
932 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
934 /* We emit it in an idle, because sometimes this
935 function could called when the account settings
936 dialog is about to close but still there. That
937 modal dialog would otherwise, prevent the
938 windows from being closed */
939 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
940 g_idle_add (on_idle_close_all_but_first, NULL);
944 static ModestWindow *
945 modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self)
947 ModestWindow *initial_window = NULL;
948 ModestHildon2WindowMgrPrivate *priv;
950 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
952 /* Connect to the account store "account-removed" signal". We
953 do this here because in the init the singletons are still
954 not initialized properly */
955 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
956 priv->accounts_handler)) {
957 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
959 G_CALLBACK (on_account_removed),
963 /* Return accounts window */
964 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
965 modest_window_mgr_register_window (self, initial_window, NULL);
967 return initial_window;
971 static ModestWindow *
972 modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self)
974 HildonWindowStack *stack;
975 stack = hildon_window_stack_get_default ();
976 return (ModestWindow *) hildon_window_stack_peek (stack);
980 find_folder_window (gconstpointer a,
983 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
987 modest_hildon2_window_mgr_get_folder_window (ModestHildon2WindowMgr *self)
989 ModestHildon2WindowMgrPrivate *priv;
992 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
994 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
996 window = g_list_find_custom (priv->window_list,
1000 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
1004 modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self)
1006 ModestHildon2WindowMgrPrivate *priv = NULL;
1008 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
1010 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1012 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
1016 modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self)
1018 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
1020 modest_accounts_window_pre_create ();
1022 MODEST_WINDOW_MGR_CLASS(parent_class)->create_caches (self);
1027 osso_display_event_cb (osso_display_state_t state,
1030 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (data);
1032 priv->display_state = state;
1034 /* Stop blinking if the screen becomes on */
1035 if (priv->display_state == OSSO_DISPLAY_ON)
1036 modest_platform_remove_new_mail_notifications (TRUE);