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-conf.h"
39 #include "modest-defs.h"
40 #include "modest-signal-mgr.h"
41 #include "modest-runtime.h"
42 #include "modest-platform.h"
43 #include "modest-ui-actions.h"
44 #include "modest-debug.h"
45 #include "modest-tny-folder.h"
46 #include "modest-folder-window.h"
47 #include "modest-accounts-window.h"
48 #include "modest-maemo-utils.h"
49 #include "modest-utils.h"
50 #include "modest-tny-msg.h"
51 #include "modest-tny-account.h"
52 #include <tny-merge-folder.h>
54 /* 'private'/'protected' functions */
55 static void modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass);
56 static void modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj);
57 static void modest_hildon2_window_mgr_finalize (GObject *obj);
59 static gboolean on_window_destroy (ModestWindow *window,
61 ModestHildon2WindowMgr *self);
63 static gboolean modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
65 ModestWindow *parent);
66 static void modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
67 ModestWindow *window);
68 static void modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
70 static gboolean modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self);
71 static void modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
73 gboolean show_toolbars,
75 static ModestWindow* modest_hildon2_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show);
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 window_has_modals (ModestWindow *window);
89 static ModestWindow *modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self);
90 static ModestWindow *modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self);
91 static gboolean modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self);
92 static void modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self);
93 static void osso_display_event_cb (osso_display_state_t state,
95 static void on_account_removed (TnyAccountStore *acc_store,
99 typedef struct _ModestHildon2WindowMgrPrivate ModestHildon2WindowMgrPrivate;
100 struct _ModestHildon2WindowMgrPrivate {
103 GQueue *modal_windows;
105 gboolean fullscreen_mode;
107 GHashTable *destroy_handlers;
108 GHashTable *viewer_handlers;
109 GSList *window_state_uids;
113 GSList *modal_handler_uids;
114 ModestWindow *current_top;
116 gulong accounts_handler;
119 osso_display_state_t display_state;
121 #define MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
122 MODEST_TYPE_HILDON2_WINDOW_MGR, \
123 ModestHildon2WindowMgrPrivate))
125 static GObjectClass *parent_class = NULL;
128 modest_hildon2_window_mgr_get_type (void)
130 static GType my_type = 0;
132 static const GTypeInfo my_info = {
133 sizeof(ModestHildon2WindowMgrClass),
134 NULL, /* base init */
135 NULL, /* base finalize */
136 (GClassInitFunc) modest_hildon2_window_mgr_class_init,
137 NULL, /* class finalize */
138 NULL, /* class data */
139 sizeof(ModestHildon2WindowMgr),
141 (GInstanceInitFunc) modest_hildon2_window_mgr_instance_init,
144 my_type = g_type_register_static (MODEST_TYPE_WINDOW_MGR,
145 "ModestHildon2WindowMgr",
152 modest_hildon2_window_mgr_class_init (ModestHildon2WindowMgrClass *klass)
154 GObjectClass *gobject_class;
155 ModestWindowMgrClass *mgr_class;
157 gobject_class = (GObjectClass*) klass;
158 mgr_class = (ModestWindowMgrClass *) klass;
160 parent_class = g_type_class_peek_parent (klass);
161 gobject_class->finalize = modest_hildon2_window_mgr_finalize;
162 mgr_class->register_window = modest_hildon2_window_mgr_register_window;
163 mgr_class->unregister_window = modest_hildon2_window_mgr_unregister_window;
164 mgr_class->set_fullscreen_mode = modest_hildon2_window_mgr_set_fullscreen_mode;
165 mgr_class->get_fullscreen_mode = modest_hildon2_window_mgr_get_fullscreen_mode;
166 mgr_class->show_toolbars = modest_hildon2_window_mgr_show_toolbars;
167 mgr_class->get_main_window = modest_hildon2_window_mgr_get_main_window;
168 mgr_class->get_modal = modest_hildon2_window_mgr_get_modal;
169 mgr_class->set_modal = modest_hildon2_window_mgr_set_modal;
170 mgr_class->find_registered_header = modest_hildon2_window_mgr_find_registered_header;
171 mgr_class->find_registered_message_uid = modest_hildon2_window_mgr_find_registered_message_uid;
172 mgr_class->get_window_list = modest_hildon2_window_mgr_get_window_list;
173 mgr_class->close_all_windows = modest_hildon2_window_mgr_close_all_windows;
174 mgr_class->show_initial_window = modest_hildon2_window_mgr_show_initial_window;
175 mgr_class->get_current_top = modest_hildon2_window_mgr_get_current_top;
176 mgr_class->screen_is_on = modest_hildon2_window_mgr_screen_is_on;
177 mgr_class->create_caches = modest_hildon2_window_mgr_create_caches;
179 g_type_class_add_private (gobject_class, sizeof(ModestHildon2WindowMgrPrivate));
184 modest_hildon2_window_mgr_instance_init (ModestHildon2WindowMgr *obj)
186 ModestHildon2WindowMgrPrivate *priv;
188 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
189 priv->window_list = NULL;
190 priv->fullscreen_mode = FALSE;
191 priv->window_state_uids = NULL;
193 priv->modal_windows = g_queue_new ();
194 priv->queue_lock = g_mutex_new ();
196 /* Could not initialize it from gconf, singletons are not
198 priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
199 priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
201 priv->closing_time = 0;
203 priv->modal_handler_uids = NULL;
204 priv->display_state = OSSO_DISPLAY_ON;
206 /* Listen for changes in the screen, we don't want to show a
207 led pattern when the display is on for example */
208 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
209 osso_display_event_cb,
215 modest_hildon2_window_mgr_finalize (GObject *obj)
217 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE(obj);
218 ModestTnyAccountStore *acc_store;
220 modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids);
221 priv->window_state_uids = NULL;
223 osso_hw_set_display_event_cb (modest_maemo_utils_get_osso_context (),
226 acc_store = modest_runtime_get_account_store ();
227 if (acc_store && g_signal_handler_is_connected (acc_store, priv->accounts_handler))
228 g_signal_handler_disconnect (acc_store, priv->accounts_handler);
230 if (priv->window_list) {
231 GList *iter = priv->window_list;
232 /* unregister pending windows */
234 ModestWindow *window = (ModestWindow *) iter->data;
235 iter = g_list_next (iter);
236 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), window);
238 g_list_free (priv->window_list);
239 priv->window_list = NULL;
242 /* Free the hash table with the handlers */
243 if (priv->destroy_handlers) {
244 g_hash_table_destroy (priv->destroy_handlers);
245 priv->destroy_handlers = NULL;
248 if (priv->viewer_handlers) {
249 g_hash_table_destroy (priv->viewer_handlers);
250 priv->viewer_handlers = NULL;
253 modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids);
254 priv->modal_handler_uids = NULL;
256 if (priv->modal_windows) {
257 g_mutex_lock (priv->queue_lock);
258 g_queue_free (priv->modal_windows);
259 priv->modal_windows = NULL;
260 g_mutex_unlock (priv->queue_lock);
262 g_mutex_free (priv->queue_lock);
264 /* Do not unref priv->main_window because it does not hold a
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);
426 modest_hildon2_window_mgr_register_window (ModestWindowMgr *self,
427 ModestWindow *window,
428 ModestWindow *parent)
431 ModestHildon2WindowMgrPrivate *priv;
433 HildonWindowStack *stack;
434 gboolean nested_msg = FALSE;
435 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 /* Check that there is no active modal dialog */
444 modal = (GtkWidget *) modest_window_mgr_get_modal (self);
445 while (modal && GTK_IS_DIALOG (modal)) {
448 /* If it's a hildon note then don't try to close it as
449 this is the default behaviour of WM, delete event
450 is not issued for this kind of notes as we want the
451 user to always click on a button */
452 if (HILDON_IS_NOTE (modal)) {
453 gtk_window_present (GTK_WINDOW (modal));
458 parent = (GtkWidget *) gtk_window_get_transient_for (GTK_WINDOW (modal));
460 /* Try to close it */
461 gtk_dialog_response (GTK_DIALOG (modal), GTK_RESPONSE_DELETE_EVENT);
463 /* Maybe the dialog was not closed, because a close
464 confirmation dialog for example. Then ignore the
466 if (GTK_IS_WINDOW (modal)) {
467 gtk_window_present (GTK_WINDOW (modal));
475 stack = hildon_window_stack_get_default ();
476 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
478 win = g_list_find (priv->window_list, window);
480 /* this is for the case we want to register the window
481 and it was already registered */
482 gtk_window_present (GTK_WINDOW (window));
486 /* Do not allow standalone editors or standalone viewers */
488 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
489 MODEST_IS_MSG_EDIT_WINDOW (window)))
490 modest_window_mgr_show_initial_window (self);
492 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
496 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
498 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
501 uid = modest_tny_folder_get_header_unique_id (header);
502 /* Embedded messages do not have uid */
504 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
505 g_debug ("%s found another view window showing the same header", __FUNCTION__);
507 g_object_unref (header);
512 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
513 g_debug ("%s found another view window showing the same header", __FUNCTION__);
514 g_object_unref (header);
519 g_object_unref (header);
522 /* Do not go backwards */
523 if ((MODEST_IS_MSG_VIEW_WINDOW (current_top) ||
524 MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
525 MODEST_IS_HEADER_WINDOW (current_top)) &&
526 (MODEST_IS_FOLDER_WINDOW (window) ||
527 MODEST_IS_ACCOUNTS_WINDOW (window) ||
528 MODEST_IS_MAILBOXES_WINDOW (window))) {
529 gtk_window_present (GTK_WINDOW (current_top));
533 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_FOLDER_WINDOW (window)) {
536 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
539 gtk_window_present (GTK_WINDOW (current_top));
542 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
545 if (MODEST_IS_MAILBOXES_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
546 gtk_window_present (GTK_WINDOW (current_top));
550 /* Mailboxes window can not replace folder windows */
551 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
552 gtk_window_present (GTK_WINDOW (current_top));
556 /* Trying to open a folders window and a mailboxes window at
557 the same time from the accounts window is not allowed */
558 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
559 MODEST_IS_FOLDER_WINDOW (window) &&
560 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
561 gtk_window_present (GTK_WINDOW (window));
565 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
566 g_debug ("Trying to register a second header window is not allowed");
567 gtk_window_present (GTK_WINDOW (current_top));
571 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
574 /* Add to list. Keep a reference to the window */
575 g_object_ref (window);
576 priv->window_list = g_list_prepend (priv->window_list, window);
578 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
579 MODEST_IS_MSG_VIEW_WINDOW (parent);
581 /* Close views if they're being shown. Nevertheless we must
582 allow nested messages */
584 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
585 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
588 /* If the current view has modal dialogs then
589 we fail to register the new view */
590 if ((current_top != NULL) &&
591 window_has_modals (MODEST_WINDOW (current_top))) {
592 /* Window on top but it has opened dialogs */
596 /* Close the current view */
597 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
599 /* Cancelled closing top window, then we fail to register */
604 /* Listen to object destruction */
605 handler_id = g_malloc0 (sizeof (gint));
606 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
607 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
609 /* Show toolbar always */
610 modest_window_show_toolbar (window, TRUE);
614 /* Add to list. Keep a reference to the window */
615 priv->window_list = g_list_remove (priv->window_list, window);
616 g_object_unref (window);
617 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
619 gtk_window_present (GTK_WINDOW (current_top));
624 cancel_window_operations (ModestWindow *window)
626 GSList* pending_ops = NULL;
628 /* cancel open and receive operations */
629 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
631 while (pending_ops != NULL) {
632 ModestMailOperationTypeOperation type;
633 GSList* tmp_list = NULL;
635 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
636 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
637 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
638 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
639 modest_mail_operation_cancel (pending_ops->data);
641 g_object_unref (G_OBJECT (pending_ops->data));
642 tmp_list = pending_ops;
643 pending_ops = g_slist_next (pending_ops);
644 g_slist_free_1 (tmp_list);
649 window_has_modals (ModestWindow *window)
653 gboolean retvalue = FALSE;
655 /* First we fetch all toplevels */
656 toplevels = gtk_window_list_toplevels ();
657 for (node = toplevels; node != NULL; node = g_list_next (node)) {
658 if (GTK_IS_WINDOW (node->data) &&
659 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (window) &&
660 GTK_WIDGET_VISIBLE (node->data)) {
665 g_list_free (toplevels);
670 on_window_destroy (ModestWindow *window,
672 ModestHildon2WindowMgr *self)
674 gboolean no_propagate = FALSE;
676 /* Do not close the window if it has modals on top */
677 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
680 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
681 gboolean sent = FALSE;
682 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
683 /* Save currently edited message to Drafts if it was not sent */
684 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
685 ModestMsgEditWindow *edit_window;
688 edit_window = MODEST_MSG_EDIT_WINDOW (window);
689 data = modest_msg_edit_window_get_msg_data (edit_window);
693 guint64 parts_size, available_size, expected_size;
695 available_size = modest_utils_get_available_space (NULL);
696 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
697 expected_size = modest_tny_msg_estimate_size (data->plain_body,
701 modest_msg_edit_window_free_msg_data (edit_window, data);
704 /* If there is not enough space
705 available for saving the message
706 then show an error and close the
707 window without saving */
708 if (expected_size >= available_size) {
709 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
710 _("mail_in_ui_save_error"),
713 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
717 g_warning ("Edit window without message data. This is probably a bug");
722 /* Unregister window */
723 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
724 no_propagate = FALSE;
730 modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
731 ModestWindow *window)
734 ModestHildon2WindowMgrPrivate *priv;
735 gulong *tmp, handler_id;
738 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
739 g_return_if_fail (MODEST_IS_WINDOW (window));
741 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
743 win = g_list_find (priv->window_list, window);
745 g_debug ("Trying to unregister a window that has not being registered yet");
749 /* Remove the viewer window handler from the hash table. The
750 HashTable could not exist if the main window was closed
751 when there were other windows remaining */
752 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
753 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
754 /* If the viewer was created without a main window
755 (for example when opening a message through D-Bus
756 the viewer handlers was not registered */
758 g_signal_handler_disconnect (window, *tmp);
759 g_hash_table_remove (priv->viewer_handlers, window);
763 /* Remove from list & hash table */
764 priv->window_list = g_list_remove_link (priv->window_list, win);
765 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
768 g_hash_table_remove (priv->destroy_handlers, window);
770 /* cancel open and receive operations */
771 cancel_window_operations (window);
773 /* Disconnect the "window-state-event" handler, we won't need it anymore */
774 if (priv->window_state_uids) {
775 priv->window_state_uids =
776 modest_signal_mgr_disconnect (priv->window_state_uids,
778 "notify::is-topmost");
781 /* Disconnect the "delete-event" handler, we won't need it anymore */
782 g_signal_handler_disconnect (window, handler_id);
784 /* Destroy the window */
785 g_object_unref (win->data);
788 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
790 /* We have to get the number of windows here in order not to
791 emit the signal too many times */
792 num_windows = modest_window_mgr_get_num_windows (self);
794 /* If there are no more windows registered emit the signal */
795 if (num_windows == 0)
796 g_signal_emit_by_name (self, "window-list-empty");
801 modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
804 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
810 modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
816 modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
818 gboolean show_toolbars,
821 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
827 modest_hildon2_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show)
829 ModestHildon2WindowMgrPrivate *priv;
830 ModestWindow *result;
832 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
833 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
835 /* TODO: make this return NULL always */
837 result = MODEST_WINDOW_MGR_CLASS (parent_class)->get_main_window (self, FALSE);
838 /* create the main window, if it hasn't been created yet */
839 if (!result && show) {
840 /* modest_window_mgr_register_window will set priv->main_window */
841 result = modest_main_window_new ();
842 /* We have to remove all other windows */
843 if (!modest_window_mgr_close_all_windows (self)) {
844 gtk_widget_destroy (GTK_WIDGET (result));
847 if (!modest_window_mgr_register_window (self, result, NULL)) {
848 gtk_widget_destroy (GTK_WIDGET (result));
852 g_debug ("%s: created main window: %p\n", __FUNCTION__, result);
856 gtk_widget_show_all (GTK_WIDGET (result));
857 gtk_window_present (GTK_WINDOW (result));
864 look_for_transient (gconstpointer a,
867 GtkWindow *win, *child;
872 child = (GtkWindow *) b;
873 win = (GtkWindow *) a;
875 if ((gtk_window_get_transient_for (win) == child) &&
876 GTK_WIDGET_VISIBLE (win))
883 modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self)
885 ModestHildon2WindowMgrPrivate *priv;
886 GList *toplevel_list;
887 GtkWidget *current_top, *toplevel;
888 HildonWindowStack *stack;
890 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
891 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
893 /* Get current top */
894 stack = hildon_window_stack_get_default ();
895 current_top = hildon_window_stack_peek (stack);
896 toplevel = current_top;
897 toplevel_list = gtk_window_list_toplevels ();
902 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
904 toplevel = (GtkWidget *) parent_link->data;
909 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
910 return (GtkWindow *) toplevel;
917 modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
921 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
922 g_return_if_fail (GTK_IS_WINDOW (window));
924 gtk_window_set_modal (window, TRUE);
925 gtk_window_set_transient_for (window, parent);
926 gtk_window_set_destroy_with_parent (window, TRUE);
930 on_idle_close_all_but_first (gpointer data)
934 HildonWindowStack *stack;
936 stack = hildon_window_stack_get_default ();
937 g_return_val_if_fail (stack, FALSE);
939 num_windows = hildon_window_stack_size (stack);
941 for (i = 0; i < (num_windows - 1); i++) {
942 GtkWidget *current_top;
945 current_top = hildon_window_stack_peek (stack);
946 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
952 on_account_removed (TnyAccountStore *acc_store,
956 HildonWindowStack *stack;
957 ModestWindow *current_top;
959 /* Ignore transport account removals */
960 if (TNY_IS_TRANSPORT_ACCOUNT (account))
963 stack = hildon_window_stack_get_default ();
964 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
966 /* if we're showing the header view of the currently deleted
967 account, or the outbox and we deleted the last account,
968 then close the window */
970 (MODEST_IS_HEADER_WINDOW (current_top) ||
971 MODEST_IS_FOLDER_WINDOW (current_top))) {
972 const gchar *acc_name;
974 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
976 /* We emit it in an idle, because sometimes this
977 function could called when the account settings
978 dialog is about to close but still there. That
979 modal dialog would otherwise, prevent the
980 windows from being closed */
981 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
982 g_idle_add (on_idle_close_all_but_first, NULL);
986 static ModestWindow *
987 modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self)
989 ModestWindow *initial_window = NULL;
990 ModestHildon2WindowMgrPrivate *priv;
992 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
994 /* Connect to the account store "account-removed" signal". We
995 do this here because in the init the singletons are still
996 not initialized properly */
997 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
998 priv->accounts_handler)) {
999 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
1001 G_CALLBACK (on_account_removed),
1005 /* Return accounts window */
1006 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
1007 modest_window_mgr_register_window (self, initial_window, NULL);
1009 return initial_window;
1013 static ModestWindow *
1014 modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self)
1016 HildonWindowStack *stack;
1017 stack = hildon_window_stack_get_default ();
1018 return (ModestWindow *) hildon_window_stack_peek (stack);
1022 find_folder_window (gconstpointer a,
1025 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
1029 modest_hildon2_window_mgr_get_folder_window (ModestHildon2WindowMgr *self)
1031 ModestHildon2WindowMgrPrivate *priv;
1034 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
1036 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1038 window = g_list_find_custom (priv->window_list,
1040 find_folder_window);
1042 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
1046 modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self)
1048 ModestHildon2WindowMgrPrivate *priv = NULL;
1050 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
1052 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1054 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
1058 modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self)
1060 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
1062 modest_accounts_window_pre_create ();
1064 MODEST_WINDOW_MGR_CLASS(parent_class)->create_caches (self);
1069 osso_display_event_cb (osso_display_state_t state,
1072 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (data);
1074 priv->display_state = state;
1076 /* Stop blinking if the screen becomes on */
1077 if (priv->display_state == OSSO_DISPLAY_ON)
1078 modest_platform_remove_new_mail_notifications (TRUE);