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-window-mgr-priv.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 modest_hildon2_window_mgr_close_all_but_initial (ModestWindowMgr *self);
88 static gboolean window_has_modals (ModestWindow *window);
89 static ModestWindow *modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self);
90 static ModestWindow *modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self);
91 static gboolean modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self);
92 static void modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self);
93 static void osso_display_event_cb (osso_display_state_t state,
95 static void on_account_removed (TnyAccountStore *acc_store,
98 static ModestWindow *modest_hildon2_window_mgr_get_folder_window (ModestWindowMgr *self);
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;
179 mgr_class->get_folder_window = modest_hildon2_window_mgr_get_folder_window;
181 g_type_class_add_private (gobject_class, sizeof(ModestHildon2WindowMgrPrivate));
186 modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj)
188 ModestHildon2WindowMgrPrivate *priv;
190 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
191 priv->window_list = NULL;
192 priv->fullscreen_mode = FALSE;
193 priv->window_state_uids = NULL;
195 priv->modal_windows = g_queue_new ();
196 priv->queue_lock = g_mutex_new ();
198 /* Could not initialize it from gconf, singletons are not
200 priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
201 priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
203 priv->closing_time = 0;
205 priv->modal_handler_uids = NULL;
206 priv->display_state = OSSO_DISPLAY_ON;
208 /* Listen for changes in the screen, we don't want to show a
209 led pattern when the display is on for example */
210 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
211 osso_display_event_cb,
217 modest_hildon2_window_mgr_finalize (GObject *obj)
219 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
220 ModestTnyAccountStore *acc_store;
222 modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids);
223 priv->window_state_uids = NULL;
225 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
228 acc_store = modest_runtime_get_account_store ();
229 if (acc_store && g_signal_handler_is_connected (acc_store, priv->accounts_handler))
230 g_signal_handler_disconnect (acc_store, priv->accounts_handler);
232 if (priv->window_list) {
233 GList *iter = priv->window_list;
234 /* unregister pending windows */
236 ModestWindow *window = (ModestWindow *) iter->data;
237 iter = g_list_next (iter);
238 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), window);
240 g_list_free (priv->window_list);
241 priv->window_list = NULL;
244 /* Free the hash table with the handlers */
245 if (priv->destroy_handlers) {
246 g_hash_table_destroy (priv->destroy_handlers);
247 priv->destroy_handlers = NULL;
250 if (priv->viewer_handlers) {
251 g_hash_table_destroy (priv->viewer_handlers);
252 priv->viewer_handlers = NULL;
255 modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids);
256 priv->modal_handler_uids = NULL;
258 if (priv->modal_windows) {
259 g_mutex_lock (priv->queue_lock);
260 g_queue_free (priv->modal_windows);
261 priv->modal_windows = NULL;
262 g_mutex_unlock (priv->queue_lock);
264 g_mutex_free (priv->queue_lock);
266 G_OBJECT_CLASS(parent_class)->finalize (obj);
270 modest_hildon2_window_mgr_new (void)
272 return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_HILDON2_WINDOW_MGR, NULL));
276 modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self)
278 ModestHildon2WindowMgrPrivate *priv = NULL;
279 gboolean ret_value = FALSE;
281 HildonWindowStack *stack;
282 gboolean failed = FALSE;
284 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
285 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
287 stack = hildon_window_stack_get_default ();
289 while ((window = hildon_window_stack_peek (stack)) != NULL) {
290 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &ret_value);
291 if (ret_value == TRUE) {
301 compare_msguids (ModestWindow *win,
304 const gchar *msg_uid;
306 if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win)))
309 /* Get message uid from msg window */
310 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
311 msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win));
312 if (msg_uid && uid &&!strcmp (msg_uid, uid))
315 msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
318 if (msg_uid && uid &&!strcmp (msg_uid, uid))
325 compare_headers (ModestWindow *win,
328 TnyHeader *my_header;
331 if (!MODEST_IS_MSG_VIEW_WINDOW (win))
334 /* Get message uid from msg window */
335 my_header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
337 if (my_header == header)
339 g_object_unref (my_header);
346 modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
349 ModestHildon2WindowMgrPrivate *priv = NULL;
351 gboolean has_header, has_window = FALSE;
354 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
355 g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
357 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
359 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_header (self, header, win);
361 uid = modest_tny_folder_get_header_unique_id (header);
363 item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids);
367 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
368 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
369 g_debug ("not a valid window!");
371 g_debug ("found a window");
372 *win = MODEST_WINDOW (item->data);
378 return has_header || has_window;
382 modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
385 ModestHildon2WindowMgrPrivate *priv = NULL;
386 gboolean has_header, has_window = FALSE;
389 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
390 g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
392 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
394 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_message_uid (self, msg_uid, win);
396 item = g_list_find_custom (priv->window_list, msg_uid, (GCompareFunc) compare_msguids);
400 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
401 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
402 g_debug ("not a valid window!");
404 g_debug ("found a window");
405 *win = MODEST_WINDOW (item->data);
410 return has_header || has_window;
414 modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self)
416 ModestHildon2WindowMgrPrivate *priv;
418 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
419 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
421 return g_list_copy (priv->window_list);
425 modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
426 ModestWindow *window,
427 ModestWindow *parent)
430 ModestHildon2WindowMgrPrivate *priv;
432 HildonWindowStack *stack;
433 gboolean nested_msg = FALSE;
434 ModestWindow *current_top;
435 const gchar *acc_name;
437 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
438 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
440 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
442 /* Try to close active modal dialogs */
443 if (modest_window_mgr_get_num_windows (self) &&
444 !_modest_window_mgr_close_active_modals (self))
447 stack = hildon_window_stack_get_default ();
448 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
450 win = g_list_find (priv->window_list, window);
452 /* this is for the case we want to register the window
453 and it was already registered */
454 gtk_window_present (GTK_WINDOW (window));
458 /* Do not allow standalone editors or standalone viewers */
460 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
461 MODEST_IS_MSG_EDIT_WINDOW (window)))
462 modest_window_mgr_show_initial_window (self);
464 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
468 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
470 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
473 uid = modest_tny_folder_get_header_unique_id (header);
474 /* Embedded messages do not have uid */
476 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
477 g_debug ("%s found another view window showing the same header", __FUNCTION__);
479 g_object_unref (header);
484 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
485 g_debug ("%s found another view window showing the same header", __FUNCTION__);
486 g_object_unref (header);
491 g_object_unref (header);
494 /* Do not go backwards */
495 if ((MODEST_IS_MSG_VIEW_WINDOW (current_top) ||
496 MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
497 MODEST_IS_HEADER_WINDOW (current_top)) &&
498 (MODEST_IS_FOLDER_WINDOW (window) ||
499 MODEST_IS_ACCOUNTS_WINDOW (window) ||
500 MODEST_IS_MAILBOXES_WINDOW (window))) {
501 gtk_window_present (GTK_WINDOW (current_top));
505 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_FOLDER_WINDOW (window)) {
508 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
511 gtk_window_present (GTK_WINDOW (current_top));
514 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
517 if (MODEST_IS_MAILBOXES_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
518 gtk_window_present (GTK_WINDOW (current_top));
522 /* Mailboxes window can not replace folder windows */
523 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
524 gtk_window_present (GTK_WINDOW (current_top));
528 /* Trying to open a folders window and a mailboxes window at
529 the same time from the accounts window is not allowed */
530 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
531 MODEST_IS_FOLDER_WINDOW (window) &&
532 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
533 gtk_window_present (GTK_WINDOW (window));
537 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
538 g_debug ("Trying to register a second header window is not allowed");
539 gtk_window_present (GTK_WINDOW (current_top));
543 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
546 /* Add to list. Keep a reference to the window */
547 g_object_ref (window);
548 priv->window_list = g_list_prepend (priv->window_list, window);
550 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
551 MODEST_IS_MSG_VIEW_WINDOW (parent);
553 /* Close views if they're being shown. Nevertheless we must
554 allow nested messages */
556 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
557 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
560 /* If the current view has modal dialogs then
561 we fail to register the new view */
562 if ((current_top != NULL) &&
563 window_has_modals (MODEST_WINDOW (current_top))) {
564 /* Window on top but it has opened dialogs */
568 /* Close the current view */
569 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
571 /* Cancelled closing top window, then we fail to register */
576 /* Listen to object destruction */
577 handler_id = g_malloc0 (sizeof (gint));
578 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
579 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
581 if (!MODEST_IS_MSG_EDIT_WINDOW (window) &&
582 !MODEST_IS_ACCOUNTS_WINDOW (window)) {
583 acc_name = modest_window_get_active_account (window);
586 modest_platform_remove_new_mail_notifications (FALSE, acc_name);
590 /* Show toolbar always */
591 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
592 gboolean show_toolbar;
593 show_toolbar = modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL);
594 modest_window_show_toolbar (window, show_toolbar);
596 modest_window_show_toolbar (window, TRUE);
601 /* Add to list. Keep a reference to the window */
602 priv->window_list = g_list_remove (priv->window_list, window);
603 g_object_unref (window);
604 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
606 gtk_window_present (GTK_WINDOW (current_top));
611 cancel_window_operations (ModestWindow *window)
613 GSList* pending_ops = NULL;
615 /* cancel open and receive operations */
616 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
618 while (pending_ops != NULL) {
619 ModestMailOperationTypeOperation type;
620 GSList* tmp_list = NULL;
622 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
623 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
624 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
625 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
626 modest_mail_operation_cancel (pending_ops->data);
628 g_object_unref (G_OBJECT (pending_ops->data));
629 tmp_list = pending_ops;
630 pending_ops = g_slist_next (pending_ops);
631 g_slist_free_1 (tmp_list);
636 window_has_modals (ModestWindow *window)
640 gboolean retvalue = FALSE;
642 /* First we fetch all toplevels */
643 toplevels = gtk_window_list_toplevels ();
644 for (node = toplevels; node != NULL; node = g_list_next (node)) {
645 if (GTK_IS_WINDOW (node->data) &&
646 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (window) &&
647 GTK_WIDGET_VISIBLE (node->data)) {
652 g_list_free (toplevels);
657 on_window_destroy (ModestWindow *window,
659 ModestHildon2WindowMgr *self)
661 gboolean no_propagate = FALSE;
663 /* Do not close the window if it has modals on top */
664 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
667 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
668 gboolean sent = FALSE;
669 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
670 /* Save currently edited message to Drafts if it was not sent */
671 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
672 ModestMsgEditWindow *edit_window;
675 edit_window = MODEST_MSG_EDIT_WINDOW (window);
676 data = modest_msg_edit_window_get_msg_data (edit_window);
680 guint64 parts_size, available_size, expected_size;
682 available_size = modest_utils_get_available_space (NULL);
683 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
684 expected_size = modest_tny_msg_estimate_size (data->plain_body,
688 modest_msg_edit_window_free_msg_data (edit_window, data);
691 /* If there is not enough space
692 available for saving the message
693 then show an error and close the
694 window without saving */
695 if (expected_size >= available_size) {
696 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
697 _("mail_in_ui_save_error"),
700 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
704 g_warning ("Edit window without message data. This is probably a bug");
709 /* Unregister window */
710 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
711 no_propagate = FALSE;
717 modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
718 ModestWindow *window)
721 ModestHildon2WindowMgrPrivate *priv;
722 gulong *tmp, handler_id;
725 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
726 g_return_if_fail (MODEST_IS_WINDOW (window));
728 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
730 win = g_list_find (priv->window_list, window);
732 g_debug ("Trying to unregister a window that has not being registered yet");
736 /* Remove the viewer window handler from the hash table. The
737 HashTable could not exist if the main window was closed
738 when there were other windows remaining */
739 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
740 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
741 /* If the viewer was created without a main window
742 (for example when opening a message through D-Bus
743 the viewer handlers was not registered */
745 g_signal_handler_disconnect (window, *tmp);
746 g_hash_table_remove (priv->viewer_handlers, window);
750 /* Remove from list & hash table */
751 priv->window_list = g_list_remove_link (priv->window_list, win);
752 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
755 g_hash_table_remove (priv->destroy_handlers, window);
757 /* cancel open and receive operations */
758 cancel_window_operations (window);
760 /* Disconnect the "window-state-event" handler, we won't need it anymore */
761 if (priv->window_state_uids) {
762 priv->window_state_uids =
763 modest_signal_mgr_disconnect (priv->window_state_uids,
765 "notify::is-topmost");
768 /* Disconnect the "delete-event" handler, we won't need it anymore */
769 g_signal_handler_disconnect (window, handler_id);
771 /* Destroy the window */
772 g_object_unref (win->data);
775 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
777 /* We have to get the number of windows here in order not to
778 emit the signal too many times */
779 num_windows = modest_window_mgr_get_num_windows (self);
781 /* If there are no more windows registered emit the signal */
782 if (num_windows == 0)
783 g_signal_emit_by_name (self, "window-list-empty");
788 modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
791 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
797 modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
803 modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
805 gboolean show_toolbars,
808 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
814 look_for_transient (gconstpointer a,
817 GtkWindow *win, *child;
822 child = (GtkWindow *) b;
823 win = (GtkWindow *) a;
825 if ((gtk_window_get_transient_for (win) == child) &&
826 GTK_WIDGET_VISIBLE (win))
833 modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self)
835 ModestHildon2WindowMgrPrivate *priv;
836 GList *toplevel_list;
837 GtkWidget *current_top, *toplevel;
838 HildonWindowStack *stack;
840 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
841 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
843 /* Get current top */
844 stack = hildon_window_stack_get_default ();
845 current_top = hildon_window_stack_peek (stack);
846 toplevel = current_top;
847 toplevel_list = gtk_window_list_toplevels ();
852 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
854 toplevel = (GtkWidget *) parent_link->data;
859 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
860 return (GtkWindow *) toplevel;
867 modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
871 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
872 g_return_if_fail (GTK_IS_WINDOW (window));
874 gtk_window_set_modal (window, TRUE);
875 gtk_window_set_transient_for (window, parent);
876 gtk_window_set_destroy_with_parent (window, TRUE);
880 close_all_but_first (gpointer data)
884 HildonWindowStack *stack;
886 stack = hildon_window_stack_get_default ();
887 g_return_if_fail (stack);
889 num_windows = hildon_window_stack_size (stack);
891 for (i = 0; i < (num_windows - 1); i++) {
892 GtkWidget *current_top;
895 current_top = hildon_window_stack_peek (stack);
896 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
901 on_idle_close_all_but_first (gpointer data)
903 gdk_threads_enter ();
904 close_all_but_first (data);
905 gdk_threads_leave ();
911 on_account_removed (TnyAccountStore *acc_store,
915 HildonWindowStack *stack;
916 ModestWindow *current_top;
918 /* Ignore transport account removals */
919 if (TNY_IS_TRANSPORT_ACCOUNT (account))
922 stack = hildon_window_stack_get_default ();
923 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
925 /* if we're showing the header view of the currently deleted
926 account, or the outbox and we deleted the last account,
927 then close the window */
929 (MODEST_IS_HEADER_WINDOW (current_top) ||
930 MODEST_IS_FOLDER_WINDOW (current_top))) {
931 const gchar *acc_name;
933 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
935 /* We emit it in an idle, because sometimes this
936 function could called when the account settings
937 dialog is about to close but still there. That
938 modal dialog would otherwise, prevent the
939 windows from being closed */
940 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
941 g_idle_add (on_idle_close_all_but_first, NULL);
945 static ModestWindow *
946 modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self)
948 ModestWindow *initial_window = NULL;
949 ModestHildon2WindowMgrPrivate *priv;
951 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
953 /* Connect to the account store "account-removed" signal". We
954 do this here because in the init the singletons are still
955 not initialized properly */
956 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
957 priv->accounts_handler)) {
958 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
960 G_CALLBACK (on_account_removed),
964 /* Return accounts window */
965 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
966 modest_window_mgr_register_window (self, initial_window, NULL);
968 return initial_window;
972 static ModestWindow *
973 modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self)
975 HildonWindowStack *stack;
976 stack = hildon_window_stack_get_default ();
977 return (ModestWindow *) hildon_window_stack_peek (stack);
981 find_folder_window (gconstpointer a,
984 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
987 static ModestWindow *
988 modest_hildon2_window_mgr_get_folder_window (ModestWindowMgr *self)
990 ModestHildon2WindowMgrPrivate *priv;
993 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
995 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
997 window = g_list_find_custom (priv->window_list,
1001 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
1005 modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self)
1007 ModestHildon2WindowMgrPrivate *priv = NULL;
1009 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
1011 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1013 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
1017 modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self)
1019 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
1021 modest_accounts_window_pre_create ();
1023 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, NULL);
1040 modest_hildon2_window_mgr_close_all_but_initial (ModestWindowMgr *self)
1044 /* Exit if there are no windows */
1045 if (!modest_window_mgr_get_num_windows (self)) {
1046 g_warning ("%s: unable to close, there are no windows", __FUNCTION__);
1050 /* Close active modals */
1051 if (!_modest_window_mgr_close_active_modals (self)) {
1052 g_debug ("%s: unable to close some dialogs", __FUNCTION__);
1056 /* Close all but first */
1057 top = modest_window_mgr_get_current_top (self);
1058 if (!MODEST_IS_ACCOUNTS_WINDOW (top))
1059 close_all_but_first (NULL);
1061 /* If some cannot be closed return */
1062 top = modest_window_mgr_get_current_top (self);
1063 if (!MODEST_IS_ACCOUNTS_WINDOW (top)) {
1064 g_debug ("%s: could not close some windows", __FUNCTION__);