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 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,
100 typedef struct _ModestHildon2WindowMgrPrivate ModestHildon2WindowMgrPrivate;
101 struct _ModestHildon2WindowMgrPrivate {
104 GQueue *modal_windows;
106 gboolean fullscreen_mode;
108 GHashTable *destroy_handlers;
109 GHashTable *viewer_handlers;
110 GSList *window_state_uids;
114 GSList *modal_handler_uids;
115 ModestWindow *current_top;
117 gulong accounts_handler;
120 osso_display_state_t display_state;
122 #define MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
123 MODEST_TYPE_HILDON2_WINDOW_MGR, \
124 ModestHildon2WindowMgrPrivate))
126 static GObjectClass *parent_class = NULL;
129 modest_hildon2_window_mgr_get_type (void)
131 static GType my_type = 0;
133 static const GTypeInfo my_info = {
134 sizeof(ModestHildon2WindowMgrClass),
135 NULL, /* base init */
136 NULL, /* base finalize */
137 (GClassInitFunc) modest_hildon2_window_mgr_class_init,
138 NULL, /* class finalize */
139 NULL, /* class data */
140 sizeof(ModestHildon2WindowMgr),
142 (GInstanceInitFunc) modest_hildon2_window_mgr_instance_init,
145 my_type = g_type_register_static (MODEST_TYPE_WINDOW_MGR,
146 "ModestHildon2WindowMgr",
153 modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass)
155 GObjectClass *gobject_class;
156 ModestWindowMgrClass *mgr_class;
158 gobject_class = (GObjectClass*) klass;
159 mgr_class = (ModestWindowMgrClass *) klass;
161 parent_class = g_type_class_peek_parent (klass);
162 gobject_class->finalize = modest_hildon2_window_mgr_finalize;
163 mgr_class->register_window = modest_hildon2_window_mgr_register_window;
164 mgr_class->unregister_window = modest_hildon2_window_mgr_unregister_window;
165 mgr_class->set_fullscreen_mode = modest_hildon2_window_mgr_set_fullscreen_mode;
166 mgr_class->get_fullscreen_mode = modest_hildon2_window_mgr_get_fullscreen_mode;
167 mgr_class->show_toolbars = modest_hildon2_window_mgr_show_toolbars;
168 mgr_class->get_main_window = modest_hildon2_window_mgr_get_main_window;
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->show_initial_window = modest_hildon2_window_mgr_show_initial_window;
176 mgr_class->get_current_top = modest_hildon2_window_mgr_get_current_top;
177 mgr_class->screen_is_on = modest_hildon2_window_mgr_screen_is_on;
178 mgr_class->create_caches = modest_hildon2_window_mgr_create_caches;
180 g_type_class_add_private (gobject_class, sizeof(ModestHildon2WindowMgrPrivate));
185 modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj)
187 ModestHildon2WindowMgrPrivate *priv;
189 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
190 priv->window_list = NULL;
191 priv->fullscreen_mode = FALSE;
192 priv->window_state_uids = NULL;
194 priv->modal_windows = g_queue_new ();
195 priv->queue_lock = g_mutex_new ();
197 /* Could not initialize it from gconf, singletons are not
199 priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
200 priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
202 priv->closing_time = 0;
204 priv->modal_handler_uids = NULL;
205 priv->display_state = OSSO_DISPLAY_ON;
207 /* Listen for changes in the screen, we don't want to show a
208 led pattern when the display is on for example */
209 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
210 osso_display_event_cb,
216 modest_hildon2_window_mgr_finalize (GObject *obj)
218 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
219 ModestTnyAccountStore *acc_store;
221 modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids);
222 priv->window_state_uids = NULL;
224 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
227 acc_store = modest_runtime_get_account_store ();
228 if (acc_store && g_signal_handler_is_connected (acc_store, priv->accounts_handler))
229 g_signal_handler_disconnect (acc_store, priv->accounts_handler);
231 if (priv->window_list) {
232 GList *iter = priv->window_list;
233 /* unregister pending windows */
235 ModestWindow *window = (ModestWindow *) iter->data;
236 iter = g_list_next (iter);
237 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), window);
239 g_list_free (priv->window_list);
240 priv->window_list = NULL;
243 /* Free the hash table with the handlers */
244 if (priv->destroy_handlers) {
245 g_hash_table_destroy (priv->destroy_handlers);
246 priv->destroy_handlers = NULL;
249 if (priv->viewer_handlers) {
250 g_hash_table_destroy (priv->viewer_handlers);
251 priv->viewer_handlers = NULL;
254 modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids);
255 priv->modal_handler_uids = NULL;
257 if (priv->modal_windows) {
258 g_mutex_lock (priv->queue_lock);
259 g_queue_free (priv->modal_windows);
260 priv->modal_windows = NULL;
261 g_mutex_unlock (priv->queue_lock);
263 g_mutex_free (priv->queue_lock);
265 /* Do not unref priv->main_window because it does not hold a
268 G_OBJECT_CLASS(parent_class)->finalize (obj);
272 modest_hildon2_window_mgr_new (void)
274 return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_HILDON2_WINDOW_MGR, NULL));
278 modest_hildon2_window_mgr_close_all_windows (ModestWindowMgr *self)
280 ModestHildon2WindowMgrPrivate *priv = NULL;
281 gboolean ret_value = FALSE;
283 HildonWindowStack *stack;
284 gboolean failed = FALSE;
286 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
287 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
289 stack = hildon_window_stack_get_default ();
291 while ((window = hildon_window_stack_peek (stack)) != NULL) {
292 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &ret_value);
293 if (ret_value == TRUE) {
303 compare_msguids (ModestWindow *win,
306 const gchar *msg_uid;
308 if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win)))
311 /* Get message uid from msg window */
312 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
313 msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win));
314 if (msg_uid && uid &&!strcmp (msg_uid, uid))
317 msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
320 if (msg_uid && uid &&!strcmp (msg_uid, uid))
327 compare_headers (ModestWindow *win,
330 TnyHeader *my_header;
333 if (!MODEST_IS_MSG_VIEW_WINDOW (win))
336 /* Get message uid from msg window */
337 my_header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
339 if (my_header == header)
341 g_object_unref (my_header);
348 modest_hildon2_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
351 ModestHildon2WindowMgrPrivate *priv = NULL;
353 gboolean has_header, has_window = FALSE;
356 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
357 g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
359 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
361 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_header (self, header, win);
363 uid = modest_tny_folder_get_header_unique_id (header);
365 item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids);
369 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
370 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
371 g_debug ("not a valid window!");
373 g_debug ("found a window");
374 *win = MODEST_WINDOW (item->data);
380 return has_header || has_window;
384 modest_hildon2_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
387 ModestHildon2WindowMgrPrivate *priv = NULL;
388 gboolean has_header, has_window = FALSE;
391 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
392 g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
394 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
396 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_message_uid (self, msg_uid, win);
398 item = g_list_find_custom (priv->window_list, msg_uid, (GCompareFunc) compare_msguids);
402 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
403 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
404 g_debug ("not a valid window!");
406 g_debug ("found a window");
407 *win = MODEST_WINDOW (item->data);
412 return has_header || has_window;
416 modest_hildon2_window_mgr_get_window_list (ModestWindowMgr *self)
418 ModestHildon2WindowMgrPrivate *priv;
420 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
421 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
423 return g_list_copy (priv->window_list);
427 modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
428 ModestWindow *window,
429 ModestWindow *parent)
432 ModestHildon2WindowMgrPrivate *priv;
434 HildonWindowStack *stack;
435 gboolean nested_msg = FALSE;
436 ModestWindow *current_top;
438 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
439 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
441 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
443 /* Try to close active modal dialogs */
444 if (modest_window_mgr_get_num_windows (self) &&
445 !_modest_window_mgr_close_active_modals (self))
448 stack = hildon_window_stack_get_default ();
449 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
451 win = g_list_find (priv->window_list, window);
453 /* this is for the case we want to register the window
454 and it was already registered */
455 gtk_window_present (GTK_WINDOW (window));
459 /* Do not allow standalone editors or standalone viewers */
461 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
462 MODEST_IS_MSG_EDIT_WINDOW (window)))
463 modest_window_mgr_show_initial_window (self);
465 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
469 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
471 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
474 uid = modest_tny_folder_get_header_unique_id (header);
475 /* Embedded messages do not have uid */
477 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
478 g_debug ("%s found another view window showing the same header", __FUNCTION__);
480 g_object_unref (header);
485 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
486 g_debug ("%s found another view window showing the same header", __FUNCTION__);
487 g_object_unref (header);
492 g_object_unref (header);
495 /* Do not go backwards */
496 if ((MODEST_IS_MSG_VIEW_WINDOW (current_top) ||
497 MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
498 MODEST_IS_HEADER_WINDOW (current_top)) &&
499 (MODEST_IS_FOLDER_WINDOW (window) ||
500 MODEST_IS_ACCOUNTS_WINDOW (window) ||
501 MODEST_IS_MAILBOXES_WINDOW (window))) {
502 gtk_window_present (GTK_WINDOW (current_top));
506 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_FOLDER_WINDOW (window)) {
509 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
512 gtk_window_present (GTK_WINDOW (current_top));
515 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
518 if (MODEST_IS_MAILBOXES_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
519 gtk_window_present (GTK_WINDOW (current_top));
523 /* Mailboxes window can not replace folder windows */
524 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
525 gtk_window_present (GTK_WINDOW (current_top));
529 /* Trying to open a folders window and a mailboxes window at
530 the same time from the accounts window is not allowed */
531 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
532 MODEST_IS_FOLDER_WINDOW (window) &&
533 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
534 gtk_window_present (GTK_WINDOW (window));
538 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
539 g_debug ("Trying to register a second header window is not allowed");
540 gtk_window_present (GTK_WINDOW (current_top));
544 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
547 /* Add to list. Keep a reference to the window */
548 g_object_ref (window);
549 priv->window_list = g_list_prepend (priv->window_list, window);
551 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
552 MODEST_IS_MSG_VIEW_WINDOW (parent);
554 /* Close views if they're being shown. Nevertheless we must
555 allow nested messages */
557 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
558 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
561 /* If the current view has modal dialogs then
562 we fail to register the new view */
563 if ((current_top != NULL) &&
564 window_has_modals (MODEST_WINDOW (current_top))) {
565 /* Window on top but it has opened dialogs */
569 /* Close the current view */
570 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
572 /* Cancelled closing top window, then we fail to register */
577 /* Listen to object destruction */
578 handler_id = g_malloc0 (sizeof (gint));
579 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
580 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
582 /* Show toolbar always */
583 modest_window_show_toolbar (window, TRUE);
587 /* Add to list. Keep a reference to the window */
588 priv->window_list = g_list_remove (priv->window_list, window);
589 g_object_unref (window);
590 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
592 gtk_window_present (GTK_WINDOW (current_top));
597 cancel_window_operations (ModestWindow *window)
599 GSList* pending_ops = NULL;
601 /* cancel open and receive operations */
602 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
604 while (pending_ops != NULL) {
605 ModestMailOperationTypeOperation type;
606 GSList* tmp_list = NULL;
608 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
609 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
610 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
611 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
612 modest_mail_operation_cancel (pending_ops->data);
614 g_object_unref (G_OBJECT (pending_ops->data));
615 tmp_list = pending_ops;
616 pending_ops = g_slist_next (pending_ops);
617 g_slist_free_1 (tmp_list);
622 window_has_modals (ModestWindow *window)
626 gboolean retvalue = FALSE;
628 /* First we fetch all toplevels */
629 toplevels = gtk_window_list_toplevels ();
630 for (node = toplevels; node != NULL; node = g_list_next (node)) {
631 if (GTK_IS_WINDOW (node->data) &&
632 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (window) &&
633 GTK_WIDGET_VISIBLE (node->data)) {
638 g_list_free (toplevels);
643 on_window_destroy (ModestWindow *window,
645 ModestHildon2WindowMgr *self)
647 gboolean no_propagate = FALSE;
649 /* Do not close the window if it has modals on top */
650 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
653 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
654 gboolean sent = FALSE;
655 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
656 /* Save currently edited message to Drafts if it was not sent */
657 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
658 ModestMsgEditWindow *edit_window;
661 edit_window = MODEST_MSG_EDIT_WINDOW (window);
662 data = modest_msg_edit_window_get_msg_data (edit_window);
666 guint64 parts_size, available_size, expected_size;
668 available_size = modest_utils_get_available_space (NULL);
669 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
670 expected_size = modest_tny_msg_estimate_size (data->plain_body,
674 modest_msg_edit_window_free_msg_data (edit_window, data);
677 /* If there is not enough space
678 available for saving the message
679 then show an error and close the
680 window without saving */
681 if (expected_size >= available_size) {
682 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
683 _("mail_in_ui_save_error"),
686 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
690 g_warning ("Edit window without message data. This is probably a bug");
695 /* Unregister window */
696 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
697 no_propagate = FALSE;
703 modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
704 ModestWindow *window)
707 ModestHildon2WindowMgrPrivate *priv;
708 gulong *tmp, handler_id;
711 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
712 g_return_if_fail (MODEST_IS_WINDOW (window));
714 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
716 win = g_list_find (priv->window_list, window);
718 g_debug ("Trying to unregister a window that has not being registered yet");
722 /* Remove the viewer window handler from the hash table. The
723 HashTable could not exist if the main window was closed
724 when there were other windows remaining */
725 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
726 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
727 /* If the viewer was created without a main window
728 (for example when opening a message through D-Bus
729 the viewer handlers was not registered */
731 g_signal_handler_disconnect (window, *tmp);
732 g_hash_table_remove (priv->viewer_handlers, window);
736 /* Remove from list & hash table */
737 priv->window_list = g_list_remove_link (priv->window_list, win);
738 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
741 g_hash_table_remove (priv->destroy_handlers, window);
743 /* cancel open and receive operations */
744 cancel_window_operations (window);
746 /* Disconnect the "window-state-event" handler, we won't need it anymore */
747 if (priv->window_state_uids) {
748 priv->window_state_uids =
749 modest_signal_mgr_disconnect (priv->window_state_uids,
751 "notify::is-topmost");
754 /* Disconnect the "delete-event" handler, we won't need it anymore */
755 g_signal_handler_disconnect (window, handler_id);
757 /* Destroy the window */
758 g_object_unref (win->data);
761 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
763 /* We have to get the number of windows here in order not to
764 emit the signal too many times */
765 num_windows = modest_window_mgr_get_num_windows (self);
767 /* If there are no more windows registered emit the signal */
768 if (num_windows == 0)
769 g_signal_emit_by_name (self, "window-list-empty");
774 modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
777 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
783 modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
789 modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
791 gboolean show_toolbars,
794 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
800 modest_hildon2_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show)
802 ModestHildon2WindowMgrPrivate *priv;
803 ModestWindow *result;
805 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
806 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
808 /* TODO: make this return NULL always */
810 result = MODEST_WINDOW_MGR_CLASS (parent_class)->get_main_window (self, FALSE);
811 /* create the main window, if it hasn't been created yet */
812 if (!result && show) {
813 /* modest_window_mgr_register_window will set priv->main_window */
814 result = modest_main_window_new ();
815 /* We have to remove all other windows */
816 if (!modest_window_mgr_close_all_windows (self)) {
817 gtk_widget_destroy (GTK_WIDGET (result));
820 if (!modest_window_mgr_register_window (self, result, NULL)) {
821 gtk_widget_destroy (GTK_WIDGET (result));
825 g_debug ("%s: created main window: %p\n", __FUNCTION__, result);
829 gtk_widget_show_all (GTK_WIDGET (result));
830 gtk_window_present (GTK_WINDOW (result));
837 look_for_transient (gconstpointer a,
840 GtkWindow *win, *child;
845 child = (GtkWindow *) b;
846 win = (GtkWindow *) a;
848 if ((gtk_window_get_transient_for (win) == child) &&
849 GTK_WIDGET_VISIBLE (win))
856 modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self)
858 ModestHildon2WindowMgrPrivate *priv;
859 GList *toplevel_list;
860 GtkWidget *current_top, *toplevel;
861 HildonWindowStack *stack;
863 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
864 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
866 /* Get current top */
867 stack = hildon_window_stack_get_default ();
868 current_top = hildon_window_stack_peek (stack);
869 toplevel = current_top;
870 toplevel_list = gtk_window_list_toplevels ();
875 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
877 toplevel = (GtkWidget *) parent_link->data;
882 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
883 return (GtkWindow *) toplevel;
890 modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
894 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
895 g_return_if_fail (GTK_IS_WINDOW (window));
897 gtk_window_set_modal (window, TRUE);
898 gtk_window_set_transient_for (window, parent);
899 gtk_window_set_destroy_with_parent (window, TRUE);
903 on_idle_close_all_but_first (gpointer data)
907 HildonWindowStack *stack;
909 stack = hildon_window_stack_get_default ();
910 g_return_val_if_fail (stack, FALSE);
912 num_windows = hildon_window_stack_size (stack);
914 for (i = 0; i < (num_windows - 1); i++) {
915 GtkWidget *current_top;
918 current_top = hildon_window_stack_peek (stack);
919 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
925 on_account_removed (TnyAccountStore *acc_store,
929 HildonWindowStack *stack;
930 ModestWindow *current_top;
932 /* Ignore transport account removals */
933 if (TNY_IS_TRANSPORT_ACCOUNT (account))
936 stack = hildon_window_stack_get_default ();
937 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
939 /* if we're showing the header view of the currently deleted
940 account, or the outbox and we deleted the last account,
941 then close the window */
943 (MODEST_IS_HEADER_WINDOW (current_top) ||
944 MODEST_IS_FOLDER_WINDOW (current_top))) {
945 const gchar *acc_name;
947 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
949 /* We emit it in an idle, because sometimes this
950 function could called when the account settings
951 dialog is about to close but still there. That
952 modal dialog would otherwise, prevent the
953 windows from being closed */
954 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
955 g_idle_add (on_idle_close_all_but_first, NULL);
959 static ModestWindow *
960 modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self)
962 ModestWindow *initial_window = NULL;
963 ModestHildon2WindowMgrPrivate *priv;
965 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
967 /* Connect to the account store "account-removed" signal". We
968 do this here because in the init the singletons are still
969 not initialized properly */
970 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
971 priv->accounts_handler)) {
972 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
974 G_CALLBACK (on_account_removed),
978 /* Return accounts window */
979 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
980 modest_window_mgr_register_window (self, initial_window, NULL);
982 return initial_window;
986 static ModestWindow *
987 modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self)
989 HildonWindowStack *stack;
990 stack = hildon_window_stack_get_default ();
991 return (ModestWindow *) hildon_window_stack_peek (stack);
995 find_folder_window (gconstpointer a,
998 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
1002 modest_hildon2_window_mgr_get_folder_window (ModestHildon2WindowMgr *self)
1004 ModestHildon2WindowMgrPrivate *priv;
1007 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
1009 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1011 window = g_list_find_custom (priv->window_list,
1013 find_folder_window);
1015 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
1019 modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self)
1021 ModestHildon2WindowMgrPrivate *priv = NULL;
1023 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
1025 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1027 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
1031 modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self)
1033 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
1035 modest_accounts_window_pre_create ();
1037 MODEST_WINDOW_MGR_CLASS(parent_class)->create_caches (self);
1042 osso_display_event_cb (osso_display_state_t state,
1045 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (data);
1047 priv->display_state = state;
1049 /* Stop blinking if the screen becomes on */
1050 if (priv->display_state == OSSO_DISPLAY_ON)
1051 modest_platform_remove_new_mail_notifications (TRUE);