X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Fwidgets%2Fmodest-window-mgr.c;h=d66cc14adbb898278947fff868bd6c0a75b757f4;hb=f8a806f78f538409b502f58f09f969186e908258;hp=91348d73ff946dd930bda8413f908ae7caa918e0;hpb=64e307fddcf056bc685688d37f07b806b619da60;p=modest diff --git a/src/widgets/modest-window-mgr.c b/src/widgets/modest-window-mgr.c index 91348d7..d66cc14 100644 --- a/src/widgets/modest-window-mgr.c +++ b/src/widgets/modest-window-mgr.c @@ -43,8 +43,11 @@ static void modest_window_mgr_class_init (ModestWindowMgrClass *klass); static void modest_window_mgr_init (ModestWindowMgr *obj); static void modest_window_mgr_finalize (GObject *obj); -static void on_window_destroy (ModestWindow *window, - ModestWindowMgr *self); +/* static void on_window_destroy (ModestWindow *window, */ +/* ModestWindowMgr *self); */ +static gboolean on_window_destroy (ModestWindow *window, + GdkEvent *event, + ModestWindowMgr *self); /* list my signals */ enum { @@ -62,7 +65,9 @@ struct _ModestWindowMgrPrivate { gboolean show_toolbars_fullscreen; GSList *windows_that_prevent_hibernation; + GSList *preregistered_uids; GHashTable *destroy_handlers; + GHashTable *viewer_handlers; }; #define MODEST_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_WINDOW_MGR, \ @@ -119,11 +124,14 @@ modest_window_mgr_init (ModestWindowMgr *obj) priv->main_window = NULL; priv->fullscreen_mode = FALSE; + priv->preregistered_uids = NULL; + /* Could not initialize it from gconf, singletons are not ready yet */ priv->show_toolbars = FALSE; priv->show_toolbars_fullscreen = FALSE; - priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + priv->destroy_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); } static void @@ -143,12 +151,21 @@ modest_window_mgr_finalize (GObject *obj) priv->window_list = NULL; } + g_slist_foreach (priv->preregistered_uids, (GFunc)g_free, NULL); + g_slist_free (priv->preregistered_uids); + + /* Free the hash table with the handlers */ if (priv->destroy_handlers) { - g_hash_table_unref (priv->destroy_handlers); + g_hash_table_destroy (priv->destroy_handlers); priv->destroy_handlers = NULL; } + if (priv->viewer_handlers) { + g_hash_table_destroy (priv->viewer_handlers); + priv->viewer_handlers = NULL; + } + /* Do not unref priv->main_window because it does not hold a new reference */ @@ -161,6 +178,170 @@ modest_window_mgr_new (void) return MODEST_WINDOW_MGR(g_object_new(MODEST_TYPE_WINDOW_MGR, NULL)); } + + + +/* do we have uid? */ +static gboolean +has_uid (GSList *list, const gchar *uid) +{ + GSList *cursor = list; + + if (!uid) + return FALSE; + + while (cursor) { + if (cursor->data && strcmp (cursor->data, uid) == 0) + return TRUE; + cursor = g_slist_next (cursor); + } + return FALSE; +} + + +/* remove all from the list have have uid = uid */ +static GSList* +remove_uid (GSList *list, const gchar *uid) +{ + GSList *cursor = list, *start = list; + + if (!uid) + return FALSE; + + while (cursor) { + GSList *next = g_slist_next (cursor); + if (cursor->data && strcmp (cursor->data, uid) == 0) { + g_free (cursor->data); + start = g_slist_delete_link (start, cursor); + } + cursor = next; + } + return start; +} + + +static GSList * +append_uid (GSList *list, const gchar *uid) +{ + return g_slist_append (list, g_strdup(uid)); +} + + + +void +modest_window_mgr_register_header (ModestWindowMgr *self, TnyHeader *header) +{ + ModestWindowMgrPrivate *priv; + gchar* uid; + + g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); + g_return_if_fail (TNY_IS_HEADER(header)); + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + uid = modest_tny_folder_get_header_unique_id (header); + + + if (!has_uid (priv->preregistered_uids, uid)) { + g_debug ("registering new uid %s", uid); + priv->preregistered_uids = append_uid (priv->preregistered_uids, uid); + } else + g_debug ("already had uid %s", uid); + + g_free (uid); +} + +void +modest_window_mgr_unregister_header (ModestWindowMgr *self, TnyHeader *header) +{ + ModestWindowMgrPrivate *priv; + gchar* uid; + + g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); + g_return_if_fail (TNY_IS_HEADER(header)); + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + uid = modest_tny_folder_get_header_unique_id (header); + + if (!has_uid (priv->preregistered_uids, uid)) { + g_debug ("trying to unregister non-existing uid %s", uid); + priv->preregistered_uids = append_uid (priv->preregistered_uids, uid); + } else + g_debug ("unregistering uid %s", uid); + + if (has_uid (priv->preregistered_uids, uid)) { + priv->preregistered_uids = remove_uid (priv->preregistered_uids, uid); + if (has_uid (priv->preregistered_uids, uid)) + g_debug ("BUG: uid %s NOT removed", uid); + else + g_debug ("uid %s removed", uid); + } + + g_free (uid); +} + +static gint +compare_msguids (ModestWindow *win, + const gchar *uid) +{ + const gchar *msg_uid; + + if (!MODEST_IS_MSG_VIEW_WINDOW (win)) + return 1; + + /* Get message uid from msg window */ + msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win)); + + if (msg_uid && uid &&!strcmp (msg_uid, uid)) + return 0; + else + return 1; +} + + + +gboolean +modest_window_mgr_find_registered_header (ModestWindowMgr *self, TnyHeader *header, + ModestWindow **win) +{ + ModestWindowMgrPrivate *priv; + gchar* uid; + gboolean has_header, has_window = FALSE; + GList *item = NULL; + + g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), FALSE); + g_return_val_if_fail (TNY_IS_HEADER(header), FALSE); + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + uid = modest_tny_folder_get_header_unique_id (header); + + if (win) + *win = NULL; + + g_debug ("windows in list: %d", g_list_length (priv->window_list)); + g_debug ("headers in list: %d", g_slist_length (priv->preregistered_uids)); + + has_header = has_uid (priv->preregistered_uids, uid); + + item = g_list_find_custom (priv->window_list, uid, (GCompareFunc) compare_msguids); + if (item) { + has_window = TRUE; + if (win) { + if (!MODEST_IS_MSG_VIEW_WINDOW(item->data)) + g_debug ("not a valid window!"); + else { + g_debug ("found a window"); + *win = MODEST_WINDOW (item->data); + } + } + } + + g_free (uid); + return has_header || has_window; +} + + + void modest_window_mgr_register_window (ModestWindowMgr *self, ModestWindow *window) @@ -181,7 +362,7 @@ modest_window_mgr_register_window (ModestWindowMgr *self, g_warning ("Trying to register an already registered window"); return; } - + /* Check that it's not a second main window */ if (MODEST_IS_MAIN_WINDOW (window)) { if (priv->main_window) { @@ -192,15 +373,41 @@ modest_window_mgr_register_window (ModestWindowMgr *self, } } + /* remove from the list of pre-registered uids */ + if (MODEST_IS_MSG_VIEW_WINDOW(window)) { + const gchar *uid = modest_msg_view_window_get_message_uid + (MODEST_MSG_VIEW_WINDOW (window)); + + g_debug ("registering window for %s", uid); + + if (!has_uid (priv->preregistered_uids, uid)) + g_debug ("weird: no uid for window (%s)", uid); + + priv->preregistered_uids = + remove_uid (priv->preregistered_uids, + modest_msg_view_window_get_message_uid + (MODEST_MSG_VIEW_WINDOW (window))); + } + /* Add to list. Keep a reference to the window */ g_object_ref (window); priv->window_list = g_list_prepend (priv->window_list, window); /* Listen to object destruction */ handler_id = g_malloc0 (sizeof (gint)); - *handler_id = g_signal_connect (window, "destroy", G_CALLBACK (on_window_destroy), self); + *handler_id = g_signal_connect (window, "delete-event", G_CALLBACK (on_window_destroy), self); g_hash_table_insert (priv->destroy_handlers, window, handler_id); + /* If there is a msg view window, let the main window listen the msg-changed signal */ + if (MODEST_IS_MSG_VIEW_WINDOW(window) && priv->main_window) { + gulong *handler; + handler = g_malloc0 (sizeof (gulong)); + *handler = g_signal_connect (window, "msg-changed", + G_CALLBACK (modest_main_window_on_msg_view_window_msg_changed), + priv->main_window); + g_hash_table_insert (priv->viewer_handlers, window, handler); + } + /* Put into fullscreen if needed */ if (priv->fullscreen_mode) gtk_window_fullscreen (GTK_WINDOW (window)); @@ -223,8 +430,12 @@ modest_window_mgr_register_window (ModestWindowMgr *self, modest_window_show_toolbar (window, show); } -static void -on_window_destroy (ModestWindow *window, ModestWindowMgr *self) +/* static void */ +/* on_window_destroy (ModestWindow *window, ModestWindowMgr *self) */ +static gboolean +on_window_destroy (ModestWindow *window, + GdkEvent *event, + ModestWindowMgr *self) { /* Specific stuff first */ if (MODEST_IS_MAIN_WINDOW (window)) { @@ -241,6 +452,7 @@ on_window_destroy (ModestWindow *window, ModestWindowMgr *self) if (iter->data != window) { GList *tmp = iter->next; on_window_destroy (MODEST_WINDOW (iter->data), + event, self); iter = tmp; } else { @@ -249,30 +461,56 @@ on_window_destroy (ModestWindow *window, ModestWindowMgr *self) } while (iter); } } - } else { - if (MODEST_IS_MSG_EDIT_WINDOW (window)) - /* Save currently edited message to Drafts */ - if (modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) { - gint response = - modest_platform_run_confirmation_dialog (GTK_WINDOW (self), + } + else { + if (MODEST_IS_MSG_EDIT_WINDOW (window)) { + gboolean sent = FALSE; + gint response = GTK_RESPONSE_ACCEPT; + sent = modest_msg_edit_window_get_sent (MODEST_MSG_EDIT_WINDOW (window)); + /* Save currently edited message to Drafts if it was not sent */ + if (!sent && modest_msg_edit_window_is_modified (MODEST_MSG_EDIT_WINDOW (window))) { + + response = + modest_platform_run_confirmation_dialog (GTK_WINDOW (window), _("mcen_nc_no_email_message_modified_save_changes")); - if (response != GTK_RESPONSE_CANCEL) { + /* Save to drafts */ + if (response != GTK_RESPONSE_CANCEL) modest_ui_actions_on_save_to_drafts (NULL, MODEST_MSG_EDIT_WINDOW (window)); - } + } + } } + /* Save configuration state (TODO: why edit window does not require this function ?) */ + if (!MODEST_IS_MSG_EDIT_WINDOW (window)) + modest_window_save_state (MODEST_WINDOW(window)); + + /* Unregister window */ modest_window_mgr_unregister_window (self, window); + + return FALSE; } +static void +disconnect_msg_changed (gpointer key, + gpointer value, + gpointer user_data) +{ + gulong *handler_id; + + handler_id = (gulong *) value; + g_signal_handler_disconnect (G_OBJECT (key), *handler_id); +} + + void modest_window_mgr_unregister_window (ModestWindowMgr *self, ModestWindow *window) { GList *win; ModestWindowMgrPrivate *priv; - gint *handler_id; + gint *tmp, handler_id; g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); g_return_if_fail (MODEST_IS_WINDOW (window)); @@ -286,25 +524,31 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, } /* If it's the main window unset it */ - if (priv->main_window == window) + if (priv->main_window == window) { priv->main_window = NULL; + /* Disconnect all emissions of msg-changed */ + g_hash_table_foreach (priv->viewer_handlers, + disconnect_msg_changed, + NULL); + g_hash_table_destroy (priv->viewer_handlers); + priv->viewer_handlers = NULL; + } + /* Save state */ modest_window_save_state (window); - /* Remove from list */ + /* Remove from list & hash table */ priv->window_list = g_list_remove_link (priv->window_list, win); + tmp = g_hash_table_lookup (priv->destroy_handlers, window); + handler_id = *tmp; + g_hash_table_remove (priv->destroy_handlers, window); + + /* Disconnect the "delete-event" handler, we won't need it anymore */ + g_signal_handler_disconnect (window, handler_id); - /* Remove the reference to the window. We need to block the - destroy event handler to avoid recursive calls */ - handler_id = g_hash_table_lookup (priv->destroy_handlers, window); - g_signal_handler_block (window, *handler_id); + /* Destroy the window */ gtk_widget_destroy (win->data); - if (G_IS_OBJECT (window)) { - g_warning ("This should not happen the window was not completely destroyed"); - g_signal_handler_unblock (window, *handler_id); - } - g_hash_table_remove (priv->destroy_handlers, window); /* If there are no more windows registered then exit program */ if (priv->window_list == NULL) { @@ -317,57 +561,12 @@ modest_window_mgr_unregister_window (ModestWindowMgr *self, priv->show_toolbars, NULL); /* Quit main loop */ - gtk_main_quit (); + /* FIXME: do we ever need to do this here? */ + if (gtk_main_level() > 0) + gtk_main_quit (); } } -static gint -compare_msguids (ModestWindow *win, - const gchar *uid) -{ - const gchar *msg_uid; - - if (!MODEST_IS_MSG_VIEW_WINDOW (win)) - return 1; - - /* Get message uid from msg window */ - msg_uid = modest_msg_view_window_get_message_uid (MODEST_MSG_VIEW_WINDOW (win)); - - if (msg_uid && uid &&!strcmp (msg_uid, uid)) - return 0; - else - return 1; -} - -ModestWindow* -modest_window_mgr_find_window_by_header (ModestWindowMgr *self, - TnyHeader *header) -{ - ModestWindowMgrPrivate *priv; - GList *win = NULL; - gchar *msg_uid; - - g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL); - g_return_val_if_fail (TNY_IS_HEADER (header), NULL); - - priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - msg_uid = modest_tny_folder_get_header_unique_id (header); - - /* Look for the window */ - if (priv->window_list) - win = g_list_find_custom (priv->window_list, - msg_uid, - (GCompareFunc) compare_msguids); - /* Free */ - g_free (msg_uid); - - /* Return the window */ - if (win) - return win->data; - else - return NULL; -} - void modest_window_mgr_set_fullscreen_mode (ModestWindowMgr *self, gboolean on)