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 ModestWindow* modest_hildon2_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show);
77 static GtkWindow *modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self);
78 static void modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
81 static gboolean modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self,
84 static gboolean modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self,
87 static GList *modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self);
88 static gboolean modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self);
89 static gboolean modest_hildon2_window_mgr_close_all_but_initial (ModestWindowMgr *self);
90 static gboolean window_has_modals (ModestWindow *window);
91 static ModestWindow *modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self);
92 static ModestWindow *modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self);
93 static gboolean modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self);
94 static void modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self);
95 static void osso_display_event_cb (osso_display_state_t state,
97 static void on_account_removed (TnyAccountStore *acc_store,
101 typedef struct _ModestHildon2WindowMgrPrivate ModestHildon2WindowMgrPrivate;
102 struct _ModestHildon2WindowMgrPrivate {
105 GQueue *modal_windows;
107 gboolean fullscreen_mode;
109 GHashTable *destroy_handlers;
110 GHashTable *viewer_handlers;
111 GSList *window_state_uids;
115 GSList *modal_handler_uids;
116 ModestWindow *current_top;
118 gulong accounts_handler;
121 osso_display_state_t display_state;
123 #define MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
124 MODEST_TYPE_HILDON2_WINDOW_MGR, \
125 ModestHildon2WindowMgrPrivate))
127 static GObjectClass *parent_class = NULL;
130 modest_hildon2_window_mgr_get_type (void)
132 static GType my_type = 0;
134 static const GTypeInfo my_info = {
135 sizeof(ModestHildon2WindowMgrClass),
136 NULL, /* base init */
137 NULL, /* base finalize */
138 (GClassInitFunc) modest_hildon2_window_mgr_class_init,
139 NULL, /* class finalize */
140 NULL, /* class data */
141 sizeof(ModestHildon2WindowMgr),
143 (GInstanceInitFunc) modest_hildon2_window_mgr_instance_init,
146 my_type = g_type_register_static (MODEST_TYPE_WINDOW_MGR,
147 "ModestHildon2WindowMgr",
154 modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass)
156 GObjectClass *gobject_class;
157 ModestWindowMgrClass *mgr_class;
159 gobject_class = (GObjectClass*) klass;
160 mgr_class = (ModestWindowMgrClass *) klass;
162 parent_class = g_type_class_peek_parent (klass);
163 gobject_class->finalize = modest_hildon2_window_mgr_finalize;
164 mgr_class->register_window = modest_hildon2_window_mgr_register_window;
165 mgr_class->unregister_window = modest_hildon2_window_mgr_unregister_window;
166 mgr_class->set_fullscreen_mode = modest_hildon2_window_mgr_set_fullscreen_mode;
167 mgr_class->get_fullscreen_mode = modest_hildon2_window_mgr_get_fullscreen_mode;
168 mgr_class->show_toolbars = modest_hildon2_window_mgr_show_toolbars;
169 mgr_class->get_main_window = modest_hildon2_window_mgr_get_main_window;
170 mgr_class->get_modal = modest_hildon2_window_mgr_get_modal;
171 mgr_class->set_modal = modest_hildon2_window_mgr_set_modal;
172 mgr_class->find_registered_header = modest_hildon2_window_mgr_find_registered_header;
173 mgr_class->find_registered_message_uid = modest_hildon2_window_mgr_find_registered_message_uid;
174 mgr_class->get_window_list = modest_hildon2_window_mgr_get_window_list;
175 mgr_class->close_all_windows = modest_hildon2_window_mgr_close_all_windows;
176 mgr_class->close_all_but_initial = modest_hildon2_window_mgr_close_all_but_initial;
177 mgr_class->show_initial_window = modest_hildon2_window_mgr_show_initial_window;
178 mgr_class->get_current_top = modest_hildon2_window_mgr_get_current_top;
179 mgr_class->screen_is_on = modest_hildon2_window_mgr_screen_is_on;
180 mgr_class->create_caches = modest_hildon2_window_mgr_create_caches;
182 g_type_class_add_private (gobject_class, sizeof(ModestHildon2WindowMgrPrivate));
187 modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj)
189 ModestHildon2WindowMgrPrivate *priv;
191 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
192 priv->window_list = NULL;
193 priv->fullscreen_mode = FALSE;
194 priv->window_state_uids = NULL;
196 priv->modal_windows = g_queue_new ();
197 priv->queue_lock = g_mutex_new ();
199 /* Could not initialize it from gconf, singletons are not
201 priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
202 priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
204 priv->closing_time = 0;
206 priv->modal_handler_uids = NULL;
207 priv->display_state = OSSO_DISPLAY_ON;
209 /* Listen for changes in the screen, we don't want to show a
210 led pattern when the display is on for example */
211 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
212 osso_display_event_cb,
218 modest_hildon2_window_mgr_finalize (GObject *obj)
220 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
221 ModestTnyAccountStore *acc_store;
223 modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids);
224 priv->window_state_uids = NULL;
226 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
229 acc_store = modest_runtime_get_account_store ();
230 if (acc_store && g_signal_handler_is_connected (acc_store, priv->accounts_handler))
231 g_signal_handler_disconnect (acc_store, priv->accounts_handler);
233 if (priv->window_list) {
234 GList *iter = priv->window_list;
235 /* unregister pending windows */
237 ModestWindow *window = (ModestWindow *) iter->data;
238 iter = g_list_next (iter);
239 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), window);
241 g_list_free (priv->window_list);
242 priv->window_list = NULL;
245 /* Free the hash table with the handlers */
246 if (priv->destroy_handlers) {
247 g_hash_table_destroy (priv->destroy_handlers);
248 priv->destroy_handlers = NULL;
251 if (priv->viewer_handlers) {
252 g_hash_table_destroy (priv->viewer_handlers);
253 priv->viewer_handlers = NULL;
256 modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids);
257 priv->modal_handler_uids = NULL;
259 if (priv->modal_windows) {
260 g_mutex_lock (priv->queue_lock);
261 g_queue_free (priv->modal_windows);
262 priv->modal_windows = NULL;
263 g_mutex_unlock (priv->queue_lock);
265 g_mutex_free (priv->queue_lock);
267 /* Do not unref priv->main_window because it does not hold a
270 G_OBJECT_CLASS(parent_class)->finalize (obj);
274 modest_hildon2_window_mgr_new (void)
276 return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_HILDON2_WINDOW_MGR, NULL));
280 modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self)
282 ModestHildon2WindowMgrPrivate *priv = NULL;
283 gboolean ret_value = FALSE;
285 HildonWindowStack *stack;
286 gboolean failed = FALSE;
288 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
289 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
291 stack = hildon_window_stack_get_default ();
293 while ((window = hildon_window_stack_peek (stack)) != NULL) {
294 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &ret_value);
295 if (ret_value == TRUE) {
305 compare_msguids (ModestWindow *win,
308 const gchar *msg_uid;
310 if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win)))
313 /* Get message uid from msg window */
314 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
315 msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win));
316 if (msg_uid && uid &&!strcmp (msg_uid, uid))
319 msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
322 if (msg_uid && uid &&!strcmp (msg_uid, uid))
329 compare_headers (ModestWindow *win,
332 TnyHeader *my_header;
335 if (!MODEST_IS_MSG_VIEW_WINDOW (win))
338 /* Get message uid from msg window */
339 my_header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
341 if (my_header == header)
343 g_object_unref (my_header);
350 modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
353 ModestHildon2WindowMgrPrivate *priv = NULL;
355 gboolean has_header, has_window = FALSE;
358 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
359 g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
361 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
363 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_header (self, header, win);
365 uid = modest_tny_folder_get_header_unique_id (header);
367 item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids);
371 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
372 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
373 g_debug ("not a valid window!");
375 g_debug ("found a window");
376 *win = MODEST_WINDOW (item->data);
382 return has_header || has_window;
386 modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
389 ModestHildon2WindowMgrPrivate *priv = NULL;
390 gboolean has_header, has_window = FALSE;
393 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
394 g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
396 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
398 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_message_uid (self, msg_uid, win);
400 item = g_list_find_custom (priv->window_list, msg_uid, (GCompareFunc) compare_msguids);
404 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
405 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
406 g_debug ("not a valid window!");
408 g_debug ("found a window");
409 *win = MODEST_WINDOW (item->data);
414 return has_header || has_window;
418 modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self)
420 ModestHildon2WindowMgrPrivate *priv;
422 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
423 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
425 return g_list_copy (priv->window_list);
429 modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
430 ModestWindow *window,
431 ModestWindow *parent)
434 ModestHildon2WindowMgrPrivate *priv;
436 HildonWindowStack *stack;
437 gboolean nested_msg = FALSE;
438 ModestWindow *current_top;
439 const gchar *acc_name;
441 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
442 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
444 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
446 /* Try to close active modal dialogs */
447 if (modest_window_mgr_get_num_windows (self) &&
448 !_modest_window_mgr_close_active_modals (self))
451 stack = hildon_window_stack_get_default ();
452 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
454 win = g_list_find (priv->window_list, window);
456 /* this is for the case we want to register the window
457 and it was already registered */
458 gtk_window_present (GTK_WINDOW (window));
462 /* Do not allow standalone editors or standalone viewers */
464 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
465 MODEST_IS_MSG_EDIT_WINDOW (window)))
466 modest_window_mgr_show_initial_window (self);
468 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
472 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
474 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
477 uid = modest_tny_folder_get_header_unique_id (header);
478 /* Embedded messages do not have uid */
480 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
481 g_debug ("%s found another view window showing the same header", __FUNCTION__);
483 g_object_unref (header);
488 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
489 g_debug ("%s found another view window showing the same header", __FUNCTION__);
490 g_object_unref (header);
495 g_object_unref (header);
498 /* Do not go backwards */
499 if ((MODEST_IS_MSG_VIEW_WINDOW (current_top) ||
500 MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
501 MODEST_IS_HEADER_WINDOW (current_top)) &&
502 (MODEST_IS_FOLDER_WINDOW (window) ||
503 MODEST_IS_ACCOUNTS_WINDOW (window) ||
504 MODEST_IS_MAILBOXES_WINDOW (window))) {
505 gtk_window_present (GTK_WINDOW (current_top));
509 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_FOLDER_WINDOW (window)) {
512 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
515 gtk_window_present (GTK_WINDOW (current_top));
518 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
521 if (MODEST_IS_MAILBOXES_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
522 gtk_window_present (GTK_WINDOW (current_top));
526 /* Mailboxes window can not replace folder windows */
527 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
528 gtk_window_present (GTK_WINDOW (current_top));
532 /* Trying to open a folders window and a mailboxes window at
533 the same time from the accounts window is not allowed */
534 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
535 MODEST_IS_FOLDER_WINDOW (window) &&
536 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
537 gtk_window_present (GTK_WINDOW (window));
541 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
542 g_debug ("Trying to register a second header window is not allowed");
543 gtk_window_present (GTK_WINDOW (current_top));
547 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
550 /* Add to list. Keep a reference to the window */
551 g_object_ref (window);
552 priv->window_list = g_list_prepend (priv->window_list, window);
554 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
555 MODEST_IS_MSG_VIEW_WINDOW (parent);
557 /* Close views if they're being shown. Nevertheless we must
558 allow nested messages */
560 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
561 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
564 /* If the current view has modal dialogs then
565 we fail to register the new view */
566 if ((current_top != NULL) &&
567 window_has_modals (MODEST_WINDOW (current_top))) {
568 /* Window on top but it has opened dialogs */
572 /* Close the current view */
573 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
575 /* Cancelled closing top window, then we fail to register */
580 /* Listen to object destruction */
581 handler_id = g_malloc0 (sizeof (gint));
582 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
583 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
585 if (!MODEST_IS_MSG_EDIT_WINDOW (window) &&
586 !MODEST_IS_ACCOUNTS_WINDOW (window)) {
587 acc_name = modest_window_get_active_account (window);
590 modest_platform_remove_new_mail_notifications (FALSE, acc_name);
594 /* Show toolbar always */
595 modest_window_show_toolbar (window, TRUE);
599 /* Add to list. Keep a reference to the window */
600 priv->window_list = g_list_remove (priv->window_list, window);
601 g_object_unref (window);
602 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
604 gtk_window_present (GTK_WINDOW (current_top));
609 cancel_window_operations (ModestWindow *window)
611 GSList* pending_ops = NULL;
613 /* cancel open and receive operations */
614 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
616 while (pending_ops != NULL) {
617 ModestMailOperationTypeOperation type;
618 GSList* tmp_list = NULL;
620 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
621 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
622 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
623 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
624 modest_mail_operation_cancel (pending_ops->data);
626 g_object_unref (G_OBJECT (pending_ops->data));
627 tmp_list = pending_ops;
628 pending_ops = g_slist_next (pending_ops);
629 g_slist_free_1 (tmp_list);
634 window_has_modals (ModestWindow *window)
638 gboolean retvalue = FALSE;
640 /* First we fetch all toplevels */
641 toplevels = gtk_window_list_toplevels ();
642 for (node = toplevels; node != NULL; node = g_list_next (node)) {
643 if (GTK_IS_WINDOW (node->data) &&
644 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (window) &&
645 GTK_WIDGET_VISIBLE (node->data)) {
650 g_list_free (toplevels);
655 on_window_destroy (ModestWindow *window,
657 ModestHildon2WindowMgr *self)
659 gboolean no_propagate = FALSE;
661 /* Do not close the window if it has modals on top */
662 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
665 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
666 gboolean sent = FALSE;
667 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
668 /* Save currently edited message to Drafts if it was not sent */
669 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
670 ModestMsgEditWindow *edit_window;
673 edit_window = MODEST_MSG_EDIT_WINDOW (window);
674 data = modest_msg_edit_window_get_msg_data (edit_window);
678 guint64 parts_size, available_size, expected_size;
680 available_size = modest_utils_get_available_space (NULL);
681 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
682 expected_size = modest_tny_msg_estimate_size (data->plain_body,
686 modest_msg_edit_window_free_msg_data (edit_window, data);
689 /* If there is not enough space
690 available for saving the message
691 then show an error and close the
692 window without saving */
693 if (expected_size >= available_size) {
694 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
695 _("mail_in_ui_save_error"),
698 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
702 g_warning ("Edit window without message data. This is probably a bug");
707 /* Unregister window */
708 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
709 no_propagate = FALSE;
715 modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
716 ModestWindow *window)
719 ModestHildon2WindowMgrPrivate *priv;
720 gulong *tmp, handler_id;
723 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
724 g_return_if_fail (MODEST_IS_WINDOW (window));
726 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
728 win = g_list_find (priv->window_list, window);
730 g_debug ("Trying to unregister a window that has not being registered yet");
734 /* Remove the viewer window handler from the hash table. The
735 HashTable could not exist if the main window was closed
736 when there were other windows remaining */
737 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
738 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
739 /* If the viewer was created without a main window
740 (for example when opening a message through D-Bus
741 the viewer handlers was not registered */
743 g_signal_handler_disconnect (window, *tmp);
744 g_hash_table_remove (priv->viewer_handlers, window);
748 /* Remove from list & hash table */
749 priv->window_list = g_list_remove_link (priv->window_list, win);
750 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
753 g_hash_table_remove (priv->destroy_handlers, window);
755 /* cancel open and receive operations */
756 cancel_window_operations (window);
758 /* Disconnect the "window-state-event" handler, we won't need it anymore */
759 if (priv->window_state_uids) {
760 priv->window_state_uids =
761 modest_signal_mgr_disconnect (priv->window_state_uids,
763 "notify::is-topmost");
766 /* Disconnect the "delete-event" handler, we won't need it anymore */
767 g_signal_handler_disconnect (window, handler_id);
769 /* Destroy the window */
770 g_object_unref (win->data);
773 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
775 /* We have to get the number of windows here in order not to
776 emit the signal too many times */
777 num_windows = modest_window_mgr_get_num_windows (self);
779 /* If there are no more windows registered emit the signal */
780 if (num_windows == 0)
781 g_signal_emit_by_name (self, "window-list-empty");
786 modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
789 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
795 modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
801 modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
803 gboolean show_toolbars,
806 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
812 modest_hildon2_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show)
814 ModestHildon2WindowMgrPrivate *priv;
815 ModestWindow *result;
817 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
818 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
820 /* TODO: make this return NULL always */
822 result = MODEST_WINDOW_MGR_CLASS (parent_class)->get_main_window (self, FALSE);
823 /* create the main window, if it hasn't been created yet */
824 if (!result && show) {
825 /* modest_window_mgr_register_window will set priv->main_window */
826 result = modest_main_window_new ();
827 /* We have to remove all other windows */
828 if (!modest_window_mgr_close_all_windows (self)) {
829 gtk_widget_destroy (GTK_WIDGET (result));
832 if (!modest_window_mgr_register_window (self, result, NULL)) {
833 gtk_widget_destroy (GTK_WIDGET (result));
837 g_debug ("%s: created main window: %p\n", __FUNCTION__, result);
841 gtk_widget_show_all (GTK_WIDGET (result));
842 gtk_window_present (GTK_WINDOW (result));
849 look_for_transient (gconstpointer a,
852 GtkWindow *win, *child;
857 child = (GtkWindow *) b;
858 win = (GtkWindow *) a;
860 if ((gtk_window_get_transient_for (win) == child) &&
861 GTK_WIDGET_VISIBLE (win))
868 modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self)
870 ModestHildon2WindowMgrPrivate *priv;
871 GList *toplevel_list;
872 GtkWidget *current_top, *toplevel;
873 HildonWindowStack *stack;
875 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
876 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
878 /* Get current top */
879 stack = hildon_window_stack_get_default ();
880 current_top = hildon_window_stack_peek (stack);
881 toplevel = current_top;
882 toplevel_list = gtk_window_list_toplevels ();
887 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
889 toplevel = (GtkWidget *) parent_link->data;
894 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
895 return (GtkWindow *) toplevel;
902 modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
906 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
907 g_return_if_fail (GTK_IS_WINDOW (window));
909 gtk_window_set_modal (window, TRUE);
910 gtk_window_set_transient_for (window, parent);
911 gtk_window_set_destroy_with_parent (window, TRUE);
915 close_all_but_first (gpointer data)
919 HildonWindowStack *stack;
921 stack = hildon_window_stack_get_default ();
922 g_return_if_fail (stack);
924 num_windows = hildon_window_stack_size (stack);
926 for (i = 0; i < (num_windows - 1); i++) {
927 GtkWidget *current_top;
930 current_top = hildon_window_stack_peek (stack);
931 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
936 on_idle_close_all_but_first (gpointer data)
938 gdk_threads_enter ();
939 close_all_but_first (data);
940 gdk_threads_leave ();
946 on_account_removed (TnyAccountStore *acc_store,
950 HildonWindowStack *stack;
951 ModestWindow *current_top;
953 /* Ignore transport account removals */
954 if (TNY_IS_TRANSPORT_ACCOUNT (account))
957 stack = hildon_window_stack_get_default ();
958 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
960 /* if we're showing the header view of the currently deleted
961 account, or the outbox and we deleted the last account,
962 then close the window */
964 (MODEST_IS_HEADER_WINDOW (current_top) ||
965 MODEST_IS_FOLDER_WINDOW (current_top))) {
966 const gchar *acc_name;
968 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
970 /* We emit it in an idle, because sometimes this
971 function could called when the account settings
972 dialog is about to close but still there. That
973 modal dialog would otherwise, prevent the
974 windows from being closed */
975 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
976 g_idle_add (on_idle_close_all_but_first, NULL);
980 static ModestWindow *
981 modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self)
983 ModestWindow *initial_window = NULL;
984 ModestHildon2WindowMgrPrivate *priv;
986 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
988 /* Connect to the account store "account-removed" signal". We
989 do this here because in the init the singletons are still
990 not initialized properly */
991 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
992 priv->accounts_handler)) {
993 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
995 G_CALLBACK (on_account_removed),
999 /* Return accounts window */
1000 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
1001 modest_window_mgr_register_window (self, initial_window, NULL);
1003 return initial_window;
1007 static ModestWindow *
1008 modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self)
1010 HildonWindowStack *stack;
1011 stack = hildon_window_stack_get_default ();
1012 return (ModestWindow *) hildon_window_stack_peek (stack);
1016 find_folder_window (gconstpointer a,
1019 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
1023 modest_hildon2_window_mgr_get_folder_window (ModestHildon2WindowMgr *self)
1025 ModestHildon2WindowMgrPrivate *priv;
1028 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
1030 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1032 window = g_list_find_custom (priv->window_list,
1034 find_folder_window);
1036 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
1040 modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self)
1042 ModestHildon2WindowMgrPrivate *priv = NULL;
1044 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
1046 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1048 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
1052 modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self)
1054 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
1056 modest_accounts_window_pre_create ();
1058 MODEST_WINDOW_MGR_CLASS(parent_class)->create_caches (self);
1062 osso_display_event_cb (osso_display_state_t state,
1065 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (data);
1067 priv->display_state = state;
1069 /* Stop blinking if the screen becomes on */
1070 if (priv->display_state == OSSO_DISPLAY_ON)
1071 modest_platform_remove_new_mail_notifications (TRUE, NULL);
1075 modest_hildon2_window_mgr_close_all_but_initial (ModestWindowMgr *self)
1079 /* Exit if there are no windows */
1080 if (!modest_window_mgr_get_num_windows (self)) {
1081 g_warning ("%s: unable to close, there are no windows", __FUNCTION__);
1085 /* Close active modals */
1086 if (!_modest_window_mgr_close_active_modals (self)) {
1087 g_debug ("%s: unable to close some dialogs", __FUNCTION__);
1091 /* Close all but first */
1092 top = modest_window_mgr_get_current_top (self);
1093 if (!MODEST_IS_ACCOUNTS_WINDOW (top))
1094 close_all_but_first (NULL);
1096 /* If some cannot be closed return */
1097 top = modest_window_mgr_get_current_top (self);
1098 if (!MODEST_IS_ACCOUNTS_WINDOW (top)) {
1099 g_debug ("%s: could not close some windows", __FUNCTION__);