00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "account.h"
00025 #include "manager.h"
00026
00027 #include <libaccounts-glib/ag-manager.h>
00028 #include <libaccounts-glib/ag-account.h>
00029
00030 namespace Accounts {
00031
00032 class Account::Private
00033 {
00034 public:
00035 Private()
00036 {
00037 m_account = 0;
00038 }
00039
00040 ~Private() {}
00041
00042 AgAccount *m_account;
00043 QString prefix;
00044
00045 static void on_display_name_changed(Account *self);
00046 static void on_enabled(Account *self, const gchar *service_name,
00047 gboolean enabled);
00048 static void account_store_cb(AgAccount *account, const GError *error,
00049 Account *self);
00050 static void on_deleted(Account *self);
00051 };
00052
00053 class Watch::Private
00054 {
00055 public:
00056 static void account_notify_cb(AgAccount *account, const gchar *key,
00057 Watch *self);
00058 };
00059 }
00060
00061
00062 using namespace Accounts;
00063
00064 static QChar slash = QChar::fromLatin1('/');
00065
00066 Watch::Watch(QObject *parent)
00067 : QObject(parent)
00068 {
00069 }
00070
00071 Watch::~Watch()
00072 {
00073 TRACE();
00074 Account *account = qobject_cast<Account *>(QObject::parent());
00075
00076
00077 Q_ASSERT(account != NULL);
00078 ag_account_remove_watch(account->d->m_account, watch);
00079 }
00080
00081 void Account::Private::on_display_name_changed(Account *self)
00082 {
00083 TRACE();
00084 const gchar *name = ag_account_get_display_name(self->d->m_account);
00085
00086 emit self->displayNameChanged(UTF8(name));
00087 }
00088
00089 void Account::Private::on_enabled(Account *self, const gchar *service_name,
00090 gboolean enabled)
00091 {
00092 TRACE();
00093
00094 emit self->enabledChanged(UTF8(service_name), enabled);
00095 }
00096
00097 void Account::Private::on_deleted(Account *self)
00098 {
00099 TRACE();
00100
00101 emit self->removed();
00102 }
00103
00104 Account::Account(AgAccount *account, QObject *parent)
00105 : QObject(parent), d(new Private)
00106 {
00107 TRACE();
00108 d->m_account = account;
00109 g_object_ref(account);
00110
00111 g_signal_connect_swapped(account, "display-name-changed",
00112 G_CALLBACK(&Private::on_display_name_changed),
00113 this);
00114 g_signal_connect_swapped(account, "enabled",
00115 G_CALLBACK(&Private::on_enabled), this);
00116 g_signal_connect_swapped(account, "deleted",
00117 G_CALLBACK(&Private::on_deleted), this);
00118 }
00119
00120 Account::~Account()
00121 {
00122 TRACE();
00123
00124 QObjectList list = children();
00125 for (int i = 0; i < list.count(); i++)
00126 {
00127 QObject *o = list.at(i);
00128 if (qobject_cast<Watch *>(o))
00129 delete o;
00130 }
00131
00132 g_signal_handlers_disconnect_by_func
00133 (d->m_account, (void *)&Private::on_display_name_changed, this);
00134 g_signal_handlers_disconnect_by_func
00135 (d->m_account, (void *)&Private::on_enabled, this);
00136 g_signal_handlers_disconnect_by_func
00137 (d->m_account, (void *)&Private::on_deleted, this);
00138 g_object_unref(d->m_account);
00139 delete d;
00140 d = 0;
00141 }
00142
00143 AccountId Account::id() const
00144 {
00145 return d->m_account ? d->m_account->id : 0;
00146 }
00147
00148 Manager *Account::manager() const
00149 {
00150 return qobject_cast<Manager *>(QObject::parent());
00151 }
00152
00153 bool Account::supportsService(const QString &serviceType) const
00154 {
00155 TRACE() << serviceType;
00156
00157 return ag_account_supports_service(d->m_account,
00158 serviceType.toUtf8().constData());
00159 }
00160
00161 ServiceList Account::services(const QString &serviceType) const
00162 {
00163 TRACE() << serviceType;
00164
00165 GList *list;
00166 if (serviceType.isEmpty()) {
00167 list = ag_account_list_services(d->m_account);
00168 } else {
00169 list = ag_account_list_services_by_type(d->m_account,
00170 serviceType.toUtf8().constData());
00171 }
00172
00173
00174 ServiceList servList;
00175 GList *iter;
00176 Manager *mgr = manager();
00177 Q_ASSERT(mgr != 0);
00178 for (iter = list; iter; iter = g_list_next(iter))
00179 {
00180 Service *serv = mgr->serviceInstance((AgService*)(iter->data));
00181 servList.append(serv);
00182 }
00183
00184 ag_service_list_free(list);
00185
00186 return servList;
00187 }
00188
00189 ServiceList Account::enabledServices() const
00190 {
00191 GList *list;
00192 list = ag_account_list_enabled_services(d->m_account);
00193
00194
00195 ServiceList servList;
00196 GList *iter;
00197 Manager *mgr = manager();
00198 Q_ASSERT(mgr != 0);
00199 for (iter = list; iter; iter = g_list_next(iter))
00200 {
00201 Service *serv = mgr->serviceInstance((AgService*)(iter->data));
00202 servList.append(serv);
00203 }
00204
00205 ag_service_list_free(list);
00206
00207 return servList;
00208 }
00209
00210 bool Account::enabled() const
00211 {
00212 return ag_account_get_enabled(d->m_account);
00213 }
00214
00215 void Account::setEnabled(bool enabled)
00216 {
00217 ag_account_set_enabled(d->m_account, enabled);
00218 }
00219
00220 QString Account::displayName() const
00221 {
00222 return UTF8(ag_account_get_display_name(d->m_account));
00223 }
00224
00225 void Account::setDisplayName(const QString &displayName)
00226 {
00227 ag_account_set_display_name(d->m_account,
00228 displayName.toUtf8().constData());
00229 }
00230
00231 QString Account::providerName() const
00232 {
00233 return UTF8(ag_account_get_provider_name(d->m_account));
00234 }
00235
00236 void Account::selectService(const Service *service)
00237 {
00238 AgService *agService = NULL;
00239
00240 if (service != NULL)
00241 agService = service->service();
00242
00243 ag_account_select_service(d->m_account, agService);
00244 d->prefix = QString();
00245 }
00246
00247 Service* Account::selectedService() const
00248 {
00249 AgService *agService = ag_account_get_selected_service(d->m_account);
00250 if (agService == NULL)
00251 return NULL;
00252
00253 Manager *mgr = manager();
00254 Q_ASSERT(mgr != 0);
00255 Service *service = mgr->serviceInstance(agService);
00256
00257 return service;
00258 }
00259
00260 QStringList Account::allKeys() const
00261 {
00262 QStringList allKeys;
00263 AgAccountSettingIter iter;
00264 const gchar *key;
00265 const GValue *val;
00266
00267
00268 QByteArray tmp = d->prefix.toLatin1();
00269 ag_account_settings_iter_init(d->m_account, &iter, tmp.constData());
00270 while (ag_account_settings_iter_next(&iter, &key, &val))
00271 {
00272 allKeys.append(QString(ASCII(key)).mid(d->prefix.size()));
00273 }
00274 return allKeys;
00275 }
00276
00277 void Account::beginGroup(const QString &prefix)
00278 {
00279 d->prefix += prefix + slash;
00280 }
00281
00282 QStringList Account::childGroups() const
00283 {
00284 QStringList groups, all_keys;
00285
00286 all_keys = allKeys();
00287 foreach (QString key, all_keys)
00288 {
00289 if (key.contains(slash)) {
00290 QString group = key.section(slash, 0, 0);
00291 if (!groups.contains(group))
00292 groups.append(group);
00293 }
00294 }
00295 return groups;
00296 }
00297
00298 QStringList Account::childKeys() const
00299 {
00300 QStringList keys, all_keys;
00301
00302 all_keys = allKeys();
00303 foreach (QString key, all_keys)
00304 {
00305 if (!key.contains(slash))
00306 keys.append(key);
00307 }
00308 return keys;
00309 }
00310
00311 void Account::clear()
00312 {
00313
00314
00315 QString saved_prefix = d->prefix;
00316 d->prefix = QString();
00317 remove(QString());
00318 d->prefix = saved_prefix;
00319 }
00320
00321 bool Account::contains(const QString &key) const
00322 {
00323 return childKeys().contains(key);
00324 }
00325
00326 void Account::endGroup()
00327 {
00328 d->prefix = d->prefix.section(slash, 0, -3,
00329 QString::SectionIncludeTrailingSep);
00330 if (d->prefix[0] == slash) d->prefix.remove(0, 1);
00331 }
00332
00333 QString Account::group() const
00334 {
00335 if (d->prefix.endsWith(slash))
00336 return d->prefix.left(d->prefix.size() - 1);
00337 return d->prefix;
00338 }
00339
00340 bool Account::isWritable() const
00341 {
00342 return true;
00343 }
00344
00345 void Account::remove(const QString &key)
00346 {
00347 if (key.isEmpty())
00348 {
00349
00350 QStringList keys = allKeys();
00351 foreach (QString key, keys)
00352 {
00353 if (!key.isEmpty())
00354 remove(key);
00355 }
00356 }
00357 else
00358 {
00359 QString full_key = d->prefix + key;
00360 QByteArray tmpkey = full_key.toLatin1();
00361 ag_account_set_value(d->m_account, tmpkey.constData(), NULL);
00362 }
00363 }
00364
00365 void Account::setValue(const QString &key, const QVariant &value)
00366 {
00367 TRACE();
00368 GValue val= {0, {{0}}};
00369 QByteArray tmpvalue;
00370
00371 switch (value.type())
00372 {
00373 case QVariant::String:
00374 g_value_init(&val, G_TYPE_STRING);
00375 tmpvalue = value.toString().toUtf8();
00376 g_value_set_static_string(&val, tmpvalue.constData());
00377 break;
00378 case QVariant::Int:
00379 g_value_init(&val, G_TYPE_INT);
00380 g_value_set_int(&val, value.toInt());
00381 break;
00382 case QVariant::UInt:
00383 g_value_init(&val, G_TYPE_UINT);
00384 g_value_set_uint(&val, value.toUInt());
00385 break;
00386 case QVariant::LongLong:
00387 g_value_init(&val, G_TYPE_INT64);
00388 g_value_set_int64(&val, value.toLongLong());
00389 break;
00390 case QVariant::ULongLong:
00391 g_value_init(&val, G_TYPE_UINT64);
00392 g_value_set_uint64(&val, value.toULongLong());
00393 break;
00394 case QVariant::Bool:
00395 g_value_init(&val, G_TYPE_BOOLEAN);
00396 g_value_set_boolean(&val, value.toBool());
00397 break;
00398 default:
00399 qWarning("unsupproted datatype %s", value.typeName());
00400 return;
00401 }
00402
00403 QString full_key = d->prefix + key;
00404 QByteArray tmpkey = full_key.toLatin1();
00405 ag_account_set_value(d->m_account, tmpkey.constData(), &val);
00406 g_value_unset(&val);
00407 }
00408
00409 void Account::Private::account_store_cb(AgAccount *account, const GError *err,
00410 Account *self)
00411 {
00412 TRACE() << "Saved accunt ID:" << account->id;
00413
00414 if (err) {
00415 emit self->error((ErrorCode)err->code);
00416 } else {
00417 emit self->synced();
00418 }
00419
00420 Q_UNUSED(account);
00421 }
00422
00423 void Account::sync()
00424 {
00425 TRACE();
00426
00427 ag_account_store(d->m_account,
00428 (AgAccountStoreCb)&Private::account_store_cb,
00429 this);
00430 }
00431
00432 bool Account::syncAndBlock()
00433 {
00434 TRACE();
00435
00436 GError *error = NULL;
00437 bool ret;
00438
00439 ret = ag_account_store_blocking(d->m_account, &error);
00440 if (error)
00441 {
00442 qWarning() << "Store operation failed: " << error->message;
00443 g_error_free(error);
00444 }
00445
00446 return ret;
00447 }
00448
00449 SettingSource Account::value(const QString &key, QVariant &value) const
00450 {
00451 GType type;
00452
00453 switch (value.type())
00454 {
00455 case QVariant::String:
00456 type = G_TYPE_STRING;
00457 break;
00458 case QVariant::Int:
00459 type = G_TYPE_INT;
00460 break;
00461 case QVariant::UInt:
00462 type = G_TYPE_UINT;
00463 break;
00464 case QVariant::LongLong:
00465 type = G_TYPE_INT64;
00466 break;
00467 case QVariant::ULongLong:
00468 type = G_TYPE_UINT64;
00469 break;
00470 case QVariant::Bool:
00471 type = G_TYPE_BOOLEAN;
00472 break;
00473 default:
00474 qWarning("Unsupported type %s", value.typeName());
00475 return NONE;
00476 }
00477
00478 GValue val= {0, {{0}}};
00479 g_value_init(&val, type);
00480 QString full_key = d->prefix + key;
00481 AgSettingSource source =
00482 ag_account_get_value(d->m_account,
00483 full_key.toLatin1().constData(), &val);
00484 if (source == AG_SETTING_SOURCE_NONE)
00485 return NONE;
00486
00487 switch (type)
00488 {
00489 case G_TYPE_STRING:
00490 value = UTF8(g_value_get_string(&val));
00491 break;
00492 case G_TYPE_INT:
00493 value = g_value_get_int(&val);
00494 break;
00495 case G_TYPE_UINT:
00496 value = g_value_get_uint(&val);
00497 break;
00498 case G_TYPE_INT64:
00499 value = qint64(g_value_get_int64(&val));
00500 break;
00501 case G_TYPE_UINT64:
00502 value = quint64(g_value_get_uint64(&val));
00503 break;
00504 case G_TYPE_BOOLEAN:
00505 value = g_value_get_boolean(&val);
00506 break;
00507 default:
00508
00509 Q_ASSERT(false);
00510 break;
00511 }
00512 g_value_unset(&val);
00513
00514 return (source == AG_SETTING_SOURCE_ACCOUNT) ? ACCOUNT : TEMPLATE;
00515 }
00516
00517 QString Account::valueAsString(const QString &key,
00518 QString default_value,
00519 SettingSource *source) const
00520 {
00521 QVariant var = default_value;
00522 SettingSource src = value(key, var);
00523 if (source)
00524 *source = src;
00525 return var.toString();
00526 }
00527
00528 int Account::valueAsInt(const QString &key,
00529 int default_value,
00530 SettingSource *source) const
00531 {
00532 QVariant var = default_value;
00533 SettingSource src = value(key, var);
00534 if (source)
00535 *source = src;
00536 return var.toInt();
00537 }
00538
00539 quint64 Account::valueAsUInt64(const QString &key,
00540 quint64 default_value,
00541 SettingSource *source) const
00542 {
00543 QVariant var = default_value;
00544 SettingSource src = value(key, var);
00545 if (source)
00546 *source = src;
00547 return var.toULongLong();
00548 }
00549
00550 bool Account::valueAsBool(const QString &key,
00551 bool default_value,
00552 SettingSource *source) const
00553 {
00554 QVariant var = default_value;
00555 SettingSource src = value(key, var);
00556 if (source)
00557 *source = src;
00558 return var.toBool();
00559 }
00560
00561 void Watch::Private::account_notify_cb(AgAccount *account, const gchar *key,
00562 Watch *watch)
00563 {
00564 emit watch->notify(key);
00565
00566 Q_UNUSED(account);
00567 }
00568
00569 Watch *Account::watchKey(const QString &key)
00570 {
00571 AgAccountWatch ag_watch;
00572 Watch *watch = new Watch(this);
00573
00574 if (!key.isEmpty())
00575 {
00576 QString full_key = d->prefix + key;
00577 ag_watch = ag_account_watch_key
00578 (d->m_account, full_key.toLatin1().constData(),
00579 (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch);
00580 }
00581 else
00582 {
00583 ag_watch = ag_account_watch_dir
00584 (d->m_account, d->prefix.toLatin1().constData(),
00585 (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch);
00586 }
00587
00588 if (!ag_watch)
00589 {
00590 delete watch;
00591 return NULL;
00592 }
00593
00594 watch->setWatch(ag_watch);
00595 return watch;
00596 }
00597
00598 void Account::remove()
00599 {
00600 TRACE();
00601 ag_account_delete(d->m_account);
00602 }
00603
00604 void Account::sign(const QString &key, const char *token)
00605 {
00606 ag_account_sign (d->m_account, key.toUtf8().constData(), token);
00607 }
00608
00609 bool Account::verify(const QString &key, const char **token)
00610 {
00611 return ag_account_verify(d->m_account, key.toUtf8().constData(), token);
00612 }
00613
00614 bool Account::verifyWithTokens(const QString &key, QList<const char*> tokens)
00615 {
00616 int tokensCount = tokens.count();
00617
00618 const char *tmp[tokensCount + 1];
00619
00620 for (int i = 0; i < tokensCount; ++i)
00621 {
00622 tmp[i] = tokens.at(i);
00623 }
00624 tmp[tokensCount] = NULL;
00625
00626 return ag_account_verify_with_tokens(d->m_account, key.toUtf8().constData(), tmp);
00627 }
00628
00629 qint32 Account::credentialsId()
00630 {
00631 QString key = ACCOUNTS_KEY_CREDENTIALS_ID;
00632 QVariant val(QVariant::Int);
00633
00634 if (value(key, val) != NONE)
00635 return val.toInt();
00636
00637 qint32 id = 0;
00638 Service *service = selectedService();
00639 if (service) {
00640 selectService(NULL);
00641 if (value(key, val) != NONE)
00642 id = val.toInt();
00643 selectService(service);
00644 }
00645 return id;
00646 }