Activate a modal dialog only on UI DBus requests
[modest] / src / dbus_api / modest-dbus-callbacks.c
index 51d7226..d9a184a 100644 (file)
@@ -1531,13 +1531,41 @@ on_idle_show_memory_low (gpointer user_data)
 static gboolean
 on_idle_present_modal (gpointer user_data)
 {
+       GtkWindow *current, *transient;
        gdk_threads_enter ();
-       gtk_window_present (user_data);
+       current = (GtkWindow *) user_data;
+       while (GTK_IS_DIALOG (current)) {
+               transient = gtk_window_get_transient_for (GTK_WINDOW (current));
+               if (transient == NULL)
+                       break;
+               else
+                       current = transient;
+       }
+       gtk_window_present (current);
        gdk_threads_leave ();
 
        return FALSE;
 }
 
+/**
+  * This function checks if a modal dialog should be activated
+  * instead of other UI components on a DBus request, and if yes, starts the request
+  * @return TRUE if a modal dialog is about to be acitvated
+  * @note This function should be used before activating any Modest UI element on DBus request
+  */
+static gboolean
+modest_dbus_check_present_modal ()
+{
+       GtkWindow *dialog;
+
+       /* Check if there is already a dialog or note open */
+       dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
+       if (dialog) {
+               g_idle_add (on_idle_present_modal, dialog);
+       }
+
+       return (NULL != dialog);
+}
 
 /* Callback for normal D-BUS messages */
 gint
