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>
53 #include <modest-account-mgr-helpers.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,
99 static ModestWindow *modest_hildon2_window_mgr_get_folder_window (ModestWindowMgr *self);
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_modal = modest_hildon2_window_mgr_get_modal;
170 mgr_class->set_modal = modest_hildon2_window_mgr_set_modal;
171 mgr_class->find_registered_header = modest_hildon2_window_mgr_find_registered_header;
172 mgr_class->find_registered_message_uid = modest_hildon2_window_mgr_find_registered_message_uid;
173 mgr_class->get_window_list = modest_hildon2_window_mgr_get_window_list;
174 mgr_class->close_all_windows = modest_hildon2_window_mgr_close_all_windows;
175 mgr_class->close_all_but_initial = modest_hildon2_window_mgr_close_all_but_initial;
176 mgr_class->show_initial_window = modest_hildon2_window_mgr_show_initial_window;
177 mgr_class->get_current_top = modest_hildon2_window_mgr_get_current_top;
178 mgr_class->screen_is_on = modest_hildon2_window_mgr_screen_is_on;
179 mgr_class->create_caches = modest_hildon2_window_mgr_create_caches;
180 mgr_class->get_folder_window = modest_hildon2_window_mgr_get_folder_window;
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 G_OBJECT_CLASS(parent_class)->finalize (obj);
271 modest_hildon2_window_mgr_new (void)
273 return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_HILDON2_WINDOW_MGR, NULL));
277 modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self)
279 ModestHildon2WindowMgrPrivate *priv = NULL;
280 gboolean ret_value = FALSE;
282 HildonWindowStack *stack;
283 gboolean failed = FALSE;
285 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
286 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
288 stack = hildon_window_stack_get_default ();
290 while ((window = hildon_window_stack_peek (stack)) != NULL) {
291 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &ret_value);
292 if (ret_value == TRUE) {
302 compare_msguids (ModestWindow *win,
305 const gchar *msg_uid;
307 if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win)))
310 /* Get message uid from msg window */
311 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
312 msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win));
313 if (msg_uid && uid &&!strcmp (msg_uid, uid))
316 msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
319 if (msg_uid && uid &&!strcmp (msg_uid, uid))
326 compare_headers (ModestWindow *win,
329 TnyHeader *my_header;
332 if (!MODEST_IS_MSG_VIEW_WINDOW (win))
335 /* Get message uid from msg window */
336 my_header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
338 if (my_header == header)
340 g_object_unref (my_header);
347 modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
350 ModestHildon2WindowMgrPrivate *priv = NULL;
352 gboolean has_header, has_window = FALSE;
355 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
356 g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
358 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
360 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_header (self, header, win);
362 uid = modest_tny_folder_get_header_unique_id (header);
364 item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids);
368 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
369 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
370 g_debug ("not a valid window!");
372 g_debug ("found a window");
373 *win = MODEST_WINDOW (item->data);
379 return has_header || has_window;
383 modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
386 ModestHildon2WindowMgrPrivate *priv = NULL;
387 gboolean has_header, has_window = FALSE;
390 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
391 g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
393 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
395 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_message_uid (self, msg_uid, win);
397 item = g_list_find_custom (priv->window_list, msg_uid, (GCompareFunc) compare_msguids);
401 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
402 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
403 g_debug ("not a valid window!");
405 g_debug ("found a window");
406 *win = MODEST_WINDOW (item->data);
411 return has_header || has_window;
415 modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self)
417 ModestHildon2WindowMgrPrivate *priv;
419 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
420 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
422 return g_list_copy (priv->window_list);
425 static gint window_precedence (GtkWindow *window)
427 if (MODEST_IS_ACCOUNTS_WINDOW (window)) {
429 } else if (MODEST_IS_MAILBOXES_WINDOW (window)) {
431 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
433 } else if (MODEST_IS_HEADER_WINDOW (window)) {
435 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
437 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
445 modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
446 ModestWindow *window,
447 ModestWindow *parent)
450 ModestHildon2WindowMgrPrivate *priv;
452 HildonWindowStack *stack;
453 gboolean nested_msg = FALSE;
454 ModestWindow *current_top;
455 const gchar *acc_name, *toplevel_acc_name;
457 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
458 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
460 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
462 /* Try to close active modal dialogs */
463 if (modest_window_mgr_get_num_windows (self) &&
464 !_modest_window_mgr_close_active_modals (self))
467 stack = hildon_window_stack_get_default ();
468 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
470 win = g_list_find (priv->window_list, window);
472 /* this is for the case we want to register the window
473 and it was already registered */
474 gtk_window_present (GTK_WINDOW (window));
478 /* Do not allow standalone editors or standalone viewers */
480 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
481 MODEST_IS_MSG_EDIT_WINDOW (window)))
482 modest_window_mgr_show_initial_window (self);
484 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
488 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
490 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
493 uid = modest_tny_folder_get_header_unique_id (header);
494 /* Embedded messages do not have uid */
496 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
497 g_debug ("%s found another view window showing the same header", __FUNCTION__);
499 g_object_unref (header);
504 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
505 g_debug ("%s found another view window showing the same header", __FUNCTION__);
506 g_object_unref (header);
511 g_object_unref (header);
515 * * toplevel = msg edit -> if not modified, close, if modified, stay
516 * * same account -> no action
517 * * window = accounts -> no action
518 * * window = folders, mailboxes, headers: close all up to accounts window
521 if (MODEST_IS_MSG_EDIT_WINDOW (current_top) &&
522 !modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (current_top))) {
525 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
526 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
529 if (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
530 (current_top && MODEST_IS_ACCOUNTS_WINDOW (window))) {
531 gtk_window_present (GTK_WINDOW (current_top));
535 acc_name = modest_window_get_active_account (window);
537 if (MODEST_IS_MSG_VIEW_WINDOW (current_top) ||
538 MODEST_IS_HEADER_WINDOW (current_top) ||
539 MODEST_IS_FOLDER_WINDOW (current_top) ||
540 MODEST_IS_MAILBOXES_WINDOW (current_top)) {
541 toplevel_acc_name = modest_window_get_active_account (current_top);
543 if (acc_name != NULL && g_strcmp0 (toplevel_acc_name, acc_name) == 0) {
544 /* Same account, no action */
546 if (window_precedence (GTK_WINDOW (current_top)) >= window_precedence (GTK_WINDOW (window))) {
547 if (!(MODEST_IS_MSG_VIEW_WINDOW (current_top) && MODEST_IS_MSG_VIEW_WINDOW (window))) {
548 gtk_window_present (GTK_WINDOW (current_top));
553 while (current_top && !MODEST_IS_ACCOUNTS_WINDOW (current_top)) {
555 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
558 gtk_window_present (GTK_WINDOW (current_top));
561 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
566 /* Trying to open a folders window and a mailboxes window at
567 the same time from the accounts window is not allowed */
568 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
569 MODEST_IS_FOLDER_WINDOW (window) &&
570 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
571 gtk_window_present (GTK_WINDOW (window));
575 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
576 g_debug ("Trying to register a second header window is not allowed");
577 gtk_window_present (GTK_WINDOW (current_top));
581 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
584 /* Add to list. Keep a reference to the window */
585 g_object_ref (window);
586 priv->window_list = g_list_prepend (priv->window_list, window);
588 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
589 MODEST_IS_MSG_VIEW_WINDOW (parent);
591 /* Close views if they're being shown. Nevertheless we must
592 allow nested messages */
594 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
595 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
598 /* If the current view has modal dialogs then
599 we fail to register the new view */
600 if ((current_top != NULL) &&
601 window_has_modals (MODEST_WINDOW (current_top))) {
602 /* Window on top but it has opened dialogs */
606 /* Close the current view */
607 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
609 /* Cancelled closing top window, then we fail to register */
614 /* Listen to object destruction */
615 handler_id = g_malloc0 (sizeof (gint));
616 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
617 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
619 if (!MODEST_IS_MSG_EDIT_WINDOW (window) &&
620 !MODEST_IS_ACCOUNTS_WINDOW (window)) {
621 acc_name = modest_window_get_active_account (window);
624 modest_platform_remove_new_mail_notifications (FALSE, acc_name);
625 modest_account_mgr_set_has_new_mails (modest_runtime_get_account_mgr (),
631 /* Show toolbar always */
632 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
633 gboolean show_toolbar;
634 show_toolbar = modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL);
635 modest_window_show_toolbar (window, show_toolbar);
637 modest_window_show_toolbar (window, TRUE);
642 /* Add to list. Keep a reference to the window */
643 priv->window_list = g_list_remove (priv->window_list, window);
644 g_object_unref (window);
645 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
647 gtk_window_present (GTK_WINDOW (current_top));
652 cancel_window_operations (ModestWindow *window)
654 GSList* pending_ops = NULL;
656 /* cancel open and receive operations */
657 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
659 while (pending_ops != NULL) {
660 ModestMailOperationTypeOperation type;
661 GSList* tmp_list = NULL;
663 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
664 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
665 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
666 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
667 modest_mail_operation_cancel (pending_ops->data);
669 g_object_unref (G_OBJECT (pending_ops->data));
670 tmp_list = pending_ops;
671 pending_ops = g_slist_next (pending_ops);
672 g_slist_free_1 (tmp_list);
677 window_has_modals (ModestWindow *window)
681 gboolean retvalue = FALSE;
683 /* First we fetch all toplevels */
684 toplevels = gtk_window_list_toplevels ();
685 for (node = toplevels; node != NULL; node = g_list_next (node)) {
686 if (GTK_IS_WINDOW (node->data) &&
687 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (window) &&
688 GTK_WIDGET_VISIBLE (node->data)) {
693 g_list_free (toplevels);
698 on_window_destroy (ModestWindow *window,
700 ModestHildon2WindowMgr *self)
702 gboolean no_propagate = FALSE;
704 /* Do not close the window if it has modals on top */
705 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
708 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
709 gboolean sent = FALSE;
710 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
711 /* Save currently edited message to Drafts if it was not sent */
712 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
713 ModestMsgEditWindow *edit_window;
716 edit_window = MODEST_MSG_EDIT_WINDOW (window);
717 data = modest_msg_edit_window_get_msg_data (edit_window);
721 guint64 parts_size, available_size, expected_size;
723 available_size = modest_utils_get_available_space (NULL);
724 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
725 expected_size = modest_tny_msg_estimate_size (data->plain_body,
729 modest_msg_edit_window_free_msg_data (edit_window, data);
732 /* If there is not enough space
733 available for saving the message
734 then show an error and close the
735 window without saving */
736 if (expected_size >= available_size) {
737 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
738 _("mail_in_ui_save_error"),
741 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
745 g_warning ("Edit window without message data. This is probably a bug");
750 /* Unregister window */
751 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
752 no_propagate = FALSE;
758 modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
759 ModestWindow *window)
762 ModestHildon2WindowMgrPrivate *priv;
763 gulong *tmp, handler_id;
766 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
767 g_return_if_fail (MODEST_IS_WINDOW (window));
769 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
771 win = g_list_find (priv->window_list, window);
773 g_debug ("Trying to unregister a window that has not being registered yet");
777 /* Remove the viewer window handler from the hash table. The
778 HashTable could not exist if the main window was closed
779 when there were other windows remaining */
780 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
781 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
782 /* If the viewer was created without a main window
783 (for example when opening a message through D-Bus
784 the viewer handlers was not registered */
786 g_signal_handler_disconnect (window, *tmp);
787 g_hash_table_remove (priv->viewer_handlers, window);
791 /* Remove from list & hash table */
792 priv->window_list = g_list_remove_link (priv->window_list, win);
793 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
796 g_hash_table_remove (priv->destroy_handlers, window);
798 /* cancel open and receive operations */
799 cancel_window_operations (window);
801 /* Disconnect the "window-state-event" handler, we won't need it anymore */
802 if (priv->window_state_uids) {
803 priv->window_state_uids =
804 modest_signal_mgr_disconnect (priv->window_state_uids,
806 "notify::is-topmost");
809 /* Disconnect the "delete-event" handler, we won't need it anymore */
810 g_signal_handler_disconnect (window, handler_id);
812 /* Destroy the window */
813 g_object_unref (win->data);
816 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
818 /* We have to get the number of windows here in order not to
819 emit the signal too many times */
820 num_windows = modest_window_mgr_get_num_windows (self);
822 /* If there are no more windows registered emit the signal */
823 if (num_windows == 0)
824 g_signal_emit_by_name (self, "window-list-empty");
829 modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
832 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
838 modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
844 modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
846 gboolean show_toolbars,
849 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
855 look_for_transient (gconstpointer a,
858 GtkWindow *win, *child;
863 child = (GtkWindow *) b;
864 win = (GtkWindow *) a;
866 if ((gtk_window_get_transient_for (win) == child) &&
867 GTK_WIDGET_VISIBLE (win))
874 modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self)
876 ModestHildon2WindowMgrPrivate *priv;
877 GList *toplevel_list;
878 GtkWidget *current_top, *toplevel;
879 HildonWindowStack *stack;
881 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
882 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
884 /* Get current top */
885 stack = hildon_window_stack_get_default ();
886 current_top = hildon_window_stack_peek (stack);
887 toplevel = current_top;
888 toplevel_list = gtk_window_list_toplevels ();
893 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
895 toplevel = (GtkWidget *) parent_link->data;
900 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
901 return (GtkWindow *) toplevel;
908 modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
912 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
913 g_return_if_fail (GTK_IS_WINDOW (window));
915 gtk_window_set_modal (window, TRUE);
916 gtk_window_set_transient_for (window, parent);
917 gtk_window_set_destroy_with_parent (window, TRUE);
919 if (!gtk_window_has_toplevel_focus (window)) {
920 GList *toplevels, *node;
922 toplevels = gtk_window_list_toplevels ();
923 for (node = toplevels; node != NULL; node = g_list_next (node)) {
924 if (gtk_window_has_toplevel_focus (GTK_WINDOW (node->data))) {
925 if (GTK_IS_DIALOG (node->data)) {
926 gtk_window_set_transient_for (window, GTK_WINDOW (node->data));
935 close_all_but_first (gpointer data)
939 HildonWindowStack *stack;
941 stack = hildon_window_stack_get_default ();
942 g_return_if_fail (stack);
944 num_windows = hildon_window_stack_size (stack);
946 for (i = 0; i < (num_windows - 1); i++) {
947 GtkWidget *current_top;
950 current_top = hildon_window_stack_peek (stack);
951 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
956 on_idle_close_all_but_first (gpointer data)
958 gdk_threads_enter ();
959 close_all_but_first (data);
960 gdk_threads_leave ();
966 on_account_removed (TnyAccountStore *acc_store,
970 HildonWindowStack *stack;
971 ModestWindow *current_top;
973 /* Ignore transport account removals */
974 if (TNY_IS_TRANSPORT_ACCOUNT (account))
977 stack = hildon_window_stack_get_default ();
978 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
980 /* if we're showing the header view of the currently deleted
981 account, or the outbox and we deleted the last account,
982 then close the window */
984 (MODEST_IS_HEADER_WINDOW (current_top) ||
985 MODEST_IS_FOLDER_WINDOW (current_top))) {
986 const gchar *acc_name;
988 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
990 /* We emit it in an idle, because sometimes this
991 function could called when the account settings
992 dialog is about to close but still there. That
993 modal dialog would otherwise, prevent the
994 windows from being closed */
995 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
996 g_idle_add (on_idle_close_all_but_first, NULL);
1000 static ModestWindow *
1001 modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self)
1003 ModestWindow *initial_window = NULL;
1004 ModestHildon2WindowMgrPrivate *priv;
1006 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1008 /* Connect to the account store "account-removed" signal". We
1009 do this here because in the init the singletons are still
1010 not initialized properly */
1011 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
1012 priv->accounts_handler)) {
1013 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
1015 G_CALLBACK (on_account_removed),
1019 /* Return accounts window */
1020 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
1021 modest_window_mgr_register_window (self, initial_window, NULL);
1023 return initial_window;
1027 static ModestWindow *
1028 modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self)
1030 HildonWindowStack *stack;
1031 stack = hildon_window_stack_get_default ();
1032 return (ModestWindow *) hildon_window_stack_peek (stack);
1036 find_folder_window (gconstpointer a,
1039 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
1042 static ModestWindow *
1043 modest_hildon2_window_mgr_get_folder_window (ModestWindowMgr *self)
1045 ModestHildon2WindowMgrPrivate *priv;
1048 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
1050 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1052 window = g_list_find_custom (priv->window_list,
1054 find_folder_window);
1056 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
1060 modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self)
1062 ModestHildon2WindowMgrPrivate *priv = NULL;
1064 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
1066 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1068 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
1072 modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self)
1074 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
1076 modest_accounts_window_pre_create ();
1078 MODEST_WINDOW_MGR_CLASS(parent_class)->create_caches (self);
1082 osso_display_event_cb (osso_display_state_t state,
1085 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (data);
1087 priv->display_state = state;
1089 /* Stop blinking if the screen becomes on */
1090 if (priv->display_state == OSSO_DISPLAY_ON)
1091 modest_platform_remove_new_mail_notifications (TRUE, NULL);
1095 modest_hildon2_window_mgr_close_all_but_initial (ModestWindowMgr *self)
1099 /* Exit if there are no windows */
1100 if (!modest_window_mgr_get_num_windows (self)) {
1101 g_warning ("%s: unable to close, there are no windows", __FUNCTION__);
1105 /* Close active modals */
1106 if (!_modest_window_mgr_close_active_modals (self)) {
1107 g_debug ("%s: unable to close some dialogs", __FUNCTION__);
1111 /* Close all but first */
1112 top = modest_window_mgr_get_current_top (self);
1113 if (!MODEST_IS_ACCOUNTS_WINDOW (top))
1114 close_all_but_first (NULL);
1116 /* If some cannot be closed return */
1117 top = modest_window_mgr_get_current_top (self);
1118 if (!MODEST_IS_ACCOUNTS_WINDOW (top)) {
1119 g_debug ("%s: could not close some windows", __FUNCTION__);