static void modest_account_mgr_finalize (GObject * obj);
static void modest_account_mgr_base_init (gpointer g_class);
+static const gchar *
+_modest_account_mgr_get_account_keyname_cached (ModestAccountMgrPrivate *priv, const gchar* account_name,
+ const gchar *name, gboolean is_server);
+
/* list my signals */
enum {
ACCOUNT_INSERTED_SIGNAL,
ACCOUNT_CHANGED_SIGNAL,
ACCOUNT_REMOVED_SIGNAL,
ACCOUNT_BUSY_SIGNAL,
+ DEFAULT_ACCOUNT_CHANGED_SIGNAL,
LAST_SIGNAL
};
static GObjectClass *parent_class = NULL;
static guint signals[LAST_SIGNAL] = {0};
-/* /\* We signal key changes in batches, every X seconds: *\/ */
-/* static gboolean */
-/* on_timeout_notify_changes (gpointer data) */
-/* { */
-/* ModestAccountMgr *self = MODEST_ACCOUNT_MGR (data); */
-/* ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self); */
+/* is the account already in the queue? */
+static gboolean
+in_change_queue (GSList *change_queue, const gchar *account)
+{
+ GSList *cursor = change_queue;
+ while (cursor) {
+ const gchar *acc = cursor->data;
+ if (acc && strcmp (acc, account) == 0)
+ return TRUE;
+ cursor = g_slist_next (cursor);
+ }
+ return FALSE;
+}
+
+static GSList*
+add_to_change_queue (GSList *change_queue, const gchar *account_name)
+{
+ g_return_val_if_fail (account_name, change_queue);
+ return g_slist_prepend (change_queue, g_strdup (account_name));
+}
+
+
+/* we don't need to track specific accounts, as in our UI case
+ * it's impossible to change two accounts within .5 seconds.
+ * still, we might want to allow that later, and then this func
+ * will come in handy */
+#if 0
+static GSList*
+remove_from_queue (GSList *change_queue, const gchar *account)
+{
+ GSList *cursor = change_queue;
+ while (cursor) {
+ const gchar *acc = cursor->data;
+ if (acc && strcmp (acc, account) == 0) {
+ g_free (acc);
+ return g_slist_delete_link (change_queue, cursor);
+ }
+ cursor = g_slist_next (cursor);
+ }
+ return change_queue;
+}
+#endif
+
+static gboolean
+on_timeout_notify_changes (gpointer data)
+{
+ ModestAccountMgr *self = MODEST_ACCOUNT_MGR (data);
+ ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
-/* /\* TODO: Also store the account names, and notify one list for each account, */
-/* * if anything uses the account names. *\/ */
+ GSList *cursor = priv->change_queue;
+ while (cursor) {
+ const gchar *account = cursor->data;
+ if (account)
+ g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0,
+ account);
+ cursor = g_slist_next (cursor);
+ }
-/* if (priv->changed_conf_keys) { */
-/* gchar *default_account = */
-/* modest_account_mgr_get_default_account (self); */
-
-/* /\* printf ("DEBUG: %s: priv->changed_conf_key length=%d\n", */
-/* __FUNCTION__, g_slist_length (priv->changed_conf_keys)); *\/ */
-/* g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0, */
-/* default_account, priv->changed_conf_keys, FALSE); */
-
-/* g_free (default_account); */
-
-/* g_slist_foreach (priv->changed_conf_keys, (GFunc) g_free, NULL); */
-/* g_slist_free (priv->changed_conf_keys); */
-/* priv->changed_conf_keys = NULL; */
-/* } */
+ /* free our queue */
+ g_slist_foreach (priv->change_queue, (GFunc)g_free, NULL);
+ g_slist_free (priv->change_queue);
+ priv->change_queue = NULL;
+ priv->timeout = 0; /* hmmm */
+
+ return FALSE; /* don't call me again */
+}
+
+
+/* little hack to retrieve the account name from a server account name,
+ * by relying on the convention for that. Note: this changes the
+ * string in-place
+ *
+ * server accounts look like fooID_transport or fooID_store
+ * FIXME: make the suffixes more explicit in the account setup
+ */
+static void
+get_account_name_from_server_account (gchar *server_account_name)
+{
+ static const gchar *t = "ID_transport";
+ static const gchar *s = "ID_store";
+ const guint len_t = strlen (t);
+ const guint len_s = strlen (s);
-/* return TRUE; /\* Call this again later. *\/ */
-/* } */
+ guint len_a = strlen (server_account_name);
+
+ if (g_str_has_suffix (server_account_name, t))
+ server_account_name [len_a - len_t] = '\0';
+ else if (g_str_has_suffix (server_account_name, s))
+ server_account_name [len_a - len_s] = '\0';
+}
+
+
static void
on_key_change (ModestConf *conf, const gchar *key, ModestConfEvent event,
ModestConfNotificationId id, gpointer user_data)
{
ModestAccountMgr *self = MODEST_ACCOUNT_MGR (user_data);
+ ModestAccountMgrPrivate *priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+
gboolean is_account_key;
gboolean is_server_account;
- gchar* account = NULL;
+ gchar* account_name = NULL;
- /* there is only one not-really-account key which will still emit
- * a signal: a change in MODEST_CONF_DEFAULT_ACCOUNT */
+ /* Notify that the default account has changed */
if (key && strcmp (key, MODEST_CONF_DEFAULT_ACCOUNT) == 0) {
- /* Get the default account instead. */
- gchar *default_account = modest_account_mgr_get_default_account (self);
- if (!default_account) {
- g_warning ("BUG: cannot find default account");
- return;
- } else {
- g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0,
- default_account, key, FALSE);
- g_free(default_account);
- return;
- }
+ g_signal_emit (G_OBJECT(self), signals[DEFAULT_ACCOUNT_CHANGED_SIGNAL], 0);
+ return;
}
is_account_key = FALSE;
is_server_account = FALSE;
- account = _modest_account_mgr_account_from_key (key, &is_account_key,
- &is_server_account);
+ account_name = _modest_account_mgr_account_from_key (key, &is_account_key,
+ &is_server_account);
/* if this is not an account-related key change, ignore */
- if (!account)
+ if (!account_name)
return;
/* account was removed. Do not emit an account removed signal
account keys for the same reason */
if ((is_account_key || is_server_account) &&
event == MODEST_CONF_EVENT_KEY_UNSET) {
- g_free (account);
+ g_free (account_name);
return;
}
+ /* ignore server account changes */
+ if (is_server_account)
+ /* change in place: retrieve the parent account name */
+ get_account_name_from_server_account (account_name);
+
/* is this account enabled? */
gboolean enabled = FALSE;
if (is_server_account)
enabled = TRUE;
else
- enabled = modest_account_mgr_get_enabled (self, account);
+ enabled = modest_account_mgr_get_enabled (self, account_name);
/* Notify is server account was changed, default account was changed
* or when enabled/disabled changes:
*/
- if (enabled ||
- g_str_has_suffix (key, MODEST_ACCOUNT_ENABLED) ||
+ if (!is_server_account)
+ if (enabled || g_str_has_suffix (key, MODEST_ACCOUNT_ENABLED) ||
strcmp (key, MODEST_CONF_DEFAULT_ACCOUNT) == 0) {
- g_signal_emit (G_OBJECT(self), signals[ACCOUNT_CHANGED_SIGNAL], 0,
- account, key, is_server_account);
- /* Store the key for later notification in our timeout callback.
- * Notifying for every key change would cause unnecessary work: */
+ if (!in_change_queue (priv->change_queue, account_name)) {
+ priv->change_queue = add_to_change_queue (priv->change_queue,
+ account_name);
+ /* hmm, small race when this object is destroyed within
+ * 500ms of the last change, and there are multiple timeouts... */
+ priv->timeout = g_timeout_add (500, (GSourceFunc) on_timeout_notify_changes,
+ self);
+ }
}
- g_free (account);
+ g_free (account_name);
}
g_signal_new ("account_inserted",
MODEST_TYPE_ACCOUNT_MGR,
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET(ModestAccountMgrClass,account_inserted),
+ G_STRUCT_OFFSET(ModestAccountMgrClass, account_inserted),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
g_signal_new ("account_removed",
MODEST_TYPE_ACCOUNT_MGR,
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET(ModestAccountMgrClass,account_removed),
+ G_STRUCT_OFFSET(ModestAccountMgrClass, account_removed),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1, G_TYPE_STRING);
g_signal_new ("account_changed",
MODEST_TYPE_ACCOUNT_MGR,
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET(ModestAccountMgrClass,account_changed),
+ G_STRUCT_OFFSET(ModestAccountMgrClass, account_changed),
NULL, NULL,
- modest_marshal_VOID__STRING_STRING_BOOLEAN,
- G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
signals[ACCOUNT_BUSY_SIGNAL] =
g_signal_new ("account_busy_changed",
MODEST_TYPE_ACCOUNT_MGR,
G_SIGNAL_RUN_FIRST,
- G_STRUCT_OFFSET(ModestAccountMgrClass,account_busy_changed),
+ G_STRUCT_OFFSET(ModestAccountMgrClass, account_busy_changed),
NULL, NULL,
modest_marshal_VOID__STRING_BOOLEAN,
G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_BOOLEAN);
+ signals[DEFAULT_ACCOUNT_CHANGED_SIGNAL] =
+ g_signal_new ("default_account_changed",
+ MODEST_TYPE_ACCOUNT_MGR,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET(ModestAccountMgrClass, default_account_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
modest_account_mgr_initialized = TRUE;
}
}
ModestAccountMgrPrivate *priv =
MODEST_ACCOUNT_MGR_GET_PRIVATE (obj);
- priv->modest_conf = NULL;
+ priv->modest_conf = NULL;
priv->busy_accounts = NULL;
-
+ priv->change_queue = NULL;
+ priv->timeout = 0;
+
priv->notification_id_accounts = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free);
+
+ /* we maintain hashes for the modest-conf keys we build from account name
+ * + key. many seem to be used often, and generating them showed up high
+ * in oprofile */
+ /* both hashes are hashes to hashes;
+ * account-key => keyname ==> account-key-name
+ */
+ priv->server_account_key_hash = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify)g_hash_table_destroy);
+ priv->account_key_hash = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify)g_hash_table_destroy);
}
static void
g_object_unref (G_OBJECT(priv->modest_conf));
priv->modest_conf = NULL;
}
+
+ if (priv->timeout)
+ g_source_remove (priv->timeout);
+ priv->timeout = 0;
+
+ if (priv->server_account_key_hash) {
+ g_hash_table_destroy (priv->server_account_key_hash);
+ priv->server_account_key_hash = NULL;
+ }
-/* if (priv->timeout) */
-/* g_source_remove (priv->timeout); */
-
-/* if (priv->changed_conf_keys) { */
-/* g_slist_foreach (priv->changed_conf_keys, (GFunc) g_free, NULL); */
-/* g_slist_free (priv->changed_conf_keys); */
-/* } */
+ if (priv->account_key_hash) {
+ g_hash_table_destroy (priv->account_key_hash);
+ priv->account_key_hash = NULL;
+ }
G_OBJECT_CLASS(parent_class)->finalize (obj);
}
gboolean enabled)
{
ModestAccountMgrPrivate *priv;
- gchar *key;
+ const gchar *key;
gboolean ok;
gchar *default_account;
GError *err = NULL;
* we create the account by adding an account 'dir', with the name <name>,
* and in that the 'display_name' string key
*/
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_DISPLAY_NAME, FALSE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_DISPLAY_NAME,
+ FALSE);
if (modest_account_mgr_account_exists (self, key, FALSE)) {
g_printerr ("modest: account already exists\n");
- g_free (key);
return FALSE;
}
ok = modest_conf_set_string (priv->modest_conf, key, name, &err);
- g_free (key);
if (!ok) {
g_printerr ("modest: cannot set display name\n");
if (err) {
}
if (store_account) {
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_STORE_ACCOUNT, FALSE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_STORE_ACCOUNT,
+ FALSE);
ok = modest_conf_set_string (priv->modest_conf, key, store_account, &err);
- g_free (key);
if (!ok) {
g_printerr ("modest: failed to set store account '%s'\n",
- store_account);
+ store_account);
if (err) {
g_printerr ("modest: Error adding store account conf: %s\n", err->message);
g_error_free (err);
}
if (transport_account) {
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
- FALSE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name,
+ MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
+ FALSE);
ok = modest_conf_set_string (priv->modest_conf, key, transport_account, &err);
- g_free (key);
if (!ok) {
g_printerr ("modest: failed to set transport account '%s'\n",
transport_account);
modest_account_mgr_set_bool (self, name,
MODEST_ACCOUNT_LEAVE_ON_SERVER, TRUE, FALSE /* not server account */);
-
modest_account_mgr_set_enabled (self, name, enabled);
/* Notify the observers */
ModestAuthProtocol auth)
{
ModestAccountMgrPrivate *priv;
- gchar *key;
+ const gchar *key;
gboolean ok = TRUE;
GError *err = NULL;
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
/* hostname */
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_HOSTNAME, TRUE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_HOSTNAME, TRUE);
if (modest_conf_key_exists (priv->modest_conf, key, &err)) {
g_printerr ("modest: server account '%s' already exists\n", name);
- g_free (key);
ok = FALSE;
}
if (!ok)
g_error_free (err);
ok = FALSE;
}
- g_free (key);
if (!ok)
goto cleanup;
/* username */
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_USERNAME, TRUE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_USERNAME, TRUE);
ok = modest_conf_set_string (priv->modest_conf, key, null_means_empty (username), &err);
if (err) {
g_printerr ("modest: failed to set %s: %s\n", key, err->message);
g_error_free (err);
ok = FALSE;
}
- g_free (key);
if (!ok)
goto cleanup;
/* password */
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_PASSWORD, TRUE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_PASSWORD, TRUE);
ok = modest_conf_set_string (priv->modest_conf, key, null_means_empty (password), &err);
if (err) {
g_printerr ("modest: failed to set %s: %s\n", key, err->message);
g_error_free (err);
ok = FALSE;
}
- g_free (key);
if (!ok)
goto cleanup;
/* proto */
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_PROTO, TRUE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_PROTO, TRUE);
ok = modest_conf_set_string (priv->modest_conf, key,
modest_protocol_info_get_transport_store_protocol_name(proto),
&err);
g_error_free (err);
ok = FALSE;
}
- g_free (key);
if (!ok)
goto cleanup;
/* portnumber */
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_PORT, TRUE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_PORT, TRUE);
ok = modest_conf_set_int (priv->modest_conf, key, portnumber, &err);
if (err) {
g_printerr ("modest: failed to set %s: %s\n", key, err->message);
g_error_free (err);
ok = FALSE;
}
- g_free (key);
if (!ok)
goto cleanup;
/* auth mechanism */
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_AUTH_MECH, TRUE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_AUTH_MECH, TRUE);
ok = modest_conf_set_string (priv->modest_conf, key,
modest_protocol_info_get_auth_protocol_name (auth),
&err);
g_error_free (err);
ok = FALSE;
}
- g_free (key);
if (!ok)
goto cleanup;
const gchar *uri)
{
ModestAccountMgrPrivate *priv;
- gchar *key;
+ const gchar *key;
gboolean ok;
g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
-
/* proto */
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_PROTO, TRUE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_PROTO, TRUE);
ok = modest_conf_set_string (priv->modest_conf, key,
modest_protocol_info_get_transport_store_protocol_name(proto),
NULL);
- g_free (key);
if (!ok) {
g_printerr ("modest: failed to set proto\n");
}
/* uri */
- key = _modest_account_mgr_get_account_keyname (name, MODEST_ACCOUNT_URI, TRUE);
+ key = _modest_account_mgr_get_account_keyname_cached (priv, name, MODEST_ACCOUNT_URI, TRUE);
ok = modest_conf_set_string (priv->modest_conf, key, uri, NULL);
- g_free (key);
if (!ok) {
g_printerr ("modest: failed to set uri\n");
gboolean server_account)
{
GError *err = NULL;
- gchar *key = NULL;
-
+ gchar *key;
+
key = _modest_account_mgr_get_account_keyname (acc_name, NULL, server_account);
modest_conf_remove_key (conf, key, &err);
- g_free (key);
if (err) {
g_printerr ("modest: error removing key: %s\n", err->message);
g_error_free (err);
}
+ g_free (key);
}
gboolean
* parent modest account already exists.
*/
if (add) {
- gchar* server_account_name = modest_account_mgr_get_string (self, account_name_key, MODEST_ACCOUNT_STORE_ACCOUNT,
- FALSE);
+ gchar* server_account_name = modest_account_mgr_get_string
+ (self, account_name_key, MODEST_ACCOUNT_STORE_ACCOUNT,
+ FALSE);
if (server_account_name) {
if (!modest_account_mgr_account_exists (self, server_account_name, TRUE))
add = FALSE;
}
if (add) {
- gchar* server_account_name = modest_account_mgr_get_string (self, account_name_key, MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
- FALSE);
+ gchar* server_account_name = modest_account_mgr_get_string
+ (self, account_name_key, MODEST_ACCOUNT_TRANSPORT_ACCOUNT,
+ FALSE);
if (server_account_name) {
if (!modest_account_mgr_account_exists (self, server_account_name, TRUE))
add = FALSE;
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
gchar *retval;
GError *err = NULL;
g_return_val_if_fail (name, NULL);
g_return_val_if_fail (key, NULL);
- keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
+ priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
retval = modest_conf_get_string (priv->modest_conf, keyname, &err);
g_error_free (err);
retval = NULL;
}
- g_free (keyname);
return retval;
}
{
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
gint retval;
GError *err = NULL;
g_return_val_if_fail (name, -1);
g_return_val_if_fail (key, -1);
- keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
-
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
+
retval = modest_conf_get_int (priv->modest_conf, keyname, &err);
if (err) {
g_printerr ("modest: error getting int '%s': %s\n", keyname, err->message);
g_error_free (err);
retval = -1;
}
- g_free (keyname);
return retval;
}
{
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
gboolean retval;
GError *err = NULL;
g_return_val_if_fail (account, FALSE);
g_return_val_if_fail (key, FALSE);
- keyname = _modest_account_mgr_get_account_keyname (account, key, server_account);
-
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+ ///keyname = _modest_account_mgr_get_account_keyname (account, key, server_account);
+
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, account, key, server_account);
+
retval = modest_conf_get_bool (priv->modest_conf, keyname, &err);
if (err) {
g_printerr ("modest: error getting bool '%s': %s\n", keyname, err->message);
g_error_free (err);
retval = FALSE;
}
- g_free (keyname);
return retval;
}
{
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
GSList *retval;
GError *err = NULL;
g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), NULL);
g_return_val_if_fail (name, NULL);
g_return_val_if_fail (key, NULL);
-
- keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key,
+ server_account);
+
retval = modest_conf_get_list (priv->modest_conf, keyname, list_type, &err);
if (err) {
g_printerr ("modest: error getting list '%s': %s\n", keyname,
g_error_free (err);
retval = FALSE;
}
- g_free (keyname);
-
return retval;
}
{
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
gboolean retval;
GError *err = NULL;
g_return_val_if_fail (name, FALSE);
g_return_val_if_fail (key, FALSE);
- keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
-
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
+
retval = modest_conf_set_string (priv->modest_conf, keyname, val, &err);
if (err) {
g_printerr ("modest: error setting string '%s': %s\n", keyname, err->message);
g_error_free (err);
retval = FALSE;
}
- g_free (keyname);
return retval;
}
{
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
gboolean retval;
GError *err = NULL;
g_return_val_if_fail (name, FALSE);
g_return_val_if_fail (key, FALSE);
- keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
-
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
+
retval = modest_conf_set_int (priv->modest_conf, keyname, val, &err);
if (err) {
g_printerr ("modest: error setting int '%s': %s\n", keyname, err->message);
g_error_free (err);
retval = FALSE;
}
- g_free (keyname);
return retval;
}
{
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
gboolean retval;
GError *err = NULL;
g_return_val_if_fail (name, FALSE);
g_return_val_if_fail (key, FALSE);
- keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
-
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
-
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
+
retval = modest_conf_set_bool (priv->modest_conf, keyname, val, &err);
if (err) {
g_printerr ("modest: error setting bool '%s': %s\n", keyname, err->message);
g_error_free (err);
retval = FALSE;
}
- g_free (keyname);
+
return retval;
}
gboolean server_account)
{
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
GError *err = NULL;
gboolean retval;
g_return_val_if_fail (key, FALSE);
g_return_val_if_fail (val, FALSE);
- keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
-
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
+
retval = modest_conf_set_list (priv->modest_conf, keyname, val, list_type, &err);
if (err) {
g_printerr ("modest: error setting list '%s': %s\n", keyname, err->message);
g_error_free (err);
retval = FALSE;
}
- g_free (keyname);
return retval;
}
gboolean
-modest_account_mgr_account_exists (ModestAccountMgr * self, const gchar * name,
+modest_account_mgr_account_exists (ModestAccountMgr * self, const gchar* name,
gboolean server_account)
{
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
gboolean retval;
GError *err = NULL;
- g_return_val_if_fail (MODEST_IS_ACCOUNT_MGR(self), FALSE);
+ g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (name, FALSE);
- keyname = _modest_account_mgr_get_account_keyname (name, NULL, server_account);
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, NULL, server_account);
retval = modest_conf_key_exists (priv->modest_conf, keyname, &err);
if (err) {
g_printerr ("modest: error determining existance of '%s': %s\n", keyname,
g_error_free (err);
retval = FALSE;
}
- g_free (keyname);
return retval;
}
{
ModestAccountMgrPrivate *priv;
- gchar *keyname;
+ const gchar *keyname;
gboolean retval;
GError *err = NULL;
g_return_val_if_fail (name, FALSE);
g_return_val_if_fail (key, FALSE);
- keyname = _modest_account_mgr_get_account_keyname (name, key, server_account);
-
priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
+ keyname = _modest_account_mgr_get_account_keyname_cached (priv, name, key, server_account);
+
retval = modest_conf_remove_key (priv->modest_conf, keyname, &err);
if (err) {
g_printerr ("modest: error unsetting'%s': %s\n", keyname,
g_error_free (err);
retval = FALSE;
}
- g_free (keyname);
return retval;
}
+
+
+/* optimization: only with non-alphanum chars, escaping is needed */
+inline static gboolean
+is_alphanum (const gchar* str)
+{
+ const gchar *cursor;
+ for (cursor = str; cursor && *cursor; ++cursor) {
+ const char c = *cursor;
+ /* we cannot trust isalnum(3), because it might consider locales */
+ /* numbers ALPHA alpha */
+ if (!((c>=48 && c<=57)||(c>=65 && c<=90)||(c>=97 && c<=122)))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+
+
/* must be freed by caller */
gchar *
-_modest_account_mgr_get_account_keyname (const gchar *account_name, const gchar * name, gboolean server_account)
+_modest_account_mgr_get_account_keyname (const gchar *account_name, const gchar* name,
+ gboolean server_account)
{
- gchar *retval = NULL;
-
+ gchar *retval = NULL;
gchar *namespace = server_account ? MODEST_SERVER_ACCOUNT_NAMESPACE : MODEST_ACCOUNT_NAMESPACE;
+ gchar *escaped_account_name, *escaped_name;
if (!account_name)
return g_strdup (namespace);
+
+ /* optimization: only escape names when need to be escaped */
+ if (is_alphanum (account_name))
+ escaped_account_name = (gchar*)account_name;
+ else
+ escaped_account_name = modest_conf_key_escape (account_name);
- /* Always escape the conf keys, so that it is acceptable to gconf: */
- gchar *escaped_account_name = account_name ? modest_conf_key_escape (account_name) : NULL;
- gchar *escaped_name = name ? modest_conf_key_escape (name) : NULL;
+ if (is_alphanum (name))
+ escaped_name = (gchar*)name;
+ else
+ escaped_name = modest_conf_key_escape (name);
+ //////////////////////////////////////////////////////////////
if (escaped_account_name && escaped_name)
retval = g_strconcat (namespace, "/", escaped_account_name, "/", escaped_name, NULL);
g_free (retval);
retval = NULL;
}
-
- g_free (escaped_name);
- g_free (escaped_account_name);
+
+ /* g_free is only needed if we actually allocated anything */
+ if (name != escaped_name)
+ g_free (escaped_name);
+ if (account_name != escaped_account_name)
+ g_free (escaped_account_name);
return retval;
}
+
+#if 0
+static void
+f2 (gchar*key, gchar* val, gpointer user_data)
+{
+ g_debug (">>%s:%s", key, val);
+}
+
+
+static void
+f1 (gchar*key, GHashTable* h, gpointer user_data)
+{
+ g_debug (">%s", key);
+ g_hash_table_foreach (h, (GHFunc)f2, NULL);
+}
+#endif
+
+
+static const gchar *
+_modest_account_mgr_get_account_keyname_cached (ModestAccountMgrPrivate *priv, const gchar* account_name,
+ const gchar *name, gboolean is_server)
+{
+ //return _modest_account_mgr_get_account_keyname (account_name, name, is_server);
+
+
+ GHashTable *hash = is_server ? priv->server_account_key_hash : priv->account_key_hash;
+ GHashTable *account_hash;
+ gchar *key = NULL;
+ const gchar *search_name;
+
+ //g_hash_table_foreach (hash, (GHFunc)f1, NULL);
+
+ if (!account_name)
+ return is_server ? MODEST_SERVER_ACCOUNT_NAMESPACE : MODEST_ACCOUNT_NAMESPACE;
+
+ search_name = name ? name : "<dummy>";
+
+ account_hash = g_hash_table_lookup (hash, account_name);
+ if (!account_hash) { /* no hash for this account yet? create it */
+ account_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ key = _modest_account_mgr_get_account_keyname (account_name, name, is_server);
+ g_hash_table_insert (account_hash, g_strdup(search_name), key);
+ g_hash_table_insert (hash, g_strdup(account_name), account_hash);
+ return key;
+ }
+
+ /* we have a hash for this account, but do we have the key? */
+ key = g_hash_table_lookup (account_hash, search_name);
+ if (!key) {
+ key = _modest_account_mgr_get_account_keyname (account_name, name, is_server);
+ g_hash_table_insert (account_hash, g_strdup(search_name), key);
+ }
+
+ return key;
+}
+
+
gboolean
modest_account_mgr_has_accounts (ModestAccountMgr* self, gboolean enabled)
{
void
modest_account_mgr_set_account_busy(ModestAccountMgr* self, const gchar* account_name,
- gboolean busy)
+ gboolean busy)
{
ModestAccountMgrPrivate* priv = MODEST_ACCOUNT_MGR_GET_PRIVATE (self);
if (busy)