@@ -1545,41 +1573,32 @@ modest_dbus_req_handler(const gchar * interface, const gchar * method,
                        GArray * arguments, gpointer data,
                        osso_rpc_t * retval)
 {
-       GtkWindow *dialog;
-
        /* Check memory low conditions */
        if (modest_platform_check_memory_low (NULL, FALSE)) {
                g_idle_add (on_idle_show_memory_low, NULL);
                goto param_error;
        }
 
-       /* Check if there is already a dialog or note open */
-       dialog = modest_window_mgr_get_modal (modest_runtime_get_window_mgr());
-       if (dialog) {
-               g_idle_add (on_idle_present_modal, dialog);
-               return OSSO_OK;
-       }
-
        if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_MAIL_TO) == 0) {
                if (arguments->len != MODEST_DBUS_MAIL_TO_ARGS_COUNT)
                        goto param_error;
-               return on_mail_to (arguments, data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_mail_to (arguments, data, retval);
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_OPEN_MESSAGE) == 0) {
                if (arguments->len != MODEST_DBUS_OPEN_MESSAGE_ARGS_COUNT)
                        goto param_error;
-               return on_open_message (arguments, data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_open_message (arguments, data, retval);
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_OPEN_ACCOUNT) == 0) {
                if (arguments->len != MODEST_DBUS_OPEN_ACCOUNT_ARGS_COUNT)
                        goto param_error;
-               return on_open_account (arguments, data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_open_account (arguments, data, retval);
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_SEND_RECEIVE) == 0) {
                if (arguments->len != 0)
                        goto param_error;
-               return on_send_receive (arguments, data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_send_receive (arguments, data, retval);
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_SEND_RECEIVE_FULL) == 0) {
                if (arguments->len != MODEST_DBUS_SEND_RECEIVE_FULL_ARGS_COUNT)
                        goto param_error;
-               return on_send_receive_full (arguments, data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_send_receive_full (arguments, data, retval);
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_UPDATE_FOLDER_COUNTS) == 0) {
                if (arguments->len != MODEST_DBUS_UPDATE_FOLDER_COUNTS_ARGS_COUNT)
                        goto param_error;
@@ -1587,23 +1606,23 @@ modest_dbus_req_handler(const gchar * interface, const gchar * method,
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_COMPOSE_MAIL) == 0) {
                if (arguments->len != MODEST_DBUS_COMPOSE_MAIL_ARGS_COUNT)
                        goto param_error;
-               return on_compose_mail (arguments, data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_compose_mail (arguments, data, retval);
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_DELETE_MESSAGE) == 0) {
                if (arguments->len != MODEST_DBUS_DELETE_MESSAGE_ARGS_COUNT)
                        goto param_error;
-               return on_delete_message (arguments,data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_delete_message (arguments,data, retval);
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_OPEN_DEFAULT_INBOX) == 0) {
                if (arguments->len != 0)
                        goto param_error;
-               return on_open_default_inbox (arguments, data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_open_default_inbox (arguments, data, retval);
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_TOP_APPLICATION) == 0) {
                if (arguments->len != 0)
                        goto param_error;
-               return on_top_application (arguments, data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_top_application (arguments, data, retval);
        } else if (g_ascii_strcasecmp (method, MODEST_DBUS_METHOD_OPEN_EDIT_ACCOUNTS_DIALOG) == 0) {
                if (arguments->len != 0)
                        goto param_error;
-               return on_open_edit_accounts_dialog (arguments, data, retval);
+               return modest_dbus_check_present_modal () ? OSSO_OK : on_open_edit_accounts_dialog (arguments, data, retval);
        } else {
                /* We need to return INVALID here so
                 * libosso will return DBUS_HANDLER_RESULT_NOT_YET_HANDLED,
@@ -1643,6 +1662,8 @@ modest_dbus_req_handler(const gchar * interface, const gchar * method,
        DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
        DBUS_TYPE_STRING_AS_STRING \
        DBUS_TYPE_STRING_AS_STRING \
+       DBUS_TYPE_STRING_AS_STRING \
+       DBUS_TYPE_INT64_AS_STRING \
        DBUS_TYPE_ARRAY_AS_STRING \
        ACCOUNT_HIT_DBUS_TYPE \
        DBUS_STRUCT_END_CHAR_AS_STRING
@@ -1889,6 +1910,9 @@ headers_cmp (TnyHeader *a, TnyHeader *b)
        return date_a - date_b;
 }
 
+/**
+  * The helper structure for handling GetUnreadMessages DBus request
+  */
 typedef struct {
        TnyList *accounts_list;
        TnyList *inboxes_list;
@@ -1897,12 +1921,16 @@ typedef struct {
        DBusMessage *message;
        GList *account_hits_list;
        ModestMailOperation *mail_op;
+       guint folder_requests_total; /**< Total get-folder requests number for multi-mailbox accounts */
+       guint folder_requests_done; /**< Done get-folder requests number for multi-mailbox accounts */
 } GetUnreadMessagesHelper;
 
 typedef struct {
        gchar *account_id;
        gchar *account_name;
+       gchar *store_protocol;
        gchar *mailbox_id;
+       gint unread_count;
        GList *header_list;
 } AccountHits;
 
@@ -1926,6 +1954,8 @@ static void return_results (GetUnreadMessagesHelper *helper)
                        AccountHits *ah = (AccountHits *) node->data;
                        const char *account_id;
                        const char *account_name;
+                       const char *store_protocol;
+                       gint64 unread_count;
                        DBusMessageIter ah_struct_iter;
                        DBusMessageIter sh_array_iter;
                        GList *result_node;
@@ -1936,12 +1966,20 @@ static void return_results (GetUnreadMessagesHelper *helper)
                                                          &ah_struct_iter);
                        account_id = ah->account_id;
                        account_name = ah->account_name;
+                       store_protocol = ah->store_protocol;
+                       unread_count = ah->unread_count;
                        dbus_message_iter_append_basic (&ah_struct_iter,
                                                        DBUS_TYPE_STRING,
                                                        &account_id);
                        dbus_message_iter_append_basic (&ah_struct_iter,
                                                        DBUS_TYPE_STRING,
                                                        &account_name);
+                       dbus_message_iter_append_basic (&ah_struct_iter,
+                                                       DBUS_TYPE_STRING,
+                                                       &store_protocol);
+                       dbus_message_iter_append_basic (&ah_struct_iter,
+                                                       DBUS_TYPE_INT64,
+                                                       &unread_count);
 
                        dbus_message_iter_open_container (&ah_struct_iter,
                                                          DBUS_TYPE_ARRAY,
@@ -1950,7 +1988,7 @@ static void return_results (GetUnreadMessagesHelper *helper)
                        for (result_node = ah->header_list; result_node != NULL; result_node = g_list_next (result_node)) {
                                TnyHeader *header = (TnyHeader *) result_node->data;
                                DBusMessageIter sh_struct_iter;
-                               gint64 ts = MIN (tny_header_get_date_received (header), tny_header_get_date_sent (header));
+                               gint64 ts = tny_header_get_date_received (header);
                                gchar *subject = tny_header_dup_subject (header);
 
                                dbus_message_iter_open_container (&sh_array_iter,
@@ -1975,6 +2013,7 @@ static void return_results (GetUnreadMessagesHelper *helper)
                                                           &ah_struct_iter); 
                        g_free (ah->account_id);
                        g_free (ah->account_name);
+                       g_free (ah->store_protocol);
                        g_list_free (ah->header_list);
                }
 
@@ -2012,11 +2051,16 @@ static void get_unread_messages_get_headers_cb (TnyFolder *self,
        AccountHits *account_hits;
        const gchar *folder_id;
        const gchar *bar;
+       ModestProtocolType store_protocol_type;
+       ModestProtocol *store_protocol;
+       gint unread_count;
+       ModestProtocolRegistry *registry;
 
        acc_iterator = tny_list_create_iterator (helper->accounts_list);
        account = TNY_ACCOUNT (tny_iterator_get_current (acc_iterator));
 
        headers_iterator = tny_list_create_iterator (headers);
+       unread_count = 0;
        while (!tny_iterator_is_done (headers_iterator)) {
                TnyHeader *header;
                TnyHeaderFlags flags;
@@ -2024,7 +2068,8 @@ static void get_unread_messages_get_headers_cb (TnyFolder *self,
                header = TNY_HEADER (tny_iterator_get_current (headers_iterator));
                flags = tny_header_get_flags (header);
                if (!(flags & TNY_HEADER_FLAG_SEEN)) {
-                 result_list = g_list_insert_sorted (result_list, g_object_ref (header), (GCompareFunc) headers_cmp);
+                       unread_count++;
+                       result_list = g_list_insert_sorted (result_list, g_object_ref (header), (GCompareFunc) headers_cmp);
                        if (members_count == helper->unread_msgs_count) {
                                g_object_unref (result_list->data);
                                result_list = g_list_delete_link (result_list, result_list);
@@ -2038,11 +2083,22 @@ static void get_unread_messages_get_headers_cb (TnyFolder *self,
        }
        g_object_unref (headers_iterator);
 
+       registry = modest_runtime_get_protocol_registry ();
+       store_protocol_type = modest_tny_account_get_protocol_type (account);
+
+       /* Get the number of unread messages for plug-in based accounts */
+       if (modest_protocol_registry_protocol_type_is_provider (registry, store_protocol_type)) {
+               unread_count = tny_folder_get_unread_count (self);
+       }
+
        account_hits = g_slice_new (AccountHits);
-       account_hits->account_id = g_strdup (tny_account_get_id (account));
+       account_hits->account_id = g_strdup (modest_tny_account_get_parent_modest_account_name_for_server_account (account));
        account_hits->account_name = g_strdup (tny_account_get_name (account));
+       store_protocol = modest_protocol_registry_get_protocol_by_type (registry, store_protocol_type);
+       account_hits->store_protocol = g_strdup (modest_protocol_get_name (store_protocol));
        account_hits->header_list = result_list;
        account_hits->mailbox_id = NULL;
+       account_hits->unread_count = unread_count;
 
        folder_id = tny_folder_get_id (self);
        bar = g_strstr_len (folder_id, -1, "/");
@@ -2102,7 +2158,6 @@ static void get_account_folders_cb (TnyFolderStore *self, gboolean cancelled, Tn
        GetUnreadMessagesHelper *helper = (GetUnreadMessagesHelper *) user_data;
        TnyIterator *iterator;
 
-       helper->inboxes_list =  TNY_LIST (tny_simple_list_new ());
        iterator = tny_list_create_iterator (list);
        while (!tny_iterator_is_done (iterator)) {
                TnyFolder *folder;
@@ -2121,6 +2176,92 @@ static void get_account_folders_cb (TnyFolderStore *self, gboolean cancelled, Tn
        get_unread_messages_get_headers (helper);
 }
 
+static void get_multi_mailbox_account_folders_cb (TnyFolderStore *self, gboolean cancelled, TnyList *list, GError *err, gpointer user_data)
+{
+       GetUnreadMessagesHelper *helper = (GetUnreadMessagesHelper *) user_data;
+       TnyIterator *iterator;
+
+       /* another request has been finished */
+       helper->folder_requests_done += 1;
+
+       /* analize the folders we got */
+       iterator = tny_list_create_iterator (list);
+       while (!tny_iterator_is_done (iterator)) {
+               TnyFolder *folder;
+
+               folder = TNY_FOLDER (tny_iterator_get_current (iterator));
+               if (tny_folder_get_folder_type (folder) == TNY_FOLDER_TYPE_INBOX) {
+                       tny_list_prepend (helper->inboxes_list, G_OBJECT (folder));
+               }
+
+               /* Try to check if we have inbox sub-folders in this folder */
+               if (TNY_IS_FOLDER_STORE (folder)) {
+                       TnyFolderStore *folder_store;
+
+                       folder_store = TNY_FOLDER_STORE (folder);
+                       if (folder_store) {
+                               TnyList *folders_list;
+
+                               helper->folder_requests_total += 1;
+                               folders_list = tny_simple_list_new ();
+                               tny_folder_store_get_folders_async (folder_store, folders_list,
+                                       NULL, FALSE, get_multi_mailbox_account_folders_cb, NULL, helper);
+                               g_object_unref (folders_list);
+                       }
+               }
+               g_object_unref (folder);
+               tny_iterator_next (iterator);
+       }
+       g_object_unref (iterator);
+
+       /* Check if we have handled all the inbox folders for multi-mailbox accounts */
+       if (helper->folder_requests_done == helper->folder_requests_total) {
+               TnyIterator *inboxes_it;
+               TnyIterator *accounts_it;
+               TnyAccount *account;
+               guint unread_messages;
+               AccountHits* account_hits;
+               ModestProtocol *store_protocol;
+               ModestProtocolType store_protocol_type;
+
+               /* Store the number of unread messages for the handled account */
+               unread_messages = 0;
+               accounts_it = tny_list_create_iterator (helper->accounts_list);
+               account = TNY_ACCOUNT (tny_iterator_get_current (accounts_it));
+               g_object_unref (accounts_it);
+               inboxes_it = tny_list_create_iterator (helper->inboxes_list);
+               while (!tny_iterator_is_done (inboxes_it)) {
+                       TnyFolder *folder;
+
+                       folder = TNY_FOLDER (tny_iterator_get_current (inboxes_it));
+                       if (folder) {
+                               unread_messages += tny_folder_get_unread_count (folder);
+                       }
+                       tny_iterator_next (inboxes_it);
+               }
+               g_object_unref (inboxes_it);
+               g_object_unref (helper->inboxes_list);
+               helper->inboxes_list = NULL;
+               account_hits = g_slice_new (AccountHits);
+               account_hits->account_id = g_strdup (
+                       modest_tny_account_get_parent_modest_account_name_for_server_account (account));
+               account_hits->account_name = g_strdup (tny_account_get_name (account));
+               store_protocol_type = modest_tny_account_get_protocol_type (account);
+               store_protocol = modest_protocol_registry_get_protocol_by_type (
+                       modest_runtime_get_protocol_registry (), store_protocol_type);
+               account_hits->store_protocol = g_strdup (modest_protocol_get_name (store_protocol));
+               account_hits->mailbox_id = NULL;
+               account_hits->header_list = NULL;
+               account_hits->unread_count = unread_messages;
+               helper->account_hits_list = g_list_prepend (helper->account_hits_list, account_hits);
+
+               /* remove the handled account from the accounts_list */
+               tny_list_remove (helper->accounts_list, G_OBJECT (account));
+               g_object_unref (account);
+
+               get_unread_messages_get_account (helper);
+       }
+}
 
 static void
 get_unread_messages_get_account (GetUnreadMessagesHelper *helper)
@@ -2133,19 +2274,35 @@ get_unread_messages_get_account (GetUnreadMessagesHelper *helper)
                /* all results, then finish */
                return_results (helper);
        } else {
-               TnyAccount *account = NULL;
+               TnyAccount *account;
                TnyList *folders_list;
+               ModestProtocolType protocol_type;
 
                account = TNY_ACCOUNT (tny_iterator_get_current (iterator));
-               folders_list = TNY_LIST (tny_simple_list_new ());
-               tny_folder_store_get_folders_async (TNY_FOLDER_STORE (account), folders_list, NULL,
-                                                   FALSE, get_account_folders_cb, NULL, helper);
+               protocol_type = modest_tny_account_get_protocol_type (account);
+
+               folders_list = tny_simple_list_new ();
+               helper->inboxes_list =  tny_simple_list_new ();
+               if (MODEST_PROTOCOL_REGISTRY_TYPE_INVALID != protocol_type &&
+                       modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
+                               protocol_type, MODEST_PROTOCOL_REGISTRY_MULTI_MAILBOX_PROVIDER_PROTOCOLS)) {
+                       /* For multi-mailbox protocols we only can get the number of unread messages,
+                          we will not even try to get their email headers */
+                       helper->folder_requests_done = 0;
+                       helper->folder_requests_total = 1;
+                       tny_folder_store_get_folders_async (TNY_FOLDER_STORE (account),
+                               folders_list, NULL, FALSE, get_multi_mailbox_account_folders_cb, NULL, helper);
+               }
+               else {
+                       /* For non-multi-mailbox protocols we will get their email headers */
+                       tny_folder_store_get_folders_async (TNY_FOLDER_STORE (account),
+                               folders_list, NULL, FALSE, get_account_folders_cb, NULL, helper);
+               }
                g_object_unref (folders_list);
                g_object_unref (account);
 
        }
        g_object_unref (iterator);
-
 }
 
 static gboolean