* leak fixes; free both list and its elements when we call modest_account_mgr_account...
[modest] / src / modest-tny-account-store.c
index 7733aa8..f5da3b4 100644 (file)
@@ -81,9 +81,9 @@ static void    modest_tny_account_store_instance_init (ModestTnyAccountStore *ob
 static void    modest_tny_account_store_init          (gpointer g, gpointer iface_data);
 
 
-static void
-get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type);
-
+static void    get_server_accounts                    (TnyAccountStore *self, 
+                                                      TnyList *list, 
+                                                      TnyAccountType type);
 
 /* list my signals */
 enum {
@@ -317,37 +317,55 @@ on_vfs_volume_unmounted(GnomeVFSVolumeMonitor *volume_monitor,
 }
 
 static void
-on_account_removed (ModestAccountMgr *acc_mgr, const gchar *account, gboolean server_account,
+on_account_removed (ModestAccountMgr *acc_mgr, 
+                   const gchar *account,
+                   gboolean server_account,
                    gpointer user_data)
 {
        ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
+       TnyAccount *store_account;
+       
+       /* Clear the account cache */
+       store_account = modest_tny_account_store_get_tny_account_by  (self, 
+                                                                     MODEST_TNY_ACCOUNT_STORE_QUERY_NAME, 
+                                                                     account);
+       if (store_account) {
+               tny_store_account_delete_cache (TNY_STORE_ACCOUNT (store_account));
+               
+               g_signal_emit (G_OBJECT (self), 
+                                        tny_account_store_signals [TNY_ACCOUNT_STORE_ACCOUNT_REMOVED], 
+                                        0, store_account);
+
+               g_object_unref (store_account);
+       } else
+               g_printerr ("modest: cannot find server account for %s", account);
        
-       /* FIXME: make this more finegrained; changes do not really affect _all_
-        * accounts, and some do not affect tny accounts at all (such as 'last_update')
+       /* FIXME: make this more finegrained; changes do not
+        * really affect _all_ accounts, and some do not
+        * affect tny accounts at all (such as 'last_update')
         */
-       if (server_account)
-               recreate_all_accounts (self);
-       
+       recreate_all_accounts (self);
+
        g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0,
                       account);
 }
 
 static void
 on_account_changed (ModestAccountMgr *acc_mgr, const gchar *account,
-                   const gchar *key, gboolean server_account, gpointer user_data)
+                   const GSList *keys, gboolean server_account, gpointer user_data)
 
 {
        ModestTnyAccountStore *self = MODEST_TNY_ACCOUNT_STORE(user_data);
        
        /* Ignore the change if it's a change in the last_updated value */
-       if (g_str_has_suffix (key, MODEST_ACCOUNT_LAST_UPDATED))
+       if (g_slist_length ((GSList *)keys) == 1 &&
+           g_str_has_suffix ((const gchar *) keys->data, MODEST_ACCOUNT_LAST_UPDATED))
                return;
 
        /* FIXME: make this more finegrained; changes do not really affect _all_
-        * accounts, and some do not affect tny accounts at all (such as 'last_update')
+        * accounts
         */
-       if (server_account)
-               recreate_all_accounts (self);
+       recreate_all_accounts (self);
 
        g_signal_emit (G_OBJECT(self), signals[ACCOUNT_UPDATE_SIGNAL], 0,
                       account);
@@ -606,8 +624,9 @@ create_per_account_local_outbox_folders (TnyAccountStore *self)
                                
                accounts = g_slist_append (accounts, tny_account_outbox); /* cache it */
        };
-       
-       g_slist_free (account_names);
+
+       modest_account_mgr_free_account_names (account_names);
+       account_names = NULL;
        
        priv->store_accounts_outboxes = accounts;
 }
@@ -620,8 +639,6 @@ static void
 get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type)
 {
        g_return_if_fail (self);
-       
-       /* printf ("DEBUG: %s: list=%p, type=%d\n", __FUNCTION__, list, type); */
                
        ModestTnyAccountStorePrivate *priv = 
                MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
@@ -635,8 +652,8 @@ get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type)
                        return;
        }
        
-       GSList                       *account_names = NULL, *cursor = NULL;
-       GSList                       *accounts = NULL;
+       GSList *account_names = NULL, *cursor = NULL;
+       GSList *accounts = NULL;
 
        /* These are account names, not server_account names */
        account_names = modest_account_mgr_account_names (priv->account_mgr,FALSE);
@@ -748,13 +765,11 @@ get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type)
                        iter_account_names = g_slist_next (iter_account_names);
                }               
        }
