From 94a4612a68cf9129d80418e40d177911297b76e7 Mon Sep 17 00:00:00 2001 From: Sergio Villar Senin Date: Fri, 28 Sep 2007 17:22:09 +0000 Subject: [PATCH] * Fixed NB#62792, the editor is closed if the account is removed * Added modest_signal_mgr_disconnect, for disconnecting a single handler * Added the signal parametter to modest_signal_mgr_connect, this way we can add multiple connections for the same object * Renamed modest_window_mgr_(set/get)_modal_dialog to modest_window_mgt_(set/get)_modal because we can set a normal window as modal as well * Implemented a queue of modal dialogs in the window mgr, this way if the top one is removed the second one becomes the topmost pmo-trunk-r3441 --- src/dbus_api/modest-dbus-callbacks.c | 2 +- src/maemo/easysetup/modest-easysetup-wizard.c | 7 +- src/maemo/modest-account-view-window.c | 37 +++--- src/maemo/modest-msg-edit-window.c | 42 +++++++ src/maemo/modest-platform.c | 47 ++----- src/modest-signal-mgr.c | 63 +++++++++- src/modest-signal-mgr.h | 26 +++- src/modest-ui-actions.c | 91 +++++--------- src/modest-ui-actions.h | 2 +- src/widgets/modest-window-mgr.c | 168 ++++++++++++++++++++++--- src/widgets/modest-window-mgr.h | 13 +- 11 files changed, 347 insertions(+), 151 deletions(-) diff --git a/src/dbus_api/modest-dbus-callbacks.c b/src/dbus_api/modest-dbus-callbacks.c index e92cdfe..962a675 100644 --- a/src/dbus_api/modest-dbus-callbacks.c +++ b/src/dbus_api/modest-dbus-callbacks.c @@ -195,7 +195,7 @@ check_and_offer_account_creation() if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) { printf ("DEBUG1: %s\n", __FUNCTION__); - const gboolean created = modest_run_account_setup_wizard (NULL); + const gboolean created = modest_ui_actions_run_account_setup_wizard (NULL); printf ("DEBUG1: %s\n", __FUNCTION__); if (!created) { g_debug ("modest: %s: no account exists even after offering, " diff --git a/src/maemo/easysetup/modest-easysetup-wizard.c b/src/maemo/easysetup/modest-easysetup-wizard.c index 21165b5..b86f40d 100644 --- a/src/maemo/easysetup/modest-easysetup-wizard.c +++ b/src/maemo/easysetup/modest-easysetup-wizard.c @@ -1088,8 +1088,7 @@ on_response_before (ModestWizardDialog *wizard_dialog, if (response_id == GTK_RESPONSE_CANCEL) { /* This is mostly copied from * src/maemo/modest-account-settings-dialog.c */ - if (priv->dirty) - { + if (priv->dirty) { GtkDialog *dialog = GTK_DIALOG (hildon_note_new_confirmation (GTK_WINDOW (self), _("imum_nc_wizard_confirm_lose_changes"))); /* TODO: These button names will be ambiguous, and not specified in the UI specification. */ @@ -1097,9 +1096,7 @@ on_response_before (ModestWizardDialog *wizard_dialog, const gint dialog_response = gtk_dialog_run (dialog); gtk_widget_destroy (GTK_WIDGET (dialog)); - if (dialog_response != GTK_RESPONSE_OK) - { - /* This is a nasty hack. murrayc. */ + if (dialog_response != GTK_RESPONSE_OK) { /* Don't let the dialog close */ g_signal_stop_emission_by_name (wizard_dialog, "response"); } diff --git a/src/maemo/modest-account-view-window.c b/src/maemo/modest-account-view-window.c index 3e90c4b..3c92994 100644 --- a/src/maemo/modest-account-view-window.c +++ b/src/maemo/modest-account-view-window.c @@ -215,6 +215,8 @@ on_delete_button_clicked (GtkWidget *button, ModestAccountViewWindow *self) if (check_for_active_account (self, account_name)) { /* The warning text depends on the account type: */ gchar *txt = NULL; + gint response; + if (modest_account_mgr_get_store_protocol (account_mgr, account_name) == MODEST_PROTOCOL_STORE_POP) { txt = g_strdup_printf (_("emev_nc_delete_mailbox"), @@ -231,10 +233,14 @@ on_delete_button_clicked (GtkWidget *button, ModestAccountViewWindow *self) g_free (txt); txt = NULL; - if (gtk_dialog_run (dialog) == GTK_RESPONSE_OK) { + response = gtk_dialog_run (dialog); + gtk_widget_destroy (GTK_WIDGET (dialog)); + while (gtk_events_pending ()) + gtk_main_iteration (); + + if (response == GTK_RESPONSE_OK) { /* Remove account. If it succeeds then it also removes - the account from the ModestAccountView: */ - + the account from the ModestAccountView: */ gboolean is_default = FALSE; gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr); if (default_account_name && (strcmp (default_account_name, account_name) == 0)) @@ -246,10 +252,8 @@ on_delete_button_clicked (GtkWidget *button, ModestAccountViewWindow *self) g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__); } } - gtk_widget_destroy (GTK_WIDGET (dialog)); g_free (account_title); - } - + } g_free (account_name); } } @@ -284,34 +288,31 @@ on_wizard_response (GtkDialog *dialog, gint response, gpointer user_data) { /* The response has already been handled by the wizard dialog itself, * creating the new account. - */ - + */ /* Destroy the dialog: */ - if (dialog) { + if (dialog) gtk_widget_destroy (GTK_WIDGET (dialog)); - modest_window_mgr_set_modal_dialog ( - modest_runtime_get_window_mgr(), NULL); - } } static void on_new_button_clicked (GtkWidget *button, ModestAccountViewWindow *self) { - GtkDialog *wizard, *dialog; + GtkDialog *wizard; + GtkWindow *dialog; /* Show the easy-setup wizard: */ - dialog = modest_window_mgr_get_modal_dialog (modest_runtime_get_window_mgr()); + dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr()); if (dialog && MODEST_IS_EASYSETUP_WIZARD_DIALOG(dialog)) { /* old wizard is active already; */ - gtk_window_present (GTK_WINDOW(dialog)); + gtk_window_present (dialog); return; } /* there is no such wizard yet */ - wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ()); - modest_window_mgr_set_modal_dialog (modest_runtime_get_window_mgr(), - GTK_DIALOG(wizard)); + wizard = GTK_DIALOG (modest_easysetup_wizard_dialog_new ()); + modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), + GTK_WINDOW (wizard)); /* if there is already another modal dialog, make it non-modal */ if (dialog) diff --git a/src/maemo/modest-msg-edit-window.c b/src/maemo/modest-msg-edit-window.c index e09c165..6ea1354 100644 --- a/src/maemo/modest-msg-edit-window.c +++ b/src/maemo/modest-msg-edit-window.c @@ -56,6 +56,7 @@ #include "modest-tny-platform-factory.h" #include "modest-tny-msg.h" #include "modest-tny-folder.h" +#include "modest-tny-account.h" #include "modest-address-book.h" #include "modest-text-utils.h" #include @@ -152,6 +153,11 @@ static gboolean gtk_text_iter_forward_search_insensitive (const GtkTextIter *ite static void remove_tags (WPTextBuffer *buffer); +static void on_account_removed (TnyAccountStore *account_store, + TnyAccount *account, + gpointer user_data); + + static void DEBUG_BUFFER (WPTextBuffer *buffer) { #ifdef DEBUG @@ -253,6 +259,7 @@ struct _ModestMsgEditWindowPrivate { gboolean can_undo, can_redo; gulong clipboard_change_handler_id; gulong default_clipboard_change_handler_id; + gulong account_removed_handler_id; gchar *clipboard_text; TnyMsg *draft_msg; @@ -369,6 +376,7 @@ modest_msg_edit_window_init (ModestMsgEditWindow *obj) priv->can_redo = FALSE; priv->clipboard_change_handler_id = 0; priv->default_clipboard_change_handler_id = 0; + priv->account_removed_handler_id = 0; priv->clipboard_text = NULL; priv->sent = FALSE; @@ -628,6 +636,12 @@ modest_msg_edit_window_disconnect_signals (ModestWindow *window) priv->default_clipboard_change_handler_id)) g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), priv->default_clipboard_change_handler_id); + + if (priv->account_removed_handler_id && + g_signal_handler_is_connected (modest_runtime_get_account_store (), + priv->account_removed_handler_id)) + g_signal_handler_disconnect(modest_runtime_get_account_store (), + priv->account_removed_handler_id); } static void @@ -1327,6 +1341,15 @@ modest_msg_edit_window_new (TnyMsg *msg, const gchar *account_name, gboolean pre priv->update_caption_visibility = TRUE; modest_msg_edit_window_reset_modified (MODEST_MSG_EDIT_WINDOW (obj)); + + /* Track account-removed signal, this window should be closed + in the case we're creating a mail associated to the account + that is deleted */ + priv->account_removed_handler_id = + g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()), + "account_removed", + G_CALLBACK(on_account_removed), + obj); return (ModestWindow*) obj; } @@ -3263,3 +3286,22 @@ remove_tags (WPTextBuffer *buffer) gtk_text_buffer_remove_all_tags (GTK_TEXT_BUFFER (buffer), &start, &end); } + +static void +on_account_removed (TnyAccountStore *account_store, + TnyAccount *account, + gpointer user_data) +{ + /* Do nothing if it's a store account, because we use the + transport to send the messages */ + if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_TRANSPORT) { + const gchar *parent_acc = NULL; + const gchar *our_acc = NULL; + + our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data)); + parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account); + /* Close this window if I'm showing a message of the removed account */ + if (strcmp (parent_acc, our_acc) == 0) + modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data)); + } +} diff --git a/src/maemo/modest-platform.c b/src/maemo/modest-platform.c index 586a455..f521639 100644 --- a/src/maemo/modest-platform.c +++ b/src/maemo/modest-platform.c @@ -851,35 +851,9 @@ modest_platform_run_rename_folder_dialog (GtkWindow *parent_window, static void on_destroy_dialog (GtkDialog *dialog) { - if (dialog == modest_window_mgr_get_modal_dialog (modest_runtime_get_window_mgr())) - modest_window_mgr_set_modal_dialog (modest_runtime_get_window_mgr(), - NULL); gtk_widget_destroy (GTK_WIDGET(dialog)); -} - - -/* is there already a modal dialog? if so, return TRUE, if not set this - * dialog to be the registered one */ -static void -check_modal_and_set_maybe (GtkDialog *dialog) -{ - GtkDialog *old_modal; - - old_modal = - modest_window_mgr_get_modal_dialog (modest_runtime_get_window_mgr()); - - if (!old_modal) { - gtk_window_set_modal (GTK_WINDOW(dialog), TRUE); - } else { - /* un-modalize the old one; the one on top should be the - * modal one */ - gtk_window_set_modal (GTK_WINDOW(old_modal), FALSE); - gtk_window_set_modal (GTK_WINDOW(dialog), TRUE); - } - - /* this will be the new modal dialog */ - modest_window_mgr_set_modal_dialog (modest_runtime_get_window_mgr(), - dialog); + if (gtk_events_pending ()) + gtk_main_iteration (); } gint @@ -890,7 +864,8 @@ modest_platform_run_confirmation_dialog (GtkWindow *parent_window, gint response; dialog = hildon_note_new_confirmation (parent_window, message); - check_modal_and_set_maybe (GTK_DIALOG(dialog)); + modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), + GTK_WINDOW (dialog)); response = gtk_dialog_run (GTK_DIALOG (dialog)); @@ -913,7 +888,7 @@ modest_platform_run_yes_no_dialog (GtkWindow *parent_window, _("mcen_bd_yes"), GTK_RESPONSE_YES, _("mcen_bd_no"), GTK_RESPONSE_NO, NULL); - check_modal_and_set_maybe (GTK_DIALOG(dialog)); + modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog)); response = gtk_dialog_run (GTK_DIALOG (dialog)); on_destroy_dialog (GTK_DIALOG(dialog)); @@ -933,7 +908,8 @@ modest_platform_run_information_dialog (GtkWindow *parent_window, GtkWidget *note; note = hildon_note_new_information (parent_window, message); - check_modal_and_set_maybe (GTK_DIALOG(note)); + modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), + GTK_WINDOW (note)); g_signal_connect_swapped (note, "response", @@ -1166,7 +1142,8 @@ modest_platform_run_sort_dialog (GtkWindow *parent_window, /* Build dialog */ dialog = hildon_sort_dialog_new (parent_window); - check_modal_and_set_maybe (GTK_DIALOG(dialog)); + modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), + GTK_WINDOW (dialog)); /* Fill sort keys */ switch (type) { @@ -1591,7 +1568,8 @@ modest_platform_run_certificate_conformation_dialog (const gchar* server_name, G_CALLBACK(on_cert_dialog_response), (gpointer) certificate); - check_modal_and_set_maybe (GTK_DIALOG(note)); + modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), + GTK_WINDOW (note)); response = gtk_dialog_run(GTK_DIALOG(note)); on_destroy_dialog (GTK_DIALOG(note)); @@ -1617,7 +1595,8 @@ modest_platform_run_alert_dialog (const gchar* prompt, * so we know what buttons to show. */ GtkWidget *dialog = GTK_WIDGET (hildon_note_new_confirmation (GTK_WINDOW (main_window), prompt)); - check_modal_and_set_maybe (GTK_DIALOG(dialog)); + modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), + GTK_WINDOW (dialog)); const int response = gtk_dialog_run (GTK_DIALOG (dialog)); retval = (response == GTK_RESPONSE_YES) || (response == GTK_RESPONSE_OK); diff --git a/src/modest-signal-mgr.c b/src/modest-signal-mgr.c index 73a76d2..d8be1d3 100644 --- a/src/modest-signal-mgr.c +++ b/src/modest-signal-mgr.c @@ -28,25 +28,31 @@ */ #include "modest-signal-mgr.h" +#include typedef struct { guint handler_id; + gchar *signal_name; GObject *obj; } SignalHandler; GSList * -modest_signal_mgr_connect (GSList *lst, GObject *instance, const gchar *detail, - GCallback handler, gpointer data) +modest_signal_mgr_connect (GSList *lst, + GObject *instance, + const gchar *signal_name, + GCallback handler, + gpointer data) { SignalHandler *sighandler; g_return_val_if_fail (instance, lst); - g_return_val_if_fail (detail, lst); + g_return_val_if_fail (signal_name, lst); g_return_val_if_fail (handler, lst); sighandler = g_new (SignalHandler, 1); - sighandler->obj = g_object_ref (instance); - sighandler->handler_id = g_signal_connect (instance, detail, handler, data); + sighandler->obj = g_object_ref (instance); + sighandler->handler_id = g_signal_connect (instance, signal_name, handler, data); + sighandler->signal_name = g_strdup (signal_name); return g_slist_prepend (lst, (gpointer)sighandler); } @@ -61,7 +67,6 @@ modest_signal_mgr_disconnect_all_and_destroy (GSList *lst) handler = (SignalHandler*)cursor->data; if (handler && handler->obj && G_IS_OBJECT(handler->obj)) { if (g_signal_handler_is_connected (handler->obj, handler->handler_id)) { - /* g_debug ("%p: disconnecting %d", handler->obj, handler->handler_id); */ g_signal_handler_disconnect (handler->obj, handler->handler_id); } g_object_unref (handler->obj); @@ -71,3 +76,49 @@ modest_signal_mgr_disconnect_all_and_destroy (GSList *lst) } g_slist_free (lst); } + +static gboolean +obj_in_a_signal_handler (gconstpointer a, + gconstpointer b) +{ + SignalHandler *handler, *list_item_handler; + + list_item_handler = (SignalHandler *) a; + handler = (SignalHandler *) b; + + if (list_item_handler->obj == handler->obj && + !strcmp (list_item_handler->signal_name, handler->signal_name)) + return 0; + else + return 1; +} + +GSList * +modest_signal_mgr_disconnect (GSList *list, + GObject *instance, + const gchar *signal_name) +{ + GSList *item = NULL; + SignalHandler *signal_handler = NULL, *tmp = NULL; + + tmp = g_new (SignalHandler, 1); + tmp->obj = instance; + tmp->signal_name = g_strdup (signal_name); + + /* Find the element */ + item = g_slist_find_custom (list, tmp, obj_in_a_signal_handler); + g_return_val_if_fail (item != NULL, list); + + /* Disconnect the signal */ + signal_handler = (SignalHandler *) item->data; + g_signal_handler_disconnect (signal_handler->obj, signal_handler->handler_id); + + /* Free the handlers */ + g_free (signal_handler->signal_name); + g_free (signal_handler); + g_free (tmp->signal_name); + g_free (tmp); + + /* Remove item from list */ + return g_slist_delete_link (list, item); +} diff --git a/src/modest-signal-mgr.h b/src/modest-signal-mgr.h index bd0ae8e..9fea07a 100644 --- a/src/modest-signal-mgr.h +++ b/src/modest-signal-mgr.h @@ -42,16 +42,34 @@ G_BEGIN_DECLS * * TRUE if this succeeded, FALSE otherwise. */ -GSList *modest_signal_mgr_connect (GSList *lst, GObject *instance, const gchar *detail, - GCallback handler, gpointer data); +GSList * modest_signal_mgr_connect (GSList *lst, + GObject *instance, + const gchar *signal_name, + GCallback handler, + gpointer data); + +/** + * modest_signal_mgr_disconnect: + * @list: + * @instance: + * + * disconnect the handler for a particular object for a particular signal + * + * Returns: + **/ +GSList * modest_signal_mgr_disconnect (GSList *list, + GObject *instance, + const gchar *signal_name); + /** * modest_signal_mgr_disconnect_all_and_destroy: + * @lst: the list of signal handlers * * disconnect all signals in the list, and destroy the list - * */ -void modest_signal_mgr_disconnect_all_and_destroy (GSList *lst); +void modest_signal_mgr_disconnect_all_and_destroy (GSList *lst); + G_END_DECLS #endif /*__MODEST_SIGNAL_MGR__*/ diff --git a/src/modest-ui-actions.c b/src/modest-ui-actions.c index 3d154ca..8b29b6e 100644 --- a/src/modest-ui-actions.c +++ b/src/modest-ui-actions.c @@ -203,13 +203,14 @@ msgs_already_deleted_from_server (TnyList *headers, const TnyFolderStore *src_fo * returns: TRUE if an account was created. FALSE if the user cancelled. */ gboolean -modest_run_account_setup_wizard (ModestWindow *win) +modest_ui_actions_run_account_setup_wizard (ModestWindow *win) { - gboolean result = FALSE; - GtkDialog *wizard, *dialog; + gboolean result = FALSE; + GtkWindow *dialog, *wizard; + gint dialog_response; /* Show the easy-setup wizard: */ - dialog = modest_window_mgr_get_modal_dialog (modest_runtime_get_window_mgr()); + dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr()); if (dialog && MODEST_IS_EASYSETUP_WIZARD_DIALOG(dialog)) { /* old wizard is active already; */ @@ -218,26 +219,9 @@ modest_run_account_setup_wizard (ModestWindow *win) } - /* there is no such wizard yet */ - - wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ()); - if (!wizard) { - g_printerr ("modest: failed to create easysetup wizard\n"); - return FALSE; - } - - modest_window_mgr_set_modal_dialog - (modest_runtime_get_window_mgr(), GTK_DIALOG(wizard)); - - - /* there is no such wizard yet */ - wizard = GTK_DIALOG(modest_easysetup_wizard_dialog_new ()); - modest_window_mgr_set_modal_dialog (modest_runtime_get_window_mgr(), - GTK_DIALOG(wizard)); - - /* make it non-modal; if though we register it as a modal dialog above - * apparently, making it modal *at all* gives hangs -- FIXME: check this*/ - gtk_window_set_modal (GTK_WINDOW(dialog), FALSE); + /* there is no such wizard yet */ + wizard = GTK_WINDOW (modest_easysetup_wizard_dialog_new ()); + modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), wizard); /* always present a main window in the background * we do it here, so we cannot end up with to wizards (as this @@ -248,28 +232,19 @@ modest_run_account_setup_wizard (ModestWindow *win) /* make sure the mainwindow is visible */ gtk_widget_show_all (GTK_WIDGET(win)); gtk_window_present (GTK_WINDOW(win)); - - gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win)); + dialog_response = gtk_dialog_run (GTK_DIALOG (wizard)); + gtk_widget_destroy (GTK_WIDGET (wizard)); + if (gtk_events_pending ()) + gtk_main_iteration (); - /* Don't make this a modal window, because secondary windows will then - * be unusable, freezing the UI: */ - /* gtk_window_set_modal (GTK_WINDOW (wizard), TRUE); */ - - gint dialog_response = gtk_dialog_run (GTK_DIALOG (wizard)); - if (dialog_response == GTK_RESPONSE_CANCEL) + if (dialog_response == GTK_RESPONSE_CANCEL) { result = FALSE; - else { + } else { /* Check whether an account was created: */ result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE); } - gtk_widget_destroy (GTK_WIDGET (wizard)); - - /* clear it from the window mgr */ - modest_window_mgr_set_modal_dialog - (modest_runtime_get_window_mgr(), NULL); - return result; } @@ -711,21 +686,22 @@ modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win) } void -modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win) +modest_ui_actions_on_accounts (GtkAction *action, + ModestWindow *win) { /* This is currently only implemented for Maemo */ #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */ - if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) { - modest_run_account_setup_wizard (win); + if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) { + modest_ui_actions_run_account_setup_wizard (win); return; - } else { - /* Show the list of accounts: */ - GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ()); - gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW (win)); + } else { + /* Show the list of accounts */ + GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ()); + gtk_window_set_transient_for (account_win, GTK_WINDOW (win)); - /* The accounts dialog must be modal */ - gtk_window_set_modal (GTK_WINDOW (account_win), TRUE); - modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), account_win); + /* The accounts dialog must be modal */ + modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), account_win); + modest_maemo_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win)); } #else GtkWidget *dialog, *label; @@ -806,9 +782,8 @@ modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win) /* if there are no accounts yet, just show the wizard */ if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) { - const gboolean created = modest_run_account_setup_wizard (win); - if (!created) - return; + if (!modest_ui_actions_run_account_setup_wizard (win)) + return; } account_name = g_strdup (modest_window_get_active_account (win)); @@ -940,8 +915,7 @@ open_msg_cb (ModestMailOperation *mail_op, TnyHeader *header, TnyMsg *msg, gpoi (folder_type == TNY_FOLDER_TYPE_OUTBOX)) { /* we cannot edit without a valid account... */ if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) { - const gboolean created = modest_run_account_setup_wizard(parent_win); - if (!created) + if (!modest_ui_actions_run_account_setup_wizard(parent_win)) goto cleanup; } win = modest_msg_edit_window_new (msg, account, TRUE); @@ -1350,8 +1324,7 @@ reply_forward (ReplyForwardAction action, ModestWindow *win) /* we need an account when editing */ if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) { - const gboolean created = modest_run_account_setup_wizard (win); - if (!created) + if (!modest_ui_actions_run_account_setup_wizard (win)) return; } @@ -2233,8 +2206,7 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window) if (!account_name) { /* Run account setup wizard */ - const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window)); - if (!created) + if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) return; } @@ -2251,8 +2223,7 @@ modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window) account_name)); if (!transport_account) { /* Run account setup wizard */ - const gboolean created = modest_run_account_setup_wizard(MODEST_WINDOW(edit_window)); - if (!created) + if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window))) return; } diff --git a/src/modest-ui-actions.h b/src/modest-ui-actions.h index 2979779..5855060 100644 --- a/src/modest-ui-actions.h +++ b/src/modest-ui-actions.h @@ -462,7 +462,7 @@ void modest_do_messages_delete (TnyList *headers, ModestWindow *win); /* Show the account creation wizard dialog. * returns: TRUE if an account was created. FALSE if the user cancelled. */ -gboolean modest_run_account_setup_wizard (ModestWindow *win); +gboolean modest_ui_actions_run_account_setup_wizard (ModestWindow *win); gint modest_ui_actions_msgs_move_to_confirmation (GtkWindow *win, TnyFolder *dest_folder, diff --git a/src/widgets/modest-window-mgr.c b/src/widgets/modest-window-mgr.c index 32dc0f3..33ec152 100644 --- a/src/widgets/modest-window-mgr.c +++ b/src/widgets/modest-window-mgr.c @@ -47,6 +47,14 @@ static gboolean on_window_destroy (ModestWindow *window, GdkEvent *event, ModestWindowMgr *self); +static gboolean on_modal_window_close (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +static void on_modal_dialog_close (GtkDialog *dialog, + gint arg1, + gpointer user_data); + static const gchar* get_show_toolbar_key (GType window_type, gboolean fullscreen); @@ -62,7 +70,9 @@ struct _ModestWindowMgrPrivate { GList *window_list; ModestWindow *main_window; - GtkDialog *modal_dialog; + + GMutex *queue_lock; + GQueue *modal_windows; gboolean fullscreen_mode; @@ -72,6 +82,8 @@ struct _ModestWindowMgrPrivate { GHashTable *viewer_handlers; guint closing_time; + + GSList *modal_handler_uids; }; #define MODEST_WINDOW_MGR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_WINDOW_MGR, \ @@ -127,7 +139,9 @@ modest_window_mgr_init (ModestWindowMgr *obj) priv->window_list = NULL; priv->main_window = NULL; priv->fullscreen_mode = FALSE; - priv->modal_dialog = NULL; + + priv->modal_windows = g_queue_new (); + priv->queue_lock = g_mutex_new (); priv->preregistered_uids = NULL; @@ -137,6 +151,8 @@ modest_window_mgr_init (ModestWindowMgr *obj) priv->viewer_handlers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); priv->closing_time = 0; + + priv->modal_handler_uids = NULL; } static void @@ -171,12 +187,15 @@ modest_window_mgr_finalize (GObject *obj) priv->viewer_handlers = NULL; } - if (priv->modal_dialog) { - g_warning ("%s: forgot to destroy a modal dialog somewhere", - __FUNCTION__); - gtk_widget_destroy (GTK_WIDGET(priv->modal_dialog)); - priv->modal_dialog = NULL; + modest_signal_mgr_disconnect_all_and_destroy (priv->modal_handler_uids); + + if (priv->modal_windows) { + g_mutex_lock (priv->queue_lock); + g_queue_free (priv->modal_windows); + priv->modal_windows = NULL; + g_mutex_unlock (priv->queue_lock); } + g_mutex_free (priv->queue_lock); /* Do not unref priv->main_window because it does not hold a new reference */ @@ -525,6 +544,10 @@ on_window_destroy (ModestWindow *window, 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))) { + + /* Raise the window if it's minimized */ + if (!gtk_window_has_toplevel_focus (GTK_WINDOW (window))) + gtk_window_present (GTK_WINDOW (window)); response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window), @@ -792,27 +815,64 @@ modest_window_mgr_get_main_window (ModestWindowMgr *self) } -GtkDialog* -modest_window_mgr_get_modal_dialog (ModestWindowMgr *self) +GtkWindow * +modest_window_mgr_get_modal (ModestWindowMgr *self) { ModestWindowMgrPrivate *priv; g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL); priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); - return priv->modal_dialog; + return g_queue_peek_head (priv->modal_windows); } -GtkDialog* -modest_window_mgr_set_modal_dialog (ModestWindowMgr *self, GtkDialog *dialog) +void +modest_window_mgr_set_modal (ModestWindowMgr *self, + GtkWindow *window) { + GtkWindow *old_modal; ModestWindowMgrPrivate *priv; - - g_return_val_if_fail (MODEST_IS_WINDOW_MGR (self), NULL); + + g_return_if_fail (MODEST_IS_WINDOW_MGR (self)); + g_return_if_fail (GTK_IS_WINDOW (window)); + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + g_mutex_lock (priv->queue_lock); + old_modal = g_queue_peek_head (priv->modal_windows); + g_mutex_unlock (priv->queue_lock); - return priv->modal_dialog = dialog; + if (!old_modal) { + gtk_window_set_modal (window, TRUE); + } else { + /* un-modalize the old one; the one on top should be the + * modal one */ + gtk_window_set_transient_for (window, GTK_WINDOW(old_modal)); + gtk_window_set_modal (window, TRUE); + } + + /* this will be the new modal window */ + g_mutex_lock (priv->queue_lock); + g_queue_push_head (priv->modal_windows, window); + g_mutex_unlock (priv->queue_lock); + + if (GTK_IS_DIALOG (window)) + /* Note that response is not always enough because it + could be captured and removed easily by dialogs but + works for most of situations */ + priv->modal_handler_uids = + modest_signal_mgr_connect (priv->modal_handler_uids, + G_OBJECT (window), + "response", + G_CALLBACK (on_modal_dialog_close), + self); + else + priv->modal_handler_uids = + modest_signal_mgr_connect (priv->modal_handler_uids, + G_OBJECT (window), + "delete-event", + G_CALLBACK (on_modal_window_close), + self); } @@ -892,3 +952,81 @@ modest_window_mgr_save_state_for_all_windows (ModestWindowMgr *self) win = g_list_next (win); } } + +static gboolean +idle_top_modal (gpointer data) +{ + ModestWindowMgr *self = MODEST_WINDOW_MGR (data); + ModestWindowMgrPrivate *priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + GtkWindow *topmost; + + /* Get the top modal */ + g_mutex_lock (priv->queue_lock); + topmost = (GtkWindow *) g_queue_peek_head (priv->modal_windows); + g_mutex_unlock (priv->queue_lock); + + /* Show it */ + if (topmost) + gtk_window_present (topmost); + + return FALSE; +} + +static void +remove_modal_from_queue (GtkWidget *widget, + ModestWindowMgr *self) +{ + ModestWindowMgrPrivate *priv; + GList *item = NULL; + + priv = MODEST_WINDOW_MGR_GET_PRIVATE (self); + + /* Remove from queue. We don't use remove, because we want to + exit if the widget does not belong to the queue */ + g_mutex_lock (priv->queue_lock); + item = g_queue_find (priv->modal_windows, widget); + if (!item) { + g_warning ("Trying to remove a modal window that is not registered"); + g_mutex_unlock (priv->queue_lock); + return; + } + g_queue_unlink (priv->modal_windows, item); + g_mutex_unlock (priv->queue_lock); + + /* Disconnect handler */ + priv->modal_handler_uids = + modest_signal_mgr_disconnect (priv->modal_handler_uids, + G_OBJECT (widget), + GTK_IS_DIALOG (widget) ? + "response" : + "destroy-event"); + + /* Schedule the next one for being shown */ + g_idle_add (idle_top_modal, self); +} + +static gboolean +on_modal_window_close (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data); + + /* Remove modal window from queue */ + remove_modal_from_queue (widget, self); + + /* Continue */ + return FALSE; +} + +static void +on_modal_dialog_close (GtkDialog *dialog, + gint arg1, + gpointer user_data) +{ + ModestWindowMgr *self = MODEST_WINDOW_MGR (user_data); + + /* Remove modal window from queue */ + remove_modal_from_queue (GTK_WIDGET (dialog), self); +} + diff --git a/src/widgets/modest-window-mgr.h b/src/widgets/modest-window-mgr.h index 2ee6e83..4b1e697 100644 --- a/src/widgets/modest-window-mgr.h +++ b/src/widgets/modest-window-mgr.h @@ -138,14 +138,14 @@ ModestWindow* modest_window_mgr_get_main_window (ModestWindowMgr *self); /** - * modest_window_mgr_get_modal_dialog: + * modest_window_mgr_get_modal: * @self: a #ModestWindowMgr * - * get the modal dialog; if it's NULL, there's no active dialog + * get the modal window; if it's NULL, there's no active modal window * - * Returns: the modal dialog or NULL + * Returns: the modal window or NULL **/ -GtkDialog* modest_window_mgr_get_modal_dialog (ModestWindowMgr *self); +GtkWindow* modest_window_mgr_get_modal (ModestWindowMgr *self); /** @@ -156,9 +156,8 @@ GtkDialog* modest_window_mgr_get_modal_dialog (ModestWindowMgr *self); * * Returns: the modal dialog just set **/ -GtkDialog* modest_window_mgr_set_modal_dialog (ModestWindowMgr *self, - GtkDialog *dialog); - +void modest_window_mgr_set_modal (ModestWindowMgr *self, + GtkWindow *window); /** * modest_window_mgr_prevent_hibernation_while_window_is_shown: -- 1.7.9.5