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>
54 #include <modest-account-mgr-helpers.h>
56 /* 'private'/'protected' functions */
57 static void modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass);
58 static void modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj);
59 static void modest_hildon2_window_mgr_finalize (GObject *obj);
61 static gboolean on_window_destroy (ModestWindow *window,
63 ModestHildon2WindowMgr *self);
65 static gboolean modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
67 ModestWindow *parent);
68 static void modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
69 ModestWindow *window);
70 static void modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
72 static gboolean modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self);
73 static void modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
75 gboolean show_toolbars,
77 static ModestWindow* modest_hildon2_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show);
78 static GtkWindow *modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self);
79 static void modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
82 static gboolean modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self,
85 static gboolean modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self,
88 static GList *modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self);
89 static gboolean modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self);
90 static gboolean modest_hildon2_window_mgr_close_all_but_initial (ModestWindowMgr *self);
91 static gboolean window_has_modals (ModestWindow *window);
92 static ModestWindow *modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self);
93 static ModestWindow *modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self);
94 static gboolean modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self);
95 static void modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self);
96 static void osso_display_event_cb (osso_display_state_t state,
98 static void on_account_removed (TnyAccountStore *acc_store,
102 typedef struct _ModestHildon2WindowMgrPrivate ModestHildon2WindowMgrPrivate;
103 struct _ModestHildon2WindowMgrPrivate {
106 GQueue *modal_windows;
108 gboolean fullscreen_mode;
110 GHashTable *destroy_handlers;
111 GHashTable *viewer_handlers;
112 GSList *window_state_uids;
116 GSList *modal_handler_uids;
117 ModestWindow *current_top;
119 gulong accounts_handler;
122 osso_display_state_t display_state;
124 #define MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
125 MODEST_TYPE_HILDON2_WINDOW_MGR, \
126 ModestHildon2WindowMgrPrivate))
128 static GObjectClass *parent_class = NULL;
131 modest_hildon2_window_mgr_get_type (void)
133 static GType my_type = 0;
135 static const GTypeInfo my_info = {
136 sizeof(ModestHildon2WindowMgrClass),
137 NULL, /* base init */
138 NULL, /* base finalize */
139 (GClassInitFunc) modest_hildon2_window_mgr_class_init,
140 NULL, /* class finalize */
141 NULL, /* class data */
142 sizeof(ModestHildon2WindowMgr),
144 (GInstanceInitFunc) modest_hildon2_window_mgr_instance_init,
147 my_type = g_type_register_static (MODEST_TYPE_WINDOW_MGR,
148 "ModestHildon2WindowMgr",
155 modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass)
157 GObjectClass *gobject_class;
158 ModestWindowMgrClass *mgr_class;
160 gobject_class = (GObjectClass*) klass;
161 mgr_class = (ModestWindowMgrClass *) klass;
163 parent_class = g_type_class_peek_parent (klass);
164 gobject_class->finalize = modest_hildon2_window_mgr_finalize;
165 mgr_class->register_window = modest_hildon2_window_mgr_register_window;
166 mgr_class->unregister_window = modest_hildon2_window_mgr_unregister_window;
167 mgr_class->set_fullscreen_mode = modest_hildon2_window_mgr_set_fullscreen_mode;
168 mgr_class->get_fullscreen_mode = modest_hildon2_window_mgr_get_fullscreen_mode;
169 mgr_class->show_toolbars = modest_hildon2_window_mgr_show_toolbars;
170 mgr_class->get_main_window = modest_hildon2_window_mgr_get_main_window;
171 mgr_class->get_modal = modest_hildon2_window_mgr_get_modal;
172 mgr_class->set_modal = modest_hildon2_window_mgr_set_modal;
173 mgr_class->find_registered_header = modest_hildon2_window_mgr_find_registered_header;
174 mgr_class->find_registered_message_uid = modest_hildon2_window_mgr_find_registered_message_uid;
175 mgr_class->get_window_list = modest_hildon2_window_mgr_get_window_list;
176 mgr_class->close_all_windows = modest_hildon2_window_mgr_close_all_windows;
177 mgr_class->close_all_but_initial = modest_hildon2_window_mgr_close_all_but_initial;
178 mgr_class->show_initial_window = modest_hildon2_window_mgr_show_initial_window;
179 mgr_class->get_current_top = modest_hildon2_window_mgr_get_current_top;
180 mgr_class->screen_is_on = modest_hildon2_window_mgr_screen_is_on;
181 mgr_class->create_caches = modest_hildon2_window_mgr_create_caches;
183 g_type_class_add_private (gobject_class, sizeof(ModestHildon2WindowMgrPrivate));
188 modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj)
190 ModestHildon2WindowMgrPrivate *priv;
192 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
193 priv->window_list = NULL;
194 priv->fullscreen_mode = FALSE;
195 priv->window_state_uids = NULL;
197 priv->modal_windows = g_queue_new ();
198 priv->queue_lock = g_mutex_new ();
200 /* Could not initialize it from gconf, singletons are not
202 priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
203 priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
205 priv->closing_time = 0;
207 priv->modal_handler_uids = NULL;
208 priv->display_state = OSSO_DISPLAY_ON;
210 /* Listen for changes in the screen, we don't want to show a
211 led pattern when the display is on for example */
212 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
213 osso_display_event_cb,
219 modest_hildon2_window_mgr_finalize (GObject *obj)
221 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
222 ModestTnyAccountStore *acc_store;
224 modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids);
225 priv->window_state_uids = NULL;
227 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
230 acc_store = modest_runtime_get_account_store ();
231 if (acc_store && g_signal_handler_is_connected (acc_store, priv->accounts_handler))
232 g_signal_handler_disconnect (acc_store, priv->accounts_handler);
234 if (priv->window_list) {
235 GList *iter = priv->window_list;
236 /* unregister pending windows */
238 ModestWindow *window = (ModestWindow *) iter->data;
239 iter = g_list_next (iter);
240 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), window);
242 g_list_free (priv->window_list);
243 priv->window_list = NULL;
246 /* Free the hash table with the handlers */
247 if (priv->destroy_handlers) {
248 g_hash_table_destroy (priv->destroy_handlers);
249 priv->destroy_handlers = NULL;
252 if (priv->viewer_handlers) {
253 g_hash_table_destroy (priv->viewer_handlers);
254 priv->viewer_handlers = NULL;
257 modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids);
258 priv->modal_handler_uids = NULL;
260 if (priv->modal_windows) {
261 g_mutex_lock (priv->queue_lock);
262 g_queue_free (priv->modal_windows);
263 priv->modal_windows = NULL;
264 g_mutex_unlock (priv->queue_lock);
266 g_mutex_free (priv->queue_lock);
268 /* Do not unref priv->main_window because it does not hold a
271 G_OBJECT_CLASS(parent_class)->finalize (obj);
275 modest_hildon2_window_mgr_new (void)
277 return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_HILDON2_WINDOW_MGR, NULL));
281 modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self)
283 ModestHildon2WindowMgrPrivate *priv = NULL;
284 gboolean ret_value = FALSE;
286 HildonWindowStack *stack;
287 gboolean failed = FALSE;
289 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
290 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
292 stack = hildon_window_stack_get_default ();
294 while ((window = hildon_window_stack_peek (stack)) != NULL) {
295 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &ret_value);
296 if (ret_value == TRUE) {
306 compare_msguids (ModestWindow *win,
309 const gchar *msg_uid;
311 if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win)))
314 /* Get message uid from msg window */
315 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
316 msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win));
317 if (msg_uid && uid &&!strcmp (msg_uid, uid))
320 msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
323 if (msg_uid && uid &&!strcmp (msg_uid, uid))
330 compare_headers (ModestWindow *win,
333 TnyHeader *my_header;
336 if (!MODEST_IS_MSG_VIEW_WINDOW (win))
339 /* Get message uid from msg window */
340 my_header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
342 if (my_header == header)
344 g_object_unref (my_header);
351 modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
354 ModestHildon2WindowMgrPrivate *priv = NULL;
356 gboolean has_header, has_window = FALSE;
359 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
360 g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
362 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
364 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_header (self, header, win);
366 uid = modest_tny_folder_get_header_unique_id (header);
368 item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids);
372 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
373 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
374 g_debug ("not a valid window!");
376 g_debug ("found a window");
377 *win = MODEST_WINDOW (item->data);
383 return has_header || has_window;
387 modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
390 ModestHildon2WindowMgrPrivate *priv = NULL;
391 gboolean has_header, has_window = FALSE;
394 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
395 g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
397 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
399 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_message_uid (self, msg_uid, win);
401 item = g_list_find_custom (priv->window_list, msg_uid, (GCompareFunc) compare_msguids);
405 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
406 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
407 g_debug ("not a valid window!");
409 g_debug ("found a window");
410 *win = MODEST_WINDOW (item->data);
415 return has_header || has_window;
419 modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self)
421 ModestHildon2WindowMgrPrivate *priv;
423 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
424 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
426 return g_list_copy (priv->window_list);
429 static gint window_precedence (GtkWindow *window)
431 if (MODEST_IS_ACCOUNTS_WINDOW (window)) {
433 } else if (MODEST_IS_MAILBOXES_WINDOW (window)) {
435 } else if (MODEST_IS_FOLDER_WINDOW (window)) {
437 } else if (MODEST_IS_HEADER_WINDOW (window)) {
439 } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
441 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
449 modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
450 ModestWindow *window,
451 ModestWindow *parent)
454 ModestHildon2WindowMgrPrivate *priv;
456 HildonWindowStack *stack;
457 gboolean nested_msg = FALSE;
458 ModestWindow *current_top;
459 const gchar *acc_name, *toplevel_acc_name;
461 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
462 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
464 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
466 /* Try to close active modal dialogs */
467 if (modest_window_mgr_get_num_windows (self) &&
468 !_modest_window_mgr_close_active_modals (self))
471 stack = hildon_window_stack_get_default ();
472 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
474 win = g_list_find (priv->window_list, window);
476 /* this is for the case we want to register the window
477 and it was already registered */
478 gtk_window_present (GTK_WINDOW (window));
482 /* Do not allow standalone editors or standalone viewers */
484 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
485 MODEST_IS_MSG_EDIT_WINDOW (window)))
486 modest_window_mgr_show_initial_window (self);
488 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
492 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
494 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
497 uid = modest_tny_folder_get_header_unique_id (header);
498 /* Embedded messages do not have uid */
500 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
501 g_debug ("%s found another view window showing the same header", __FUNCTION__);
503 g_object_unref (header);
508 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
509 g_debug ("%s found another view window showing the same header", __FUNCTION__);
510 g_object_unref (header);
515 g_object_unref (header);
519 * * toplevel = msg edit -> if not modified, close, if modified, stay
520 * * same account -> no action
521 * * window = accounts -> no action
522 * * window = folders, mailboxes, headers: close all up to accounts window
525 if (MODEST_IS_MSG_EDIT_WINDOW (current_top) &&
526 !modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (current_top))) {
529 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
530 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
533 if (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
534 (current_top && MODEST_IS_ACCOUNTS_WINDOW (window))) {
535 gtk_window_present (GTK_WINDOW (current_top));
539 acc_name = modest_window_get_active_account (window);
541 if (MODEST_IS_MSG_VIEW_WINDOW (current_top) ||
542 MODEST_IS_HEADER_WINDOW (current_top) ||
543 MODEST_IS_FOLDER_WINDOW (current_top) ||
544 MODEST_IS_MAILBOXES_WINDOW (current_top)) {
545 toplevel_acc_name = modest_window_get_active_account (current_top);
547 if (acc_name != NULL && g_strcmp0 (toplevel_acc_name, acc_name) == 0) {
548 /* Same account, no action */
550 if (window_precedence (GTK_WINDOW (current_top)) >= window_precedence (GTK_WINDOW (window))) {
551 if (!(MODEST_IS_MSG_VIEW_WINDOW (current_top) && MODEST_IS_MSG_VIEW_WINDOW (window))) {
552 gtk_window_present (GTK_WINDOW (current_top));
557 while (current_top && !MODEST_IS_ACCOUNTS_WINDOW (current_top)) {
559 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
562 gtk_window_present (GTK_WINDOW (current_top));
565 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
570 /* Trying to open a folders window and a mailboxes window at
571 the same time from the accounts window is not allowed */
572 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
573 MODEST_IS_FOLDER_WINDOW (window) &&
574 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
575 gtk_window_present (GTK_WINDOW (window));
579 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
580 g_debug ("Trying to register a second header window is not allowed");
581 gtk_window_present (GTK_WINDOW (current_top));
585 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
588 /* Add to list. Keep a reference to the window */
589 g_object_ref (window);
590 priv->window_list = g_list_prepend (priv->window_list, window);
592 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
593 MODEST_IS_MSG_VIEW_WINDOW (parent);
595 /* Close views if they're being shown. Nevertheless we must
596 allow nested messages */
598 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
599 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
602 /* If the current view has modal dialogs then
603 we fail to register the new view */
604 if ((current_top != NULL) &&
605 window_has_modals (MODEST_WINDOW (current_top))) {
606 /* Window on top but it has opened dialogs */
610 /* Close the current view */
611 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
613 /* Cancelled closing top window, then we fail to register */
618 /* Listen to object destruction */
619 handler_id = g_malloc0 (sizeof (gint));
620 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
621 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
623 if (!MODEST_IS_MSG_EDIT_WINDOW (window) &&
624 !MODEST_IS_ACCOUNTS_WINDOW (window)) {
625 acc_name = modest_window_get_active_account (window);
628 modest_platform_remove_new_mail_notifications (FALSE, acc_name);
629 modest_account_mgr_set_has_new_mails (modest_runtime_get_account_mgr (),
635 /* Show toolbar always */
636 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
637 gboolean show_toolbar;
638 show_toolbar = modest_conf_get_bool (modest_runtime_get_conf (), MODEST_CONF_EDIT_WINDOW_SHOW_TOOLBAR, NULL);
639 modest_window_show_toolbar (window, show_toolbar);
641 modest_window_show_toolbar (window, TRUE);
646 /* Add to list. Keep a reference to the window */
647 priv->window_list = g_list_remove (priv->window_list, window);
648 g_object_unref (window);
649 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
651 gtk_window_present (GTK_WINDOW (current_top));
656 cancel_window_operations (ModestWindow *window)
658 GSList* pending_ops = NULL;
660 /* cancel open and receive operations */
661 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
663 while (pending_ops != NULL) {
664 ModestMailOperationTypeOperation type;
665 GSList* tmp_list = NULL;
667 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
668 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
669 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
670 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
671 modest_mail_operation_cancel (pending_ops->data);
673 g_object_unref (G_OBJECT (pending_ops->data));
674 tmp_list = pending_ops;
675 pending_ops = g_slist_next (pending_ops);
676 g_slist_free_1 (tmp_list);
681 window_has_modals (ModestWindow *window)
685 gboolean retvalue = FALSE;
687 /* First we fetch all toplevels */
688 toplevels = gtk_window_list_toplevels ();
689 for (node = toplevels; node != NULL; node = g_list_next (node)) {
690 if (GTK_IS_WINDOW (node->data) &&
691 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (window) &&
692 GTK_WIDGET_VISIBLE (node->data)) {
697 g_list_free (toplevels);
702 on_window_destroy (ModestWindow *window,
704 ModestHildon2WindowMgr *self)
706 gboolean no_propagate = FALSE;
708 /* Do not close the window if it has modals on top */
709 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
712 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
713 gboolean sent = FALSE;
714 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
715 /* Save currently edited message to Drafts if it was not sent */
716 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
717 ModestMsgEditWindow *edit_window;
720 edit_window = MODEST_MSG_EDIT_WINDOW (window);
721 data = modest_msg_edit_window_get_msg_data (edit_window);
725 guint64 parts_size, available_size, expected_size;
727 available_size = modest_utils_get_available_space (NULL);
728 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
729 expected_size = modest_tny_msg_estimate_size (data->plain_body,
733 modest_msg_edit_window_free_msg_data (edit_window, data);
736 /* If there is not enough space
737 available for saving the message
738 then show an error and close the
739 window without saving */
740 if (expected_size >= available_size) {
741 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
742 _("mail_in_ui_save_error"),
745 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
749 g_warning ("Edit window without message data. This is probably a bug");
754 /* Unregister window */
755 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
756 no_propagate = FALSE;
762 modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
763 ModestWindow *window)
766 ModestHildon2WindowMgrPrivate *priv;
767 gulong *tmp, handler_id;
770 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
771 g_return_if_fail (MODEST_IS_WINDOW (window));
773 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
775 win = g_list_find (priv->window_list, window);
777 g_debug ("Trying to unregister a window that has not being registered yet");
781 /* Remove the viewer window handler from the hash table. The
782 HashTable could not exist if the main window was closed
783 when there were other windows remaining */
784 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
785 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
786 /* If the viewer was created without a main window
787 (for example when opening a message through D-Bus
788 the viewer handlers was not registered */
790 g_signal_handler_disconnect (window, *tmp);
791 g_hash_table_remove (priv->viewer_handlers, window);
795 /* Remove from list & hash table */
796 priv->window_list = g_list_remove_link (priv->window_list, win);
797 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
800 g_hash_table_remove (priv->destroy_handlers, window);
802 /* cancel open and receive operations */
803 cancel_window_operations (window);
805 /* Disconnect the "window-state-event" handler, we won't need it anymore */
806 if (priv->window_state_uids) {
807 priv->window_state_uids =
808 modest_signal_mgr_disconnect (priv->window_state_uids,
810 "notify::is-topmost");
813 /* Disconnect the "delete-event" handler, we won't need it anymore */
814 g_signal_handler_disconnect (window, handler_id);
816 /* Destroy the window */
817 g_object_unref (win->data);
820 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
822 /* We have to get the number of windows here in order not to
823 emit the signal too many times */
824 num_windows = modest_window_mgr_get_num_windows (self);
826 /* If there are no more windows registered emit the signal */
827 if (num_windows == 0)
828 g_signal_emit_by_name (self, "window-list-empty");
833 modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
836 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
842 modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
848 modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
850 gboolean show_toolbars,
853 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
859 modest_hildon2_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show)
861 ModestHildon2WindowMgrPrivate *priv;
862 ModestWindow *result;
864 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
865 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
867 /* TODO: make this return NULL always */
869 result = MODEST_WINDOW_MGR_CLASS (parent_class)->get_main_window (self, FALSE);
870 /* create the main window, if it hasn't been created yet */
871 if (!result && show) {
872 /* modest_window_mgr_register_window will set priv->main_window */
873 result = modest_main_window_new ();
874 /* We have to remove all other windows */
875 if (!modest_window_mgr_close_all_windows (self)) {
876 gtk_widget_destroy (GTK_WIDGET (result));
879 if (!modest_window_mgr_register_window (self, result, NULL)) {
880 gtk_widget_destroy (GTK_WIDGET (result));
884 g_debug ("%s: created main window: %p\n", __FUNCTION__, result);
888 gtk_widget_show_all (GTK_WIDGET (result));
889 gtk_window_present (GTK_WINDOW (result));
896 look_for_transient (gconstpointer a,
899 GtkWindow *win, *child;
904 child = (GtkWindow *) b;
905 win = (GtkWindow *) a;
907 if ((gtk_window_get_transient_for (win) == child) &&
908 GTK_WIDGET_VISIBLE (win))
915 modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self)
917 ModestHildon2WindowMgrPrivate *priv;
918 GList *toplevel_list;
919 GtkWidget *current_top, *toplevel;
920 HildonWindowStack *stack;
922 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
923 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
925 /* Get current top */
926 stack = hildon_window_stack_get_default ();
927 current_top = hildon_window_stack_peek (stack);
928 toplevel = current_top;
929 toplevel_list = gtk_window_list_toplevels ();
934 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
936 toplevel = (GtkWidget *) parent_link->data;
941 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
942 return (GtkWindow *) toplevel;
949 modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
953 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
954 g_return_if_fail (GTK_IS_WINDOW (window));
956 gtk_window_set_modal (window, TRUE);
957 gtk_window_set_transient_for (window, parent);
958 gtk_window_set_destroy_with_parent (window, TRUE);
960 if (!gtk_window_has_toplevel_focus (window)) {
961 GList *toplevels, *node;
963 toplevels = gtk_window_list_toplevels ();
964 for (node = toplevels; node != NULL; node = g_list_next (node)) {
965 if (gtk_window_has_toplevel_focus (GTK_WINDOW (node->data))) {
966 if (GTK_IS_DIALOG (node->data)) {
967 gtk_window_set_transient_for (window, GTK_WINDOW (node->data));
976 close_all_but_first (gpointer data)
980 HildonWindowStack *stack;
982 stack = hildon_window_stack_get_default ();
983 g_return_if_fail (stack);
985 num_windows = hildon_window_stack_size (stack);
987 for (i = 0; i < (num_windows - 1); i++) {
988 GtkWidget *current_top;
991 current_top = hildon_window_stack_peek (stack);
992 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
997 on_idle_close_all_but_first (gpointer data)
999 gdk_threads_enter ();
1000 close_all_but_first (data);
1001 gdk_threads_leave ();
1007 on_account_removed (TnyAccountStore *acc_store,
1008 TnyAccount *account,
1011 HildonWindowStack *stack;
1012 ModestWindow *current_top;
1014 /* Ignore transport account removals */
1015 if (TNY_IS_TRANSPORT_ACCOUNT (account))
1018 stack = hildon_window_stack_get_default ();
1019 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
1021 /* if we're showing the header view of the currently deleted
1022 account, or the outbox and we deleted the last account,
1023 then close the window */
1025 (MODEST_IS_HEADER_WINDOW (current_top) ||
1026 MODEST_IS_FOLDER_WINDOW (current_top))) {
1027 const gchar *acc_name;
1029 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
1031 /* We emit it in an idle, because sometimes this
1032 function could called when the account settings
1033 dialog is about to close but still there. That
1034 modal dialog would otherwise, prevent the
1035 windows from being closed */
1036 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
1037 g_idle_add (on_idle_close_all_but_first, NULL);
1041 static ModestWindow *
1042 modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self)
1044 ModestWindow *initial_window = NULL;
1045 ModestHildon2WindowMgrPrivate *priv;
1047 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1049 /* Connect to the account store "account-removed" signal". We
1050 do this here because in the init the singletons are still
1051 not initialized properly */
1052 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
1053 priv->accounts_handler)) {
1054 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
1056 G_CALLBACK (on_account_removed),
1060 /* Return accounts window */
1061 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
1062 modest_window_mgr_register_window (self, initial_window, NULL);
1064 return initial_window;
1068 static ModestWindow *
1069 modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self)
1071 HildonWindowStack *stack;
1072 stack = hildon_window_stack_get_default ();
1073 return (ModestWindow *) hildon_window_stack_peek (stack);
1077 find_folder_window (gconstpointer a,
1080 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
1084 modest_hildon2_window_mgr_get_folder_window (ModestHildon2WindowMgr *self)
1086 ModestHildon2WindowMgrPrivate *priv;
1089 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
1091 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1093 window = g_list_find_custom (priv->window_list,
1095 find_folder_window);
1097 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
1101 modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self)
1103 ModestHildon2WindowMgrPrivate *priv = NULL;
1105 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
1107 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1109 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
1113 modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self)
1115 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
1117 modest_accounts_window_pre_create ();
1119 MODEST_WINDOW_MGR_CLASS(parent_class)->create_caches (self);
1123 osso_display_event_cb (osso_display_state_t state,
1126 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (data);
1128 priv->display_state = state;
1130 /* Stop blinking if the screen becomes on */
1131 if (priv->display_state == OSSO_DISPLAY_ON)
1132 modest_platform_remove_new_mail_notifications (TRUE, NULL);
1136 modest_hildon2_window_mgr_close_all_but_initial (ModestWindowMgr *self)
1140 /* Exit if there are no windows */
1141 if (!modest_window_mgr_get_num_windows (self)) {
1142 g_warning ("%s: unable to close, there are no windows", __FUNCTION__);
1146 /* Close active modals */
1147 if (!_modest_window_mgr_close_active_modals (self)) {
1148 g_debug ("%s: unable to close some dialogs", __FUNCTION__);
1152 /* Close all but first */
1153 top = modest_window_mgr_get_current_top (self);
1154 if (!MODEST_IS_ACCOUNTS_WINDOW (top))
1155 close_all_but_first (NULL);
1157 /* If some cannot be closed return */
1158 top = modest_window_mgr_get_current_top (self);
1159 if (!MODEST_IS_ACCOUNTS_WINDOW (top)) {
1160 g_debug ("%s: could not close some windows", __FUNCTION__);