removed QT_NO_CAST_FROM_ASCII for compilation to go thru
[accounts-sso:accounts-qt.git] / Accounts / account-service.cpp
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /*
3  * This file is part of libaccounts-qt
4  *
5  * Copyright (C) 2009-2010 Nokia Corporation.
6  *
7  * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * version 2.1 as published by the Free Software Foundation.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23
24 #include "account-service.h"
25 #include <libaccounts-glib/ag-account.h>
26 #include <libaccounts-glib/ag-account-service.h>
27
28 namespace Accounts
29 {
30     class AccountService::Private
31     {
32     public:
33         Private()
34         {
35             m_manager = NULL;
36             m_account = NULL;
37             m_service = NULL;
38         }
39         ~Private() {}
40
41         static void on_account_service_changed(AccountService *self);
42
43         ServiceList m_serviceList;
44         AgAccountService *m_accountService;
45         Account *m_account;
46         Manager *m_manager;
47         Service *m_service;
48         QString prefix;
49     };
50 }   // namespace accounts
51
52 using namespace Accounts;
53
54 static QChar slash = QChar::fromLatin1('/');
55
56 void AccountService::Private::on_account_service_changed(AccountService *self)
57 {
58     TRACE();
59     emit self->changed();
60 }
61
62 AccountService::AccountService(Account *account, const QString *serviceType, QObject *parent)
63     : QObject(parent), d(new Private)
64 {
65     TRACE() << "Creating AccountService object for service = " << serviceType;
66     foreach(Service *service, d->m_serviceList = account->services()) {
67         if (service->serviceType() == serviceType) {
68             d->m_service = service;
69             break;
70         }
71     }
72     d->prefix = QString();
73     d->m_account = account;
74     d->m_manager = account->manager();
75
76     d->m_accountService = ag_account_service_new(account->account(), d->m_service->service());
77     g_signal_connect_swapped(d->m_accountService, "changed",
78                              G_CALLBACK(&Private::on_account_service_changed),
79                              this);
80 }
81
82 AccountService::~AccountService()
83 {
84     g_signal_handlers_disconnect_by_func
85         (d->m_accountService, (void *)&Private::on_account_service_changed, this);
86
87     delete d;
88 }
89
90 /*!
91  * Returns the Account. Do not delete this object explicitly
92  */
93 Account *AccountService::account() const
94 {
95     AgAccount *account = ag_account_service_get_account(d->m_accountService);
96     AgAccountId account_id = account->id;
97
98     return d->m_manager->account(account_id);
99 }
100
101 /*!
102  * Checks whether the account service is enabled
103  */
104 bool AccountService::enabled() const
105 {
106     return ag_account_service_get_enabled(this->d->m_accountService);
107 }
108
109 /*!
110  * returns all the keys in the current group
111  */
112 QStringList AccountService::allKeys() const
113 {
114     QStringList allKeys;
115     AgAccountSettingIter iter;
116     const gchar *key;
117     const GValue *val;
118
119     /* iterate the settings */
120     QByteArray tmp = d->prefix.toLatin1();
121     ag_account_settings_iter_init(ag_account_service_get_account(d->m_accountService),
122                                   &iter, tmp.constData());
123     while (ag_account_settings_iter_next(&iter, &key, &val))
124     {
125         allKeys.append(QString(ASCII(key)).mid(d->prefix.size()));
126     }
127     return allKeys;
128 }
129
130 /*!
131  * Enters a group. This method never fails.
132  * @param prefix
133  */
134 void AccountService::beginGroup(const QString &prefix)
135 {
136     d->prefix += prefix + slash;
137 }
138
139 /*!
140  * Returns all the groups which are direct children of the current group.
141  */
142 QStringList AccountService::childGroups() const
143 {
144     QStringList groups, all_keys;
145
146     all_keys = allKeys();
147     foreach (QString key, all_keys)
148     {
149         if (key.contains(slash)) {
150             QString group = key.section(slash, 0, 0);
151             if (!groups.contains(group))
152                 groups.append(group);
153         }
154     }
155     return groups;
156 }
157
158 /*!
159  * Return all the keys which are direct children of the current group.
160  */
161 QStringList AccountService::childKeys() const
162 {
163     QStringList keys, all_keys;
164
165     all_keys = allKeys();
166     foreach (QString key, all_keys)
167     {
168         if (!key.contains(slash))
169             keys.append(key);
170     }
171     return keys;
172 }
173
174 /*!
175  * Removes all the keys.
176  * @see remove(const QString &key)
177  */
178 void AccountService::clear()
179 {
180     /* clear() must ignore the group: so, temporarily reset it and call
181      * remove("") */
182     QString saved_prefix = d->prefix;
183     d->prefix = QString();
184     remove(QString());
185     d->prefix = saved_prefix;
186 }
187
188 /*!
189  * Check whether the given key is in the current group.
190  * @param key The key name of the settings.
191  */
192 bool AccountService::contains(const QString &key) const
193 {
194     return childKeys().contains(key);
195 }
196
197 /*!
198  * Exits a group.
199  */
200 void AccountService::endGroup()
201 {
202     d->prefix = d->prefix.section(slash, 0, -3,
203                                   QString::SectionIncludeTrailingSep);
204     if (d->prefix[0] == slash) d->prefix.remove(0, 1);
205 }
206
207 /*!
208  * Returns the name of the current group.
209  */
210 QString AccountService::group() const
211 {
212     if (d->prefix.endsWith(slash))
213         return d->prefix.left(d->prefix.size() - 1);
214     return d->prefix;
215 }
216
217 /*!
218  * Remove the given key. If the key is the empty string, all keys in the
219  * current group are removed.
220  * @param key The key name of the settings.
221  */
222 void AccountService::remove(const QString &key)
223 {
224     if (key.isEmpty())
225     {
226         /* delete all keys in the group */
227         QStringList keys = allKeys();
228         foreach (QString key, keys)
229         {
230             if (!key.isEmpty())
231                 remove(key);
232         }
233     }
234     else
235     {
236         QString full_key = d->prefix + key;
237         QByteArray tmpkey = full_key.toLatin1();
238         ag_account_service_set_value(this->d->m_accountService, tmpkey.constData(), NULL);
239     }
240 }
241
242 /*!
243  * changes the values of an account setting
244  * @param key The name of the setting
245  * @param value The new value of the setting
246  */
247 void AccountService::setValue(const QString &key, const QVariant &value)
248 {
249     TRACE();
250     GValue val= {0, {{0}}};
251     QByteArray tmpvalue;
252
253     switch (value.type())
254     {
255     case QVariant::String:
256         g_value_init(&val, G_TYPE_STRING);
257         tmpvalue = value.toString().toUtf8();
258         g_value_set_static_string(&val, tmpvalue.constData());
259         break;
260     case QVariant::Int:
261         g_value_init(&val, G_TYPE_INT);
262         g_value_set_int(&val, value.toInt());
263         break;
264     case QVariant::UInt:
265         g_value_init(&val, G_TYPE_UINT);
266         g_value_set_uint(&val, value.toUInt());
267         break;
268     case QVariant::LongLong:
269         g_value_init(&val, G_TYPE_INT64);
270         g_value_set_int64(&val, value.toLongLong());
271         break;
272     case QVariant::ULongLong:
273         g_value_init(&val, G_TYPE_UINT64);
274         g_value_set_uint64(&val, value.toULongLong());
275         break;
276     case QVariant::Bool:
277         g_value_init(&val, G_TYPE_BOOLEAN);
278         g_value_set_boolean(&val, value.toBool());
279         break;
280     default:
281         qWarning("unsupproted datatype %s", value.typeName());
282         return;
283     }
284
285     QString full_key = d->prefix + key;
286     QByteArray tmpkey = full_key.toLatin1();
287     ag_account_service_set_value(this->d->m_accountService, tmpkey.constData(), &val);
288     g_value_unset(&val);
289 }
290
291 /*!
292  * retrieves the value of an account setting, as QVariant
293  * @param key The key whose value must be retrieved
294  * @param value A QVariant initialized to the expected type of value
295  * @see valueAsString
296  * @see valueAsInt
297  * @see valueAsBool
298  *
299  * Returns whether the value comes from the account, the service template
300  * or was unset
301  */
302 SettingSource AccountService::value(const QString &key, QVariant &value) const
303 {
304     GType type;
305
306     switch (value.type())
307     {
308     case QVariant::String:
309         type = G_TYPE_STRING;
310         break;
311     case QVariant::Int:
312         type = G_TYPE_INT;
313         break;
314     case QVariant::UInt:
315         type = G_TYPE_UINT;
316         break;
317     case QVariant::LongLong:
318         type = G_TYPE_INT64;
319         break;
320     case QVariant::ULongLong:
321         type = G_TYPE_UINT64;
322         break;
323     case QVariant::Bool:
324         type = G_TYPE_BOOLEAN;
325         break;
326     default:
327         qWarning("Unsupported type %s", value.typeName());
328         return NONE;
329     }
330
331     GValue val= {0, {{0}}};
332     g_value_init(&val, type);
333     QString full_key = d->prefix + key;
334     AgSettingSource source =
335         ag_account_service_get_value(this->d->m_accountService,
336                              full_key.toLatin1().constData(), &val);
337     if (source == AG_SETTING_SOURCE_NONE)
338         return NONE;
339
340     switch (type)
341     {
342     case G_TYPE_STRING:
343         value = UTF8(g_value_get_string(&val));
344         break;
345     case G_TYPE_INT:
346         value = g_value_get_int(&val);
347         break;
348     case G_TYPE_UINT:
349         value = g_value_get_uint(&val);
350         break;
351     case G_TYPE_INT64:
352         value = g_value_get_int64(&val);
353         break;
354     case G_TYPE_UINT64:
355         value = g_value_get_uint64(&val);
356         break;
357     case G_TYPE_BOOLEAN:
358         value = g_value_get_boolean(&val);
359         break;
360     default:
361         /* This can never be reached */
362         Q_ASSERT(false);
363         break;
364     }
365     g_value_unset(&val);
366
367     return (source == AG_SETTING_SOURCE_ACCOUNT) ? ACCOUNT : TEMPLATE;
368 }
369
370 /*!
371  * Gets an account setting as a string.
372  * @param key The key whose value must be retrieved.
373  * @param default_value Value returned if the key is unset.
374  * @param source Indicates whether the value comes from the account, the
375  * service template or was unset.
376  */
377 QString AccountService::valueAsString(const QString &key,
378                       QString default_value,
379                       SettingSource *source) const
380 {
381     QVariant var = default_value;
382     SettingSource src = value(key, var);
383     if (source)
384         *source = src;
385     return var.toString();
386 }
387
388 /*!
389  * Gets an account setting as an integer.
390  * @param key The key whose value must be retrieved.
391  * @param default_value Value returned if the key is unset.
392  * @param source Indicates whether the value comes from the account, the
393  * service template or was unset.
394  */
395 int AccountService::valueAsInt(const QString &key,
396                int default_value,
397                SettingSource *source) const
398 {
399     QVariant var = default_value;
400     SettingSource src = value(key, var);
401     if (source)
402         *source = src;
403     return var.toInt();
404 }
405
406 /*!
407  * Gets an account setting as an usigned long long integer.
408  * @param key The key whose value must be retrieved.
409  * @param default_value Value returned if the key is unset.
410  * @param source Indicates whether the value comes from the account, the
411  * service template or was unset.
412  */
413 quint64 AccountService::valueAsUInt64(const QString &key,
414                       quint64 default_value,
415                       SettingSource *source) const
416 {
417     QVariant var = default_value;
418     SettingSource src = value(key, var);
419     if (source)
420         *source = src;
421     return var.toULongLong();
422 }
423
424 /*!
425  * Gets an account setting as a boolean.
426  * @param key The key whose value must be retrieved.
427  * @param default_value Value returned if the key is unset.
428  * @param source Indicates whether the value comes from the account, the
429  * service template or was unset.
430  */
431 bool AccountService::valueAsBool(const QString &key,
432                  bool default_value,
433                  SettingSource *source) const
434 {
435     QVariant var = default_value;
436     SettingSource src = value(key, var);
437     if (source)
438         *source = src;
439     return var.toBool();
440 }
441
442 /*!
443  * This method should be called only in the context of a handler of the
444  * AccountService::changed() signal, and can be used to retrieve the set of
445  * changes.
446  *
447  * @return a QStringList of the keys which have changed.
448  */
449 QStringList AccountService::changedFields()
450 {
451     QStringList keyList;
452     gchar **keys = ag_account_service_get_changed_fields(this->d->m_accountService);
453     gchar **keyPtr = keys;
454
455     if (keys == NULL)
456         return keyList;
457
458     while (keys != NULL) {
459         keyList.append(QString(ASCII(*keys)));
460         keys++;
461     }
462
463     g_strfreev(keyPtr);
464     return keyList;
465 }
466