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)) {
449 parent = (GtkWidget *) gtk_window_get_transient_for (GTK_WINDOW (modal));
451 /* Try to close it */
452 gtk_dialog_response (GTK_DIALOG (modal), GTK_RESPONSE_DELETE_EVENT);
454 /* Maybe the dialog was not closed, because a close
455 confirmation dialog for example. Then ignore the
457 if (GTK_IS_WINDOW (modal)) {
458 gtk_window_present (GTK_WINDOW (modal));
466 stack = hildon_window_stack_get_default ();
467 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
469 win = g_list_find (priv->window_list, window);
471 /* this is for the case we want to register the window
472 and it was already registered */
473 gtk_window_present (GTK_WINDOW (window));
477 /* Do not allow standalone editors or standalone viewers */
479 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
480 MODEST_IS_MSG_EDIT_WINDOW (window)))
481 modest_window_mgr_show_initial_window (self);
483 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
487 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
489 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
492 uid = modest_tny_folder_get_header_unique_id (header);
493 /* Embedded messages do not have uid */
495 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
496 g_debug ("%s found another view window showing the same header", __FUNCTION__);
498 g_object_unref (header);
503 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
504 g_debug ("%s found another view window showing the same header", __FUNCTION__);
505 g_object_unref (header);
510 g_object_unref (header);
513 /* Do not go backwards */
514 if ((MODEST_IS_MSG_VIEW_WINDOW (current_top) || MODEST_IS_MSG_EDIT_WINDOW (current_top)) &&
515 (MODEST_IS_FOLDER_WINDOW (window) || MODEST_IS_ACCOUNTS_WINDOW (window) ||
516 MODEST_IS_MAILBOXES_WINDOW (window))) {
517 gtk_window_present (GTK_WINDOW (window));
521 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_FOLDER_WINDOW (window)) {
522 gtk_window_present (GTK_WINDOW (window));
526 if (MODEST_IS_MAILBOXES_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
527 gtk_window_present (GTK_WINDOW (window));
531 /* Mailboxes window can not replace folder windows */
532 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
533 gtk_window_present (GTK_WINDOW (current_top));
537 /* Trying to open a folders window and a mailboxes window at
538 the same time from the accounts window is not allowed */
539 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
540 MODEST_IS_FOLDER_WINDOW (window) &&
541 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
542 gtk_window_present (GTK_WINDOW (window));
546 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
547 g_debug ("Trying to register a second header window is not allowed");
548 gtk_window_present (GTK_WINDOW (current_top));
552 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
555 /* Add to list. Keep a reference to the window */
556 g_object_ref (window);
557 priv->window_list = g_list_prepend (priv->window_list, window);
559 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
560 MODEST_IS_MSG_VIEW_WINDOW (parent);
562 /* Close views if they're being shown. Nevertheless we must
563 allow nested messages */
565 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
566 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
569 /* If the current view has modal dialogs then
570 we fail to register the new view */
571 if ((current_top != NULL) &&
572 window_has_modals (MODEST_WINDOW (current_top))) {
573 /* Window on top but it has opened dialogs */
577 /* Close the current view */
578 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
579 if (retval == TRUE) {
580 /* Cancelled closing top window, then we fail to register */
585 /* Listen to object destruction */
586 handler_id = g_malloc0 (sizeof (gint));
587 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
588 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
590 /* Show toolbar always */
591 modest_window_show_toolbar (window, TRUE);
595 /* Add to list. Keep a reference to the window */
596 priv->window_list = g_list_remove (priv->window_list, window);
597 g_object_unref (window);
598 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
600 gtk_window_present (GTK_WINDOW (current_top));
605 cancel_window_operations (ModestWindow *window)
607 GSList* pending_ops = NULL;
609 /* cancel open and receive operations */
610 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
612 while (pending_ops != NULL) {
613 ModestMailOperationTypeOperation type;
614 GSList* tmp_list = NULL;
616 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
617 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
618 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
619 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
620 modest_mail_operation_cancel (pending_ops->data);
622 g_object_unref (G_OBJECT (pending_ops->data));
623 tmp_list = pending_ops;
624 pending_ops = g_slist_next (pending_ops);
625 g_slist_free_1 (tmp_list);
630 window_has_modals (ModestWindow *window)
634 gboolean retvalue = FALSE;
636 /* First we fetch all toplevels */
637 toplevels = gtk_window_list_toplevels ();
638 for (node = toplevels; node != NULL; node = g_list_next (node)) {
639 if (GTK_IS_WINDOW (node->data) &&
640 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (window) &&
641 GTK_WIDGET_VISIBLE (node->data)) {
646 g_list_free (toplevels);
651 on_window_destroy (ModestWindow *window,
653 ModestHildon2WindowMgr *self)
655 gboolean no_propagate = FALSE;
657 /* Do not close the window if it has modals on top */
658 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
661 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
662 gboolean sent = FALSE;
663 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
664 /* Save currently edited message to Drafts if it was not sent */
665 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
666 ModestMsgEditWindow *edit_window;
669 edit_window = MODEST_MSG_EDIT_WINDOW (window);
670 data = modest_msg_edit_window_get_msg_data (edit_window);
674 guint64 parts_size, available_size, expected_size;
676 available_size = modest_utils_get_available_space (NULL);
677 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
678 expected_size = modest_tny_msg_estimate_size (data->plain_body,
682 modest_msg_edit_window_free_msg_data (edit_window, data);
685 /* If there is not enough space
686 available for saving the message
687 then show an error and close the
688 window without saving */
689 if (expected_size >= available_size) {
690 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
691 _("mail_in_ui_save_error"),
694 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
698 g_warning ("Edit window without message data. This is probably a bug");
703 /* Unregister window */
704 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
705 no_propagate = FALSE;
711 modest_hildon2_window_mgr_unregister_window (ModestWindowMgr *self,
712 ModestWindow *window)
715 ModestHildon2WindowMgrPrivate *priv;
716 gulong *tmp, handler_id;
719 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
720 g_return_if_fail (MODEST_IS_WINDOW (window));
722 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
724 win = g_list_find (priv->window_list, window);
726 g_debug ("Trying to unregister a window that has not being registered yet");
730 /* Remove the viewer window handler from the hash table. The
731 HashTable could not exist if the main window was closed
732 when there were other windows remaining */
733 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
734 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
735 /* If the viewer was created without a main window
736 (for example when opening a message through D-Bus
737 the viewer handlers was not registered */
739 g_signal_handler_disconnect (window, *tmp);
740 g_hash_table_remove (priv->viewer_handlers, window);
744 /* Remove from list & hash table */
745 priv->window_list = g_list_remove_link (priv->window_list, win);
746 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
749 g_hash_table_remove (priv->destroy_handlers, window);
751 /* cancel open and receive operations */
752 cancel_window_operations (window);
754 /* Disconnect the "window-state-event" handler, we won't need it anymore */
755 if (priv->window_state_uids) {
756 priv->window_state_uids =
757 modest_signal_mgr_disconnect (priv->window_state_uids,
759 "notify::is-topmost");
762 /* Disconnect the "delete-event" handler, we won't need it anymore */
763 g_signal_handler_disconnect (window, handler_id);
765 /* Destroy the window */
766 g_object_unref (win->data);
769 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
771 /* We have to get the number of windows here in order not to
772 emit the signal too many times */
773 num_windows = modest_window_mgr_get_num_windows (self);
775 /* If there are no more windows registered emit the signal */
776 if (num_windows == 0)
777 g_signal_emit_by_name (self, "window-list-empty");
782 modest_hildon2_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
785 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
791 modest_hildon2_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
797 modest_hildon2_window_mgr_show_toolbars (ModestWindowMgr *self,
799 gboolean show_toolbars,
802 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
808 modest_hildon2_window_mgr_get_main_window (ModestWindowMgr *self, gboolean show)
810 ModestHildon2WindowMgrPrivate *priv;
811 ModestWindow *result;
813 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
814 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
816 /* TODO: make this return NULL always */
818 result = MODEST_WINDOW_MGR_CLASS (parent_class)->get_main_window (self, FALSE);
819 /* create the main window, if it hasn't been created yet */
820 if (!result && show) {
821 /* modest_window_mgr_register_window will set priv->main_window */
822 result = modest_main_window_new ();
823 /* We have to remove all other windows */
824 if (!modest_window_mgr_close_all_windows (self)) {
825 gtk_widget_destroy (GTK_WIDGET (result));
828 if (!modest_window_mgr_register_window (self, result, NULL)) {
829 gtk_widget_destroy (GTK_WIDGET (result));
833 g_debug ("%s: created main window: %p\n", __FUNCTION__, result);
837 gtk_widget_show_all (GTK_WIDGET (result));
838 gtk_window_present (GTK_WINDOW (result));
845 look_for_transient (gconstpointer a,
848 GtkWindow *win, *child;
853 child = (GtkWindow *) b;
854 win = (GtkWindow *) a;
856 if (gtk_window_get_transient_for (win) == child)
863 modest_hildon2_window_mgr_get_modal (ModestWindowMgr *self)
865 ModestHildon2WindowMgrPrivate *priv;
866 GList *toplevel_list;
867 GtkWidget *current_top, *toplevel;
868 HildonWindowStack *stack;
870 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
871 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
873 /* Get current top */
874 stack = hildon_window_stack_get_default ();
875 current_top = hildon_window_stack_peek (stack);
876 toplevel = current_top;
877 toplevel_list = gtk_window_list_toplevels ();
882 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
884 toplevel = (GtkWidget *) parent_link->data;
889 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
890 return (GtkWindow *) toplevel;
897 modest_hildon2_window_mgr_set_modal (ModestWindowMgr *self,
901 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
902 g_return_if_fail (GTK_IS_WINDOW (window));
904 gtk_window_set_modal (window, TRUE);
905 gtk_window_set_transient_for (window, parent);
906 gtk_window_set_destroy_with_parent (window, TRUE);
910 on_idle_close_all_but_first (gpointer data)
914 HildonWindowStack *stack;
916 stack = hildon_window_stack_get_default ();
917 g_return_val_if_fail (stack, FALSE);
919 num_windows = hildon_window_stack_size (stack);
921 for (i = 0; i < (num_windows - 1); i++) {
922 GtkWidget *current_top;
925 current_top = hildon_window_stack_peek (stack);
926 g_signal_emit_by_name (G_OBJECT (current_top), "delete-event", NULL, &retval);
932 on_account_removed (TnyAccountStore *acc_store,
936 HildonWindowStack *stack;
937 ModestWindow *current_top;
939 /* Ignore transport account removals */
940 if (TNY_IS_TRANSPORT_ACCOUNT (account))
943 stack = hildon_window_stack_get_default ();
944 current_top = (ModestWindow *) hildon_window_stack_peek (stack);
946 /* if we're showing the header view of the currently deleted
947 account, or the outbox and we deleted the last account,
948 then close the window */
950 (MODEST_IS_HEADER_WINDOW (current_top) ||
951 MODEST_IS_FOLDER_WINDOW (current_top))) {
952 const gchar *acc_name;
954 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
956 /* We emit it in an idle, because sometimes this
957 function could called when the account settings
958 dialog is about to close but still there. That
959 modal dialog would otherwise, prevent the
960 windows from being closed */
961 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
962 g_idle_add (on_idle_close_all_but_first, NULL);
966 static ModestWindow *
967 modest_hildon2_window_mgr_show_initial_window (ModestWindowMgr *self)
969 ModestWindow *initial_window = NULL;
970 ModestHildon2WindowMgrPrivate *priv;
972 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
974 /* Connect to the account store "account-removed" signal". We
975 do this here because in the init the singletons are still
976 not initialized properly */
977 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
978 priv->accounts_handler)) {
979 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
981 G_CALLBACK (on_account_removed),
985 /* Return accounts window */
986 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
987 modest_window_mgr_register_window (self, initial_window, NULL);
989 return initial_window;
993 static ModestWindow *
994 modest_hildon2_window_mgr_get_current_top (ModestWindowMgr *self)
996 HildonWindowStack *stack;
997 stack = hildon_window_stack_get_default ();
998 return (ModestWindow *) hildon_window_stack_peek (stack);
1002 find_folder_window (gconstpointer a,
1005 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
1009 modest_hildon2_window_mgr_get_folder_window (ModestHildon2WindowMgr *self)
1011 ModestHildon2WindowMgrPrivate *priv;
1014 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), NULL);
1016 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1018 window = g_list_find_custom (priv->window_list,
1020 find_folder_window);
1022 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
1026 modest_hildon2_window_mgr_screen_is_on (ModestWindowMgr *self)
1028 ModestHildon2WindowMgrPrivate *priv = NULL;
1030 g_return_val_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self), FALSE);
1032 priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (self);
1034 return (priv->display_state == OSSO_DISPLAY_ON) ? TRUE : FALSE;
1038 modest_hildon2_window_mgr_create_caches (ModestWindowMgr *self)
1040 g_return_if_fail (MODEST_IS_HILDON2_WINDOW_MGR (self));
1042 modest_accounts_window_pre_create ();
1044 MODEST_WINDOW_MGR_CLASS(parent_class)->create_caches (self);
1049 osso_display_event_cb (osso_display_state_t state,
1052 ModestHildon2WindowMgrPrivate *priv = MODEST_HILDON2_WINDOW_MGR_GET_PRIVATE (data);
1054 priv->display_state = state;
1056 /* Stop blinking if the screen becomes on */
1057 if (priv->display_state == OSSO_DISPLAY_ON)
1058 modest_platform_remove_new_mail_notifications (TRUE);