-       
-       g_slist_free (account_names);
+
+       /* free the account_names */
+       modest_account_mgr_free_account_names (account_names);
        account_names = NULL;
-       
-       /* TODO: Delete the strings in the GSList */
-       
-       
+
        /* We also create a per-account local outbox folder (a _store_ account) 
         * for each _transport_ account. */
        if (type == TNY_ACCOUNT_TYPE_TRANSPORT) {
@@ -775,6 +790,11 @@ get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type)
                        create_per_account_local_outbox_folders (self);
                }
        
+               /* Also add the local folder pseudo-account: */
+               TnyAccount *tny_account =
+                       modest_tny_account_new_for_local_folders (priv->account_mgr, 
+                               priv->session, NULL);
+                                       
                /* Add them to the TnyList: */
                if (priv->store_accounts_outboxes) {
                        GSList *iter = NULL;
@@ -786,25 +806,21 @@ get_server_accounts  (TnyAccountStore *self, TnyList *list, TnyAccountType type)
                                g_object_ref (outbox_account);
                                accounts = g_slist_append (accounts, outbox_account);
                        }
+               }
+               
+               /* Add a merged folder, merging all the per-account outbox folders: */
+               modest_tny_local_folders_account_add_merged_outbox_folders (
+                       MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (tny_account), priv->store_accounts_outboxes);
                        
-                       
-                       /* Also add the local folder pseudo-account: */
-                       TnyAccount *tny_account =
-                               modest_tny_account_new_for_local_folders (priv->account_mgr, 
-                                       priv->session, NULL);
-                       /* Add a merged folder, merging all the per-account outbox folders: */
-                       modest_tny_local_folders_account_add_merged_outbox_folders (
-                               MODEST_TNY_LOCAL_FOLDERS_ACCOUNT (tny_account), priv->store_accounts_outboxes);
-       
-                       if (list)
-                               tny_list_prepend (list, G_OBJECT(tny_account));
-                       accounts = g_slist_append (accounts, tny_account); /* cache it */
-                       
-                       
+               if (priv->store_accounts_outboxes) {
                        /* We have finished with this temporary list, so free it: */
                        account_list_free (priv->store_accounts_outboxes);
                        priv->store_accounts_outboxes = NULL;
                }
+               
+               if (list)
+                       tny_list_prepend (list, G_OBJECT(tny_account));
+               accounts = g_slist_append (accounts, tny_account); /* cache it */       
        }
                
        if (type == TNY_ACCOUNT_TYPE_STORE) {
@@ -887,35 +903,9 @@ modest_tny_account_store_get_device (TnyAccountStore *self)
 static TnyAccount*
 modest_tny_account_store_find_account_by_url (TnyAccountStore *self, const gchar* url_string)
 {
-       TnyAccount *account = NULL;
-       ModestTnyAccountStorePrivate *priv;     
-       GSList *cursor;
-       
-       g_return_val_if_fail (self, NULL);
-       g_return_val_if_fail (url_string, NULL);
-       
-       priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
-
-       for (cursor = priv->store_accounts; cursor ; cursor = cursor->next) {
-               if (tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), url_string)) {
-                       account = TNY_ACCOUNT(cursor->data);
-                       break;
-               }
-       }
-
-       if (!account) {
-               for (cursor = priv->transport_accounts; !account && cursor ; cursor = cursor->next) {
-                       if (tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), url_string)) {
-                               account = TNY_ACCOUNT(cursor->data);
-                               break;
-                       }
-               }
-       }
-
-       if (account)
-               g_object_ref (G_OBJECT(account));
-
-       return account;
+       return modest_tny_account_store_get_tny_account_by (MODEST_TNY_ACCOUNT_STORE (self), 
+                                                           MODEST_TNY_ACCOUNT_STORE_QUERY_URL,
+                                                           url_string);
 }
 
 
