* Fixed NB#62792, the editor is closed if the account is removed
authorSergio Villar Senin <svillar@igalia.com>
Fri, 28 Sep 2007 17:22:09 +0000 (17:22 +0000)
committerSergio Villar Senin <svillar@igalia.com>
Fri, 28 Sep 2007 17:22:09 +0000 (17:22 +0000)
        * 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
src/maemo/easysetup/modest-easysetup-wizard.c
src/maemo/modest-account-view-window.c
src/maemo/modest-msg-edit-window.c
src/maemo/modest-platform.c
src/modest-signal-mgr.c
src/modest-signal-mgr.h
src/modest-ui-actions.c
src/modest-ui-actions.h
src/widgets/modest-window-mgr.c
src/widgets/modest-window-mgr.h

index e92cdfe..962a675 100644 (file)
@@ -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, "
index 21165b5..b86f40d 100644 (file)
@@ -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");
                        }
index 3e90c4b..3c92994 100644 (file)
@@ -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)
index e09c165..6ea1354 100644 (file)
@@ -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 <tny-simple-list.h>
@@ -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));
+       }
+}
index 586a455..f521639 100644 (file)
@@ -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);
index 73a76d2..d8be1d3 100644 (file)
  */
 
 #include "modest-signal-mgr.h"
+#include <string.h>
 
 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);
+}
index bd0ae8e..9fea07a 100644 (file)
@@ -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__*/
index 3d154ca..8b29b6e 100644 (file)
@@ -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;
        }
        
index 2979779..5855060 100644 (file)
@@ -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,
index 32dc0f3..33ec152 100644 (file)
@@ -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);
+}
+
index 2ee6e83..4b1e697 100644 (file)
@@ -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: