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 "modest-window.h"
32 #include "modest-gtk-window-mgr.h"
33 #include "modest-msg-edit-window.h"
34 #include "modest-mailboxes-window.h"
35 #include "modest-header-window.h"
36 #include "modest-main-window.h"
37 #include "modest-window-mgr-priv.h"
38 #include "modest-conf.h"
39 #include "modest-defs.h"
40 #include "modest-signal-mgr.h"
41 #include "modest-runtime.h"
42 #include "modest-platform.h"
43 #include "modest-ui-actions.h"
44 #include "modest-debug.h"
45 #include "modest-tny-folder.h"
46 #include "modest-folder-window.h"
47 #include "modest-accounts-window.h"
48 #include "modest-maemo-utils.h"
49 #include "modest-utils.h"
50 #include "modest-tny-msg.h"
51 #include "modest-tny-account.h"
52 #include <modest-shell.h>
53 #include <tny-merge-folder.h>
55 /* 'private'/'protected' functions */
56 static void modest_gtk_window_mgr_class_init (ModestGtkWindowMgrClass *klass);
57 static void modest_gtk_window_mgr_instance_init (ModestGtkWindowMgr *obj);
58 static void modest_gtk_window_mgr_finalize (GObject *obj);
60 static gboolean on_window_destroy (ModestWindow *window,
62 ModestGtkWindowMgr *self);
64 static gboolean modest_gtk_window_mgr_register_window (ModestWindowMgr *self,
66 ModestWindow *parent);
67 static void modest_gtk_window_mgr_unregister_window (ModestWindowMgr *self,
68 ModestWindow *window);
69 static void modest_gtk_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
71 static gboolean modest_gtk_window_mgr_get_fullscreen_mode (ModestWindowMgr *self);
72 static void modest_gtk_window_mgr_show_toolbars (ModestWindowMgr *self,
74 gboolean show_toolbars,
76 static GtkWindow *modest_gtk_window_mgr_get_modal (ModestWindowMgr *self);
77 static void modest_gtk_window_mgr_set_modal (ModestWindowMgr *self,
80 static gboolean modest_gtk_window_mgr_find_registered_header (ModestWindowMgr *self,
83 static gboolean modest_gtk_window_mgr_find_registered_message_uid (ModestWindowMgr *self,
86 static GList *modest_gtk_window_mgr_get_window_list (ModestWindowMgr *self);
87 static gboolean modest_gtk_window_mgr_close_all_windows (ModestWindowMgr *self);
88 static gboolean modest_gtk_window_mgr_close_all_but_initial (ModestWindowMgr *self);
89 static gboolean window_has_modals (ModestWindow *window);
90 static ModestWindow *modest_gtk_window_mgr_show_initial_window (ModestWindowMgr *self);
91 static ModestWindow *modest_gtk_window_mgr_get_current_top (ModestWindowMgr *self);
92 static gboolean modest_gtk_window_mgr_screen_is_on (ModestWindowMgr *self);
93 static void modest_gtk_window_mgr_create_caches (ModestWindowMgr *self);
94 static void on_account_removed (TnyAccountStore *acc_store,
97 static ModestWindow *modest_gtk_window_mgr_get_folder_window (ModestWindowMgr *self);
99 typedef struct _ModestGtkWindowMgrPrivate ModestGtkWindowMgrPrivate;
100 struct _ModestGtkWindowMgrPrivate {
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 #define MODEST_GTK_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
120 MODEST_TYPE_GTK_WINDOW_MGR, \
121 ModestGtkWindowMgrPrivate))
123 static GObjectClass *parent_class = NULL;
126 modest_gtk_window_mgr_get_type (void)
128 static GType my_type = 0;
130 static const GTypeInfo my_info = {
131 sizeof(ModestGtkWindowMgrClass),
132 NULL, /* base init */
133 NULL, /* base finalize */
134 (GClassInitFunc) modest_gtk_window_mgr_class_init,
135 NULL, /* class finalize */
136 NULL, /* class data */
137 sizeof(ModestGtkWindowMgr),
139 (GInstanceInitFunc) modest_gtk_window_mgr_instance_init,
142 my_type = g_type_register_static (MODEST_TYPE_WINDOW_MGR,
143 "ModestGtkWindowMgr",
150 modest_gtk_window_mgr_class_init (ModestGtkWindowMgrClass *klass)
152 GObjectClass *gobject_class;
153 ModestWindowMgrClass *mgr_class;
155 gobject_class = (GObjectClass*) klass;
156 mgr_class = (ModestWindowMgrClass *) klass;
158 parent_class = g_type_class_peek_parent (klass);
159 gobject_class->finalize = modest_gtk_window_mgr_finalize;
160 mgr_class->register_window = modest_gtk_window_mgr_register_window;
161 mgr_class->unregister_window = modest_gtk_window_mgr_unregister_window;
162 mgr_class->set_fullscreen_mode = modest_gtk_window_mgr_set_fullscreen_mode;
163 mgr_class->get_fullscreen_mode = modest_gtk_window_mgr_get_fullscreen_mode;
164 mgr_class->show_toolbars = modest_gtk_window_mgr_show_toolbars;
165 mgr_class->get_modal = modest_gtk_window_mgr_get_modal;
166 mgr_class->set_modal = modest_gtk_window_mgr_set_modal;
167 mgr_class->find_registered_header = modest_gtk_window_mgr_find_registered_header;
168 mgr_class->find_registered_message_uid = modest_gtk_window_mgr_find_registered_message_uid;
169 mgr_class->get_window_list = modest_gtk_window_mgr_get_window_list;
170 mgr_class->close_all_windows = modest_gtk_window_mgr_close_all_windows;
171 mgr_class->close_all_but_initial = modest_gtk_window_mgr_close_all_but_initial;
172 mgr_class->show_initial_window = modest_gtk_window_mgr_show_initial_window;
173 mgr_class->get_current_top = modest_gtk_window_mgr_get_current_top;
174 mgr_class->screen_is_on = modest_gtk_window_mgr_screen_is_on;
175 mgr_class->create_caches = modest_gtk_window_mgr_create_caches;
176 mgr_class->get_folder_window = modest_gtk_window_mgr_get_folder_window;
178 g_type_class_add_private (gobject_class, sizeof(ModestGtkWindowMgrPrivate));
183 modest_gtk_window_mgr_instance_init (ModestGtkWindowMgr *obj)
185 ModestGtkWindowMgrPrivate *priv;
187 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE(obj);
188 priv->window_list = NULL;
189 priv->fullscreen_mode = FALSE;
190 priv->window_state_uids = NULL;
192 priv->modal_windows = g_queue_new ();
193 priv->queue_lock = g_mutex_new ();
195 /* Could not initialize it from gconf, singletons are not
197 priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
198 priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
200 priv->closing_time = 0;
202 priv->modal_handler_uids = NULL;
203 priv->shell = modest_shell_new ();
207 modest_gtk_window_mgr_finalize (GObject *obj)
209 ModestGtkWindowMgrPrivate *priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE(obj);
210 ModestTnyAccountStore *acc_store;
212 modest_signal_mgr_disconnect_all_and_destroy (priv->window_state_uids);
213 priv->window_state_uids = NULL;
215 acc_store = modest_runtime_get_account_store ();
216 if (acc_store && g_signal_handler_is_connected (acc_store, priv->accounts_handler))
217 g_signal_handler_disconnect (acc_store, priv->accounts_handler);
219 if (priv->window_list) {
220 GList *iter = priv->window_list;
221 /* unregister pending windows */
223 ModestWindow *window = (ModestWindow *) iter->data;
224 iter = g_list_next (iter);
225 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (obj), window);
227 g_list_free (priv->window_list);
228 priv->window_list = NULL;
231 /* Free the hash table with the handlers */
232 if (priv->destroy_handlers) {
233 g_hash_table_destroy (priv->destroy_handlers);
234 priv->destroy_handlers = NULL;
237 if (priv->viewer_handlers) {
238 g_hash_table_destroy (priv->viewer_handlers);
239 priv->viewer_handlers = NULL;
242 modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids);
243 priv->modal_handler_uids = NULL;
245 if (priv->modal_windows) {
246 g_mutex_lock (priv->queue_lock);
247 g_queue_free (priv->modal_windows);
248 priv->modal_windows = NULL;
249 g_mutex_unlock (priv->queue_lock);
251 g_mutex_free (priv->queue_lock);
253 G_OBJECT_CLASS(parent_class)->finalize (obj);
257 modest_gtk_window_mgr_new (void)
259 return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_GTK_WINDOW_MGR, NULL));
263 modest_gtk_window_mgr_close_all_windows (ModestWindowMgr *self)
265 ModestGtkWindowMgrPrivate *priv = NULL;
266 gboolean ret_value = FALSE;
268 gboolean failed = FALSE;
270 g_return_val_if_fail (MODEST_IS_GTK_WINDOW_MGR (self), FALSE);
271 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
273 while ((window = modest_shell_peek_window (MODEST_SHELL (priv->shell))) != NULL) {
274 ret_value = modest_shell_delete_window (MODEST_SHELL (priv->shell), window);
275 if (ret_value == TRUE) {
285 compare_msguids (ModestWindow *win,
288 const gchar *msg_uid;
290 if ((!MODEST_IS_MSG_EDIT_WINDOW (win)) && (!MODEST_IS_MSG_VIEW_WINDOW (win)))
293 /* Get message uid from msg window */
294 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
295 msg_uid = modest_msg_edit_window_get_message_uid (MODEST_MSG_EDIT_WINDOW (win));
296 if (msg_uid && uid &&!strcmp (msg_uid, uid))
299 msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win));
302 if (msg_uid && uid &&!strcmp (msg_uid, uid))
309 compare_headers (ModestWindow *win,
312 TnyHeader *my_header;
315 if (!MODEST_IS_MSG_VIEW_WINDOW (win))
318 /* Get message uid from msg window */
319 my_header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
321 if (my_header == header)
323 g_object_unref (my_header);
330 modest_gtk_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header,
333 ModestGtkWindowMgrPrivate *priv = NULL;
335 gboolean has_header, has_window = FALSE;
338 g_return_val_if_fail (MODEST_IS_GTK_WINDOW_MGR (self), FALSE);
339 g_return_val_if_fail (TNY_IS_HEADER(header), FALSE);
341 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
343 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_header (self, header, win);
345 uid = modest_tny_folder_get_header_unique_id (header);
347 item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids);
351 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
352 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
353 g_debug ("not a valid window!");
355 g_debug ("found a window");
356 *win = MODEST_WINDOW (item->data);
362 return has_header || has_window;
366 modest_gtk_window_mgr_find_registered_message_uid (ModestWindowMgr *self, const gchar *msg_uid,
369 ModestGtkWindowMgrPrivate *priv = NULL;
370 gboolean has_header, has_window = FALSE;
373 g_return_val_if_fail (MODEST_IS_GTK_WINDOW_MGR (self), FALSE);
374 g_return_val_if_fail (msg_uid && msg_uid[0] != '\0', FALSE);
376 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
378 has_header = MODEST_WINDOW_MGR_CLASS (parent_class)->find_registered_message_uid (self, msg_uid, win);
380 item = g_list_find_custom (priv->window_list, msg_uid, (GCompareFunc) compare_msguids);
384 if ((!MODEST_IS_MSG_VIEW_WINDOW(item->data)) &&
385 (!MODEST_IS_MSG_EDIT_WINDOW (item->data)))
386 g_debug ("not a valid window!");
388 g_debug ("found a window");
389 *win = MODEST_WINDOW (item->data);
394 return has_header || has_window;
398 modest_gtk_window_mgr_get_window_list (ModestWindowMgr *self)
400 ModestGtkWindowMgrPrivate *priv;
402 g_return_val_if_fail (MODEST_IS_GTK_WINDOW_MGR (self), NULL);
403 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
405 return g_list_copy (priv->window_list);
409 modest_gtk_window_mgr_register_window (ModestWindowMgr *self,
410 ModestWindow *window,
411 ModestWindow *parent)
414 ModestGtkWindowMgrPrivate *priv;
416 gboolean nested_msg = FALSE;
417 ModestWindow *current_top;
419 g_return_val_if_fail (MODEST_IS_GTK_WINDOW_MGR (self), FALSE);
420 g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
422 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
424 /* Try to close active modal dialogs */
425 if (modest_window_mgr_get_num_windows (self) &&
426 !_modest_window_mgr_close_active_modals (self))
429 current_top = (ModestWindow *) modest_shell_peek_window (MODEST_SHELL (priv->shell));
431 win = g_list_find (priv->window_list, window);
433 /* this is for the case we want to register the window
434 and it was already registered */
435 gtk_window_present (GTK_WINDOW (priv->shell));
439 /* Do not allow standalone editors or standalone viewers */
441 (MODEST_IS_MSG_VIEW_WINDOW (window) ||
442 MODEST_IS_MSG_EDIT_WINDOW (window)))
443 modest_window_mgr_show_initial_window (self);
445 if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
449 uid = g_strdup (modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (window)));
451 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (window));
454 uid = modest_tny_folder_get_header_unique_id (header);
455 /* Embedded messages do not have uid */
457 if (g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids)) {
458 g_debug ("%s found another view window showing the same header", __FUNCTION__);
460 g_object_unref (header);
465 if (g_list_find_custom (priv->window_list, header, (GCompareFunc) compare_headers)) {
466 g_debug ("%s found another view window showing the same header", __FUNCTION__);
467 g_object_unref (header);
472 g_object_unref (header);
475 /* Do not go backwards */
476 if ((MODEST_IS_MSG_VIEW_WINDOW (current_top) ||
477 MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
478 MODEST_IS_HEADER_WINDOW (current_top)) &&
479 (MODEST_IS_FOLDER_WINDOW (window) ||
480 MODEST_IS_ACCOUNTS_WINDOW (window) ||
481 MODEST_IS_MAILBOXES_WINDOW (window))) {
482 gtk_window_present (GTK_WINDOW (priv->shell));
486 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_FOLDER_WINDOW (window)) {
489 retval = modest_shell_delete_window (MODEST_SHELL (priv->shell), shell);
492 gtk_window_present (GTK_WINDOW (priv->shell));
495 current_top = (ModestWindow *) modest_shell_peek_window (MODEST_SHELL (priv->shell));
498 if (MODEST_IS_MAILBOXES_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
499 gtk_window_present (GTK_WINDOW (priv->shell));
503 /* Mailboxes window can not replace folder windows */
504 if (MODEST_IS_FOLDER_WINDOW (current_top) && MODEST_IS_MAILBOXES_WINDOW (window)) {
505 gtk_window_present (GTK_WINDOW (priv->shell));
509 /* Trying to open a folders window and a mailboxes window at
510 the same time from the accounts window is not allowed */
511 if (MODEST_IS_MAILBOXES_WINDOW (current_top) &&
512 MODEST_IS_FOLDER_WINDOW (window) &&
513 MODEST_IS_ACCOUNTS_WINDOW (parent)) {
514 gtk_window_present (GTK_WINDOW (priv->shell));
518 if (MODEST_IS_HEADER_WINDOW (current_top) && MODEST_IS_HEADER_WINDOW (window)) {
519 g_debug ("Trying to register a second header window is not allowed");
520 gtk_window_present (GTK_WINDOW (priv->shell));
524 if (!MODEST_WINDOW_MGR_CLASS (parent_class)->register_window (self, window, parent))
527 /* Add to list. Keep a reference to the window */
528 g_object_ref (window);
529 priv->window_list = g_list_prepend (priv->window_list, window);
531 nested_msg = MODEST_IS_MSG_VIEW_WINDOW (window) &&
532 MODEST_IS_MSG_VIEW_WINDOW (parent);
534 /* Close views if they're being shown. Nevertheless we must
535 allow nested messages */
537 (MODEST_IS_MSG_EDIT_WINDOW (current_top) ||
538 MODEST_IS_MSG_VIEW_WINDOW (current_top))) {
541 /* If the current view has modal dialogs then
542 we fail to register the new view */
543 if ((current_top != NULL) &&
544 window_has_modals (MODEST_WINDOW (current_top))) {
545 /* Window on top but it has opened dialogs */
549 /* Close the current view */
550 retval = modest_shell_delete_window (MODEST_SHELL (priv->shell), current_top);
552 /* Cancelled closing top window, then we fail to register */
557 /* Listen to object destruction */
558 handler_id = g_malloc0 (sizeof (gint));
559 *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self);
560 g_hash_table_insert (priv->destroy_handlers, window, handler_id);
562 /* Show toolbar always */
563 modest_window_show_toolbar (window, TRUE);
565 modest_shell_add_window (MODEST_SHELL (priv->shell), window);
569 /* Add to list. Keep a reference to the window */
570 priv->window_list = g_list_remove (priv->window_list, window);
571 g_object_unref (window);
572 current_top = (ModestWindow *) modest_shell_peek_window (MODEST_SHELL (priv->shell));
574 gtk_window_present (GTK_WINDOW (priv->shell));
579 cancel_window_operations (ModestWindow *window)
581 GSList* pending_ops = NULL;
583 /* cancel open and receive operations */
584 pending_ops = modest_mail_operation_queue_get_by_source (modest_runtime_get_mail_operation_queue (),
586 while (pending_ops != NULL) {
587 ModestMailOperationTypeOperation type;
588 GSList* tmp_list = NULL;
590 type = modest_mail_operation_get_type_operation (MODEST_MAIL_OPERATION (pending_ops->data));
591 if (type == MODEST_MAIL_OPERATION_TYPE_RECEIVE ||
592 type == MODEST_MAIL_OPERATION_TYPE_OPEN ||
593 type == MODEST_MAIL_OPERATION_TYPE_SEND_AND_RECEIVE) {
594 modest_mail_operation_cancel (pending_ops->data);
596 g_object_unref (G_OBJECT (pending_ops->data));
597 tmp_list = pending_ops;
598 pending_ops = g_slist_next (pending_ops);
599 g_slist_free_1 (tmp_list);
604 window_has_modals (ModestWindow *window)
608 gboolean retvalue = FALSE;
610 /* First we fetch all toplevels */
611 toplevels = gtk_window_list_toplevels ();
612 for (node = toplevels; node != NULL; node = g_list_next (node)) {
613 if (GTK_IS_WINDOW (node->data) &&
614 gtk_window_get_transient_for (GTK_WINDOW (node->data)) == GTK_WINDOW (priv->shell) &&
615 GTK_WIDGET_VISIBLE (node->data)) {
620 g_list_free (toplevels);
625 on_window_destroy (ModestWindow *window,
627 ModestGtkWindowMgr *self)
629 gboolean no_propagate = FALSE;
631 /* Do not close the window if it has modals on top */
632 if (!MODEST_IS_MSG_EDIT_WINDOW (window) && window_has_modals (window))
635 if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
636 gboolean sent = FALSE;
637 sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window));
638 /* Save currently edited message to Drafts if it was not sent */
639 if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) {
640 ModestMsgEditWindow *edit_window;
643 edit_window = MODEST_MSG_EDIT_WINDOW (window);
644 data = modest_msg_edit_window_get_msg_data (edit_window);
648 guint64 parts_size, available_size, expected_size;
650 available_size = modest_utils_get_available_space (NULL);
651 modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
652 expected_size = modest_tny_msg_estimate_size (data->plain_body,
656 modest_msg_edit_window_free_msg_data (edit_window, data);
659 /* If there is not enough space
660 available for saving the message
661 then show an error and close the
662 window without saving */
663 if (expected_size >= available_size) {
664 modest_platform_run_information_dialog (GTK_WINDOW (edit_window),
665 _("mail_in_ui_save_error"),
668 if (!modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)))
672 g_warning ("Edit window without message data. This is probably a bug");
677 /* Unregister window */
678 modest_window_mgr_unregister_window (MODEST_WINDOW_MGR (self), window);
679 no_propagate = FALSE;
685 modest_gtk_window_mgr_unregister_window (ModestWindowMgr *self,
686 ModestWindow *window)
689 ModestGtkWindowMgrPrivate *priv;
690 gulong *tmp, handler_id;
693 g_return_if_fail (MODEST_IS_GTK_WINDOW_MGR (self));
694 g_return_if_fail (MODEST_IS_WINDOW (window));
696 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
698 win = g_list_find (priv->window_list, window);
700 g_debug ("Trying to unregister a window that has not being registered yet");
704 /* Remove the viewer window handler from the hash table. The
705 HashTable could not exist if the main window was closed
706 when there were other windows remaining */
707 if (MODEST_IS_MSG_VIEW_WINDOW (window) && priv->viewer_handlers) {
708 tmp = (gulong *) g_hash_table_lookup (priv->viewer_handlers, window);
709 /* If the viewer was created without a main window
710 (for example when opening a message through D-Bus
711 the viewer handlers was not registered */
713 g_signal_handler_disconnect (window, *tmp);
714 g_hash_table_remove (priv->viewer_handlers, window);
718 /* Remove from list & hash table */
719 priv->window_list = g_list_remove_link (priv->window_list, win);
720 tmp = g_hash_table_lookup (priv->destroy_handlers, window);
723 g_hash_table_remove (priv->destroy_handlers, window);
725 /* cancel open and receive operations */
726 cancel_window_operations (window);
728 /* Disconnect the "delete-event" handler, we won't need it anymore */
729 g_signal_handler_disconnect (window, handler_id);
731 /* Destroy the window */
732 g_object_unref (win->data);
735 MODEST_WINDOW_MGR_CLASS (parent_class)->unregister_window (self, window);
737 /* We have to get the number of windows here in order not to
738 emit the signal too many times */
739 num_windows = modest_window_mgr_get_num_windows (self);
741 /* If there are no more windows registered emit the signal */
742 if (num_windows == 0)
743 g_signal_emit_by_name (self, "window-list-empty");
748 modest_gtk_window_mgr_set_fullscreen_mode (ModestWindowMgr *self,
751 g_return_if_fail (MODEST_IS_GTK_WINDOW_MGR (self));
757 modest_gtk_window_mgr_get_fullscreen_mode (ModestWindowMgr *self)
763 modest_gtk_window_mgr_show_toolbars (ModestWindowMgr *self,
765 gboolean show_toolbars,
768 g_return_if_fail (MODEST_IS_GTK_WINDOW_MGR (self));
774 look_for_transient (gconstpointer a,
777 GtkWindow *win, *child;
782 child = (GtkWindow *) b;
783 win = (GtkWindow *) a;
785 if ((gtk_window_get_transient_for (win) == child) &&
786 GTK_WIDGET_VISIBLE (win))
793 modest_gtk_window_mgr_get_modal (ModestWindowMgr *self)
795 ModestGtkWindowMgrPrivate *priv;
796 GList *toplevel_list;
797 GtkWidget *current_top, *toplevel;
799 g_return_val_if_fail (MODEST_IS_GTK_WINDOW_MGR (self), NULL);
800 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
802 /* Get current top */
803 toplevel = priv->shell;
804 toplevel_list = gtk_window_list_toplevels ();
809 parent_link = g_list_find_custom (toplevel_list, toplevel, look_for_transient);
811 toplevel = (GtkWidget *) parent_link->data;
816 if (toplevel && GTK_WIDGET_VISIBLE (toplevel) && gtk_window_get_modal ((GtkWindow *) toplevel))
817 return (GtkWindow *) toplevel;
824 modest_gtk_window_mgr_set_modal (ModestWindowMgr *self,
828 g_return_if_fail (MODEST_IS_GTK_WINDOW_MGR (self));
829 g_return_if_fail (GTK_IS_WINDOW (window));
831 gtk_window_set_modal (window, TRUE);
832 gtk_window_set_transient_for (window, parent);
833 gtk_window_set_destroy_with_parent (window, TRUE);
837 close_all_but_first (gpointer data)
841 HildonWindowStack *stack;
843 stack = hildon_window_stack_get_default ();
844 g_return_if_fail (stack);
846 num_windows = hildon_window_stack_size (stack);
848 for (i = 0; i < (num_windows - 1); i++) {
849 GtkWidget *current_top;
852 current_top = modest_shell_peek_window (MODEST_SHELL (priv->shell));
853 retval = modest_shell_delete_window (MODEST_SHELL (priv->shell), current_top);
858 on_idle_close_all_but_first (gpointer data)
860 gdk_threads_enter ();
861 close_all_but_first (data);
862 gdk_threads_leave ();
868 on_account_removed (TnyAccountStore *acc_store,
872 ModestWindow *current_top;
874 /* Ignore transport account removals */
875 if (TNY_IS_TRANSPORT_ACCOUNT (account))
878 current_top = (ModestWindow *) modest_shell_peek_window (MODEST_SHELL (priv->shell));
880 /* if we're showing the header view of the currently deleted
881 account, or the outbox and we deleted the last account,
882 then close the window */
884 (MODEST_IS_HEADER_WINDOW (current_top) ||
885 MODEST_IS_FOLDER_WINDOW (current_top))) {
886 const gchar *acc_name;
888 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
890 /* We emit it in an idle, because sometimes this
891 function could called when the account settings
892 dialog is about to close but still there. That
893 modal dialog would otherwise, prevent the
894 windows from being closed */
895 if (!strcmp (acc_name, modest_window_get_active_account (current_top)))
896 g_idle_add (on_idle_close_all_but_first, NULL);
900 static ModestWindow *
901 modest_gtk_window_mgr_show_initial_window (ModestWindowMgr *self)
903 ModestWindow *initial_window = NULL;
904 ModestGtkWindowMgrPrivate *priv;
906 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
908 /* Connect to the account store "account-removed" signal". We
909 do this here because in the init the singletons are still
910 not initialized properly */
911 if (!g_signal_handler_is_connected (modest_runtime_get_account_store (),
912 priv->accounts_handler)) {
913 priv->accounts_handler = g_signal_connect (modest_runtime_get_account_store (),
915 G_CALLBACK (on_account_removed),
919 /* Return accounts window */
920 initial_window = MODEST_WINDOW (modest_accounts_window_new ());
921 modest_window_mgr_register_window (self, initial_window, NULL);
923 return initial_window;
927 static ModestWindow *
928 modest_gtk_window_mgr_get_current_top (ModestWindowMgr *self)
930 ModestWindow *initial_window = NULL;
931 ModestGtkWindowMgrPrivate *priv;
933 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
934 return (ModestWindow *) modest_shell_peek_window (MODEST_SHELL (priv->shell));
938 find_folder_window (gconstpointer a,
941 return (MODEST_IS_FOLDER_WINDOW (a)) ? 0 : 1;
944 static ModestWindow *
945 modest_gtk_window_mgr_get_folder_window (ModestWindowMgr *self)
947 ModestGtkWindowMgrPrivate *priv;
950 g_return_val_if_fail (MODEST_IS_GTK_WINDOW_MGR (self), NULL);
952 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
954 window = g_list_find_custom (priv->window_list,
958 return (window != NULL) ? MODEST_WINDOW (window->data) : NULL;
962 modest_gtk_window_mgr_screen_is_on (ModestWindowMgr *self)
964 ModestGtkWindowMgrPrivate *priv = NULL;
966 g_return_val_if_fail (MODEST_IS_GTK_WINDOW_MGR (self), FALSE);
968 priv = MODEST_GTK_WINDOW_MGR_GET_PRIVATE (self);
974 modest_gtk_window_mgr_create_caches (ModestWindowMgr *self)
976 g_return_if_fail (MODEST_IS_GTK_WINDOW_MGR (self));
978 modest_accounts_window_pre_create ();
980 MODEST_WINDOW_MGR_CLASS(parent_class)->create_caches (self);
984 modest_gtk_window_mgr_close_all_but_initial (ModestWindowMgr *self)
988 /* Exit if there are no windows */
989 if (!modest_window_mgr_get_num_windows (self)) {
990 g_warning ("%s: unable to close, there are no windows", __FUNCTION__);
994 /* Close active modals */
995 if (!_modest_window_mgr_close_active_modals (self)) {
996 g_debug ("%s: unable to close some dialogs", __FUNCTION__);
1000 /* Close all but first */
1001 top = modest_window_mgr_get_current_top (self);
1002 if (!MODEST_IS_ACCOUNTS_WINDOW (top))
1003 close_all_but_first (NULL);
1005 /* If some cannot be closed return */
1006 top = modest_window_mgr_get_current_top (self);
1007 if (!MODEST_IS_ACCOUNTS_WINDOW (top)) {
1008 g_debug ("%s: could not close some windows", __FUNCTION__);