accounts-qt 0.31
|
00001 /* vi: set et sw=4 ts=4 cino=t0,(0: */ 00002 /* 00003 * This file is part of libaccounts-qt 00004 * 00005 * Copyright (C) 2009-2010 Nokia Corporation. 00006 * 00007 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com> 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public License 00011 * version 2.1 as published by the Free Software Foundation. 00012 * 00013 * This library is distributed in the hope that it will be useful, but 00014 * WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00021 * 02110-1301 USA 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; //real 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 } //namespace Accounts 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 /* The destructor of Account deletes the child Watches before detaching 00076 * them, so here account should always be not NULL */ 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 /* convert glist -> ServiceList */ 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 /* convert glist -> ServiceList */ 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 /* iterate the settings */ 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 /* clear() must ignore the group: so, temporarily reset it and call 00314 * remove("") */ 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 /* delete all keys in the group */ 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 /* This can never be reached */ 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 }