@@ -924,6 +914,8 @@ static gboolean
 modest_tny_account_store_alert (TnyAccountStore *self, TnyAlertType type,
                                gboolean question, const GError *error)
 {
+       /* TODO: It would be nice to know what account caused this error. */
+       
        g_return_val_if_fail (error, FALSE);
 
        if ((error->domain != TNY_ACCOUNT_ERROR) 
@@ -943,15 +935,20 @@ modest_tny_account_store_alert (TnyAccountStore *self, TnyAlertType type,
                /* The tinymail camel implementation just sends us this for almost 
                 * everything, so we have to guess at the cause.
                 * It could be a wrong password, or inability to resolve a hostname, 
-                * or lack of network, or something entirely different: */
+                * or lack of network, or incorrect authentication method, or something entirely different: */
+               /* TODO: Fix camel to provide specific error codes, and then use the 
+                * specific dialog messages from Chapter 12 of the UI spec.
+                */
                case TNY_ACCOUNT_STORE_ERROR_UNKNOWN_ALERT: 
-                   g_debug ("%s: Handling GError domain=%d, code=%d, message=%s", 
-                               __FUNCTION__, error->domain, error->code, error->message);
+/*                 g_debug ("%s: Handling GError domain=%d, code=%d, message=%s",  */
+/*                             __FUNCTION__, error->domain, error->code, error->message); */
                        
                        /* TODO: Remove the internal error message for the real release.
                         * This is just so the testers can give us more information: */
                        /* prompt = _("Modest account not yet fully configured."); */
-                       prompt = g_strdup_printf(_("Modest account not yet fully configured. Error=%s"), 
+                       prompt = g_strdup_printf(
+                               "%s\n (Internal error message, often very misleading):\n%s", 
+                               _("Incorrect Account Settings"), 
                                error->message);
                                
                        /* TODO: If we can ever determine that the problem is a wrong password:
@@ -987,7 +984,7 @@ modest_tny_account_store_alert (TnyAccountStore *self, TnyAlertType type,
                        break;
                        
                //TODO: We have started receiving errors of 
-               //domain=TNY_ACCOUNT_ERROR, code=TNY_ACCOUNT_ERROR_TRY_CONNECT, messagae="Canceled".
+               //domain=TNY_ACCOUNT_ERROR, code=TNY_ACCOUNT_ERROR_TRY_CONNECT, message="Canceled".
                //If this is really a result of us cancelling our own operation then 
                //a) this probably shouldn't be an error, and
                //b) should have its own error code.
@@ -1092,35 +1089,72 @@ modest_tny_account_store_get_session  (TnyAccountStore *self)
 
 
 TnyAccount*
-modest_tny_account_store_get_tny_account_by_id  (ModestTnyAccountStore *self, const gchar *id)
+modest_tny_account_store_get_tny_account_by (ModestTnyAccountStore *self, 
+                                            ModestTnyAccountStoreQueryType type,
+                                            const gchar *str)
 {
        TnyAccount *account = NULL;
        ModestTnyAccountStorePrivate *priv;     
        GSList *cursor;
+       const gchar *val = NULL;
 
        g_return_val_if_fail (self, NULL);
-       g_return_val_if_fail (id, NULL);
+       g_return_val_if_fail (str, NULL);
        
        priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
 
-
+       /* Search in store accounts */
        for (cursor = priv->store_accounts; cursor ; cursor = cursor->next) {
-               const gchar *acc_id = tny_account_get_id (TNY_ACCOUNT(cursor->data));
-               if (acc_id && strcmp (acc_id, id) == 0) {
-                       account = TNY_ACCOUNT(cursor->data);
+               switch (type) {
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_ID:
+                       val = tny_account_get_id (TNY_ACCOUNT(cursor->data));
+                       break;
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_NAME:
+                       val = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT(cursor->data));
                        break;
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_URL:
+                       val = tny_account_get_url_string (TNY_ACCOUNT(cursor->data));
+                       break;
+               }
+               
+               if (type == MODEST_TNY_ACCOUNT_STORE_QUERY_URL && 
+                   tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), val)) {
+                       account = TNY_ACCOUNT (cursor->data);
+                       goto end;
+               } else {
+                       if (strcmp (val, str) == 0) {
+                               account = TNY_ACCOUNT(cursor->data);
+                               goto end;
+                       }
                }
        }
                
        /* if we already found something, no need to search the transport accounts */
        for (cursor = priv->transport_accounts; !account && cursor ; cursor = cursor->next) {
-               const gchar *acc_id = tny_account_get_id (TNY_ACCOUNT(cursor->data));
-               if (acc_id && strcmp (acc_id, id) == 0) {
-                       account = TNY_ACCOUNT(cursor->data);
+               switch (type) {
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_ID:
+                       val = tny_account_get_id (TNY_ACCOUNT(cursor->data));
+                       break;
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_NAME:
+                       val = tny_account_get_name (TNY_ACCOUNT(cursor->data));
+                       break;
+               case MODEST_TNY_ACCOUNT_STORE_QUERY_URL:
+                       val = tny_account_get_url_string (TNY_ACCOUNT(cursor->data));
                        break;
                }
+               
+               if (type == MODEST_TNY_ACCOUNT_STORE_QUERY_URL && 
+                   tny_account_matches_url_string (TNY_ACCOUNT(cursor->data), val)) {
+                       account = TNY_ACCOUNT (cursor->data);
+                       goto end;
+               } else {
+                       if (strcmp (val, str) == 0) {
+                               account = TNY_ACCOUNT(cursor->data);
+                               goto end;
+                       }
+               }
        }
-
+ end:
        if (account)
                g_object_ref (G_OBJECT(account));
        
@@ -1128,7 +1162,7 @@ modest_tny_account_store_get_tny_account_by_id  (ModestTnyAccountStore *self, co
 }
 
 TnyAccount*
-modest_tny_account_store_get_tny_account_by_account (ModestTnyAccountStore *self,
+modest_tny_account_store_get_server_account (ModestTnyAccountStore *self,
                                                     const gchar *account_name,
                                                     TnyAccountType type)
 {
@@ -1144,15 +1178,19 @@ modest_tny_account_store_get_tny_account_by_account (ModestTnyAccountStore *self
        priv = MODEST_TNY_ACCOUNT_STORE_GET_PRIVATE(self);
 
        /* Special case for the local account */
-       if (!strcmp (account_name, MODEST_ACTUAL_LOCAL_FOLDERS_ACCOUNT_ID) && 
-           type == TNY_ACCOUNT_TYPE_STORE) {
-               id = g_strdup (MODEST_ACTUAL_LOCAL_FOLDERS_ACCOUNT_ID);
+       if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
+               if(type == TNY_ACCOUNT_TYPE_STORE)
+                       id = g_strdup (MODEST_LOCAL_FOLDERS_ACCOUNT_ID);
+               else {
+                       /* The local folders modest account has no transport server account. */
+                       return NULL;
+               }
        } else {
                ModestAccountData *account_data;
-
                account_data = modest_account_mgr_get_account_data (priv->account_mgr, account_name);
                if (!account_data) {
-                       g_printerr ("modest: %s: cannot get account data for account '%s'\n", __FUNCTION__, account_name);
+                       g_printerr ("modest: %s: cannot get account data for account '%s'\n", __FUNCTION__,
+                                   account_name);
                        return NULL;
                }
 
@@ -1168,7 +1206,7 @@ modest_tny_account_store_get_tny_account_by_account (ModestTnyAccountStore *self
                g_printerr ("modest: could not get an id for account %s\n",
                            account_name);
        else    
-               account = modest_tny_account_store_get_tny_account_by_id (self, id);
+               account = modest_tny_account_store_get_tny_account_by (self, MODEST_TNY_ACCOUNT_STORE_QUERY_ID, id);
 
        if (!account)
                g_printerr ("modest: could not get tny %s account for %s (id=%s)\n",
@@ -1215,7 +1253,9 @@ get_smtp_specific_transport_account_for_open_connection (ModestTnyAccountStore *
                return NULL; /* No connection-specific SMTP server was specified for this connection. */
        }
                
-       TnyAccount* account = modest_tny_account_store_get_tny_account_by_id (self, server_account_name);
+       TnyAccount* account = modest_tny_account_store_get_tny_account_by (self, 
+                                                                          MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
+                                                                          server_account_name);
 
        /* printf ("DEBUG: %s: account=%p\n", __FUNCTION__, account); */
        g_free (server_account_name);   
@@ -1241,21 +1281,28 @@ modest_tny_account_store_get_transport_account_for_open_connection (ModestTnyAcc
         * just get the regular transport account: */
        if (!account) {
                /* printf("DEBUG: %s: using regular transport account for account %s.\n", __FUNCTION__, account_name); */
-               account = modest_tny_account_store_get_tny_account_by_account (self, account_name, 
+
+               /* The special local folders don't have transport accounts. */
+               if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) == 0)
+                       account = NULL;
+               else
+                       account = modest_tny_account_store_get_server_account (self, account_name, 
                                                     TNY_ACCOUNT_TYPE_TRANSPORT);
        }
                             
        return account;
 }
 
-gboolean modest_tny_account_is_virtual_local_folders (TnyAccount *self)
+gboolean
+modest_tny_account_is_virtual_local_folders (TnyAccount *self)
 {
        /* We should make this more sophisticated if we ever use ModestTnyLocalFoldersAccount 
         * for anything else. */
        return MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (self);
 }
 
-TnyAccount* modest_tny_account_store_get_local_folders_account (TnyAccountStore *self)
+TnyAccount*
+modest_tny_account_store_get_local_folders_account (TnyAccountStore *self)
 {
        TnyAccount *account = NULL;
        ModestTnyAccountStorePrivate *priv;