|
libaccounts-qt
1.1
|
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-2011 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 #include "utils.h" 00027 00028 #undef signals 00029 #include <libaccounts-glib/ag-manager.h> 00030 #include <libaccounts-glib/ag-account.h> 00031 00032 namespace Accounts { 00033 00074 class Account::Private 00075 { 00076 public: 00077 Private() 00078 { 00079 m_account = 0; 00080 } 00081 00082 ~Private() {} 00083 00084 AgAccount *m_account; //real account 00085 QString prefix; 00086 00087 static void on_display_name_changed(Account *self); 00088 static void on_enabled(Account *self, const gchar *service_name, 00089 gboolean enabled); 00090 static void account_store_cb(AgAccount *account, const GError *error, 00091 Account *self); 00092 static void on_deleted(Account *self); 00093 }; 00094 00095 class Watch::Private 00096 { 00097 public: 00098 static void account_notify_cb(AgAccount *account, const gchar *key, 00099 Watch *self); 00100 }; 00101 } //namespace Accounts 00102 00103 00104 using namespace Accounts; 00105 00106 static QChar slash = QChar::fromLatin1('/'); 00107 00117 Watch::Watch(QObject *parent) 00118 : QObject(parent) 00119 { 00120 } 00121 00122 Watch::~Watch() 00123 { 00124 TRACE(); 00125 Account *account = qobject_cast<Account *>(QObject::parent()); 00126 /* The destructor of Account deletes the child Watches before detaching 00127 * them, so here account should always be not NULL */ 00128 Q_ASSERT(account != NULL); 00129 ag_account_remove_watch(account->d->m_account, watch); 00130 } 00131 00132 void Account::Private::on_display_name_changed(Account *self) 00133 { 00134 TRACE(); 00135 const gchar *name = ag_account_get_display_name(self->d->m_account); 00136 00137 emit self->displayNameChanged(UTF8(name)); 00138 } 00139 00140 void Account::Private::on_enabled(Account *self, const gchar *service_name, 00141 gboolean enabled) 00142 { 00143 TRACE(); 00144 00145 emit self->enabledChanged(UTF8(service_name), enabled); 00146 } 00147 00148 void Account::Private::on_deleted(Account *self) 00149 { 00150 TRACE(); 00151 00152 emit self->removed(); 00153 } 00154 00161 Account::Account(AgAccount *account, QObject *parent) 00162 : QObject(parent), d(new Private) 00163 { 00164 TRACE(); 00165 d->m_account = account; 00166 g_object_ref(account); 00167 00168 g_signal_connect_swapped(account, "display-name-changed", 00169 G_CALLBACK(&Private::on_display_name_changed), 00170 this); 00171 g_signal_connect_swapped(account, "enabled", 00172 G_CALLBACK(&Private::on_enabled), this); 00173 g_signal_connect_swapped(account, "deleted", 00174 G_CALLBACK(&Private::on_deleted), this); 00175 } 00176 00180 Account::~Account() 00181 { 00182 TRACE(); 00183 00184 QObjectList list = children(); 00185 for (int i = 0; i < list.count(); i++) 00186 { 00187 QObject *o = list.at(i); 00188 if (qobject_cast<Watch *>(o)) 00189 delete o; 00190 } 00191 00192 g_signal_handlers_disconnect_by_func 00193 (d->m_account, (void *)&Private::on_display_name_changed, this); 00194 g_signal_handlers_disconnect_by_func 00195 (d->m_account, (void *)&Private::on_enabled, this); 00196 g_signal_handlers_disconnect_by_func 00197 (d->m_account, (void *)&Private::on_deleted, this); 00198 g_object_unref(d->m_account); 00199 delete d; 00200 d = 0; 00201 } 00202 00207 AccountId Account::id() const 00208 { 00209 return d->m_account ? d->m_account->id : 0; 00210 } 00211 00215 Manager *Account::manager() const 00216 { 00217 return qobject_cast<Manager *>(QObject::parent()); 00218 } 00219 00223 bool Account::supportsService(const QString &serviceType) const 00224 { 00225 TRACE() << serviceType; 00226 00227 return ag_account_supports_service(d->m_account, 00228 serviceType.toUtf8().constData()); 00229 } 00230 00239 ServiceList Account::services(const QString &serviceType) const 00240 { 00241 TRACE() << serviceType; 00242 00243 GList *list; 00244 if (serviceType.isEmpty()) { 00245 list = ag_account_list_services(d->m_account); 00246 } else { 00247 list = ag_account_list_services_by_type(d->m_account, 00248 serviceType.toUtf8().constData()); 00249 } 00250 00251 /* convert glist -> ServiceList */ 00252 ServiceList servList; 00253 GList *iter; 00254 Manager *mgr = manager(); 00255 Q_ASSERT(mgr != 0); 00256 for (iter = list; iter; iter = g_list_next(iter)) 00257 { 00258 Service *serv = mgr->serviceInstance((AgService*)(iter->data)); 00259 servList.append(serv); 00260 } 00261 00262 ag_service_list_free(list); 00263 00264 return servList; 00265 } 00266 00272 ServiceList Account::enabledServices() const 00273 { 00274 GList *list; 00275 list = ag_account_list_enabled_services(d->m_account); 00276 00277 /* convert glist -> ServiceList */ 00278 ServiceList servList; 00279 GList *iter; 00280 Manager *mgr = manager(); 00281 Q_ASSERT(mgr != 0); 00282 for (iter = list; iter; iter = g_list_next(iter)) 00283 { 00284 Service *serv = mgr->serviceInstance((AgService*)(iter->data)); 00285 servList.append(serv); 00286 } 00287 00288 ag_service_list_free(list); 00289 00290 return servList; 00291 } 00292 00299 bool Account::enabled() const 00300 { 00301 return ag_account_get_enabled(d->m_account); 00302 } 00303 00311 void Account::setEnabled(bool enabled) 00312 { 00313 ag_account_set_enabled(d->m_account, enabled); 00314 } 00315 00321 QString Account::displayName() const 00322 { 00323 return UTF8(ag_account_get_display_name(d->m_account)); 00324 } 00325 00330 void Account::setDisplayName(const QString &displayName) 00331 { 00332 ag_account_set_display_name(d->m_account, 00333 displayName.toUtf8().constData()); 00334 } 00335 00339 QString Account::providerName() const 00340 { 00341 return UTF8(ag_account_get_provider_name(d->m_account)); 00342 } 00343 00349 void Account::selectService(const Service *service) 00350 { 00351 AgService *agService = NULL; 00352 00353 if (service != NULL) 00354 agService = service->service(); 00355 00356 ag_account_select_service(d->m_account, agService); 00357 d->prefix = QString(); 00358 } 00359 00363 Service* Account::selectedService() const 00364 { 00365 AgService *agService = ag_account_get_selected_service(d->m_account); 00366 if (agService == NULL) 00367 return NULL; 00368 00369 Manager *mgr = manager(); 00370 Q_ASSERT(mgr != 0); 00371 Service *service = mgr->serviceInstance(agService); 00372 00373 return service; 00374 } 00375 00381 QStringList Account::allKeys() const 00382 { 00383 QStringList allKeys; 00384 AgAccountSettingIter iter; 00385 const gchar *key; 00386 const GValue *val; 00387 00388 /* iterate the settings */ 00389 QByteArray tmp = d->prefix.toLatin1(); 00390 ag_account_settings_iter_init(d->m_account, &iter, tmp.constData()); 00391 while (ag_account_settings_iter_next(&iter, &key, &val)) 00392 { 00393 allKeys.append(QString(ASCII(key))); 00394 } 00395 return allKeys; 00396 } 00397 00404 void Account::beginGroup(const QString &prefix) 00405 { 00406 d->prefix += prefix + slash; 00407 } 00408 00414 QStringList Account::childGroups() const 00415 { 00416 QStringList groups, all_keys; 00417 00418 all_keys = allKeys(); 00419 foreach (QString key, all_keys) 00420 { 00421 if (key.contains(slash)) { 00422 QString group = key.section(slash, 0, 0); 00423 if (!groups.contains(group)) 00424 groups.append(group); 00425 } 00426 } 00427 return groups; 00428 } 00429 00435 QStringList Account::childKeys() const 00436 { 00437 QStringList keys, all_keys; 00438 00439 all_keys = allKeys(); 00440 foreach (QString key, all_keys) 00441 { 00442 if (!key.contains(slash)) 00443 keys.append(key); 00444 } 00445 return keys; 00446 } 00447 00452 void Account::clear() 00453 { 00454 /* clear() must ignore the group: so, temporarily reset it and call 00455 * remove("") */ 00456 QString saved_prefix = d->prefix; 00457 d->prefix = QString(); 00458 remove(QString()); 00459 d->prefix = saved_prefix; 00460 } 00461 00468 bool Account::contains(const QString &key) const 00469 { 00470 return childKeys().contains(key); 00471 } 00472 00478 void Account::endGroup() 00479 { 00480 d->prefix = d->prefix.section(slash, 0, -3, 00481 QString::SectionIncludeTrailingSep); 00482 if (d->prefix[0] == slash) d->prefix.remove(0, 1); 00483 } 00484 00490 QString Account::group() const 00491 { 00492 if (d->prefix.endsWith(slash)) 00493 return d->prefix.left(d->prefix.size() - 1); 00494 return d->prefix; 00495 } 00496 00500 bool Account::isWritable() const 00501 { 00502 return true; 00503 } 00504 00512 void Account::remove(const QString &key) 00513 { 00514 if (key.isEmpty()) 00515 { 00516 /* delete all keys in the group */ 00517 QStringList keys = allKeys(); 00518 foreach (QString key, keys) 00519 { 00520 if (!key.isEmpty()) 00521 remove(key); 00522 } 00523 } 00524 else 00525 { 00526 QString full_key = d->prefix + key; 00527 QByteArray tmpkey = full_key.toLatin1(); 00528 ag_account_set_value(d->m_account, tmpkey.constData(), NULL); 00529 } 00530 } 00531 00539 void Account::setValue(const QString &key, const QVariant &value) 00540 { 00541 TRACE(); 00542 GValue val= {0, {{0}}}; 00543 00544 if (!variantToGValue(value, &val)) { 00545 return; 00546 } 00547 00548 QString full_key = d->prefix + key; 00549 QByteArray tmpkey = full_key.toLatin1(); 00550 ag_account_set_value(d->m_account, tmpkey.constData(), &val); 00551 g_value_unset(&val); 00552 } 00553 00554 void Account::Private::account_store_cb(AgAccount *account, const GError *err, 00555 Account *self) 00556 { 00557 TRACE() << "Saved accunt ID:" << account->id; 00558 00559 if (err) { 00560 emit self->error(Error(err)); 00561 } else { 00562 emit self->synced(); 00563 } 00564 00565 Q_UNUSED(account); 00566 } 00567 00580 void Account::sync() 00581 { 00582 TRACE(); 00583 00584 ag_account_store(d->m_account, 00585 (AgAccountStoreCb)&Private::account_store_cb, 00586 this); 00587 } 00588 00596 bool Account::syncAndBlock() 00597 { 00598 TRACE(); 00599 00600 GError *error = NULL; 00601 bool ret; 00602 00603 ret = ag_account_store_blocking(d->m_account, &error); 00604 if (error) 00605 { 00606 qWarning() << "Store operation failed: " << error->message; 00607 g_error_free(error); 00608 } 00609 00610 return ret; 00611 } 00612 00626 SettingSource Account::value(const QString &key, QVariant &value) const 00627 { 00628 GType type; 00629 00630 switch (value.type()) 00631 { 00632 case QVariant::String: 00633 type = G_TYPE_STRING; 00634 break; 00635 case QVariant::Int: 00636 type = G_TYPE_INT; 00637 break; 00638 case QVariant::UInt: 00639 type = G_TYPE_UINT; 00640 break; 00641 case QVariant::LongLong: 00642 type = G_TYPE_INT64; 00643 break; 00644 case QVariant::ULongLong: 00645 type = G_TYPE_UINT64; 00646 break; 00647 case QVariant::Bool: 00648 type = G_TYPE_BOOLEAN; 00649 break; 00650 default: 00651 qWarning("Unsupported type %s", value.typeName()); 00652 return NONE; 00653 } 00654 00655 GValue val= {0, {{0}}}; 00656 g_value_init(&val, type); 00657 QString full_key = d->prefix + key; 00658 AgSettingSource source = 00659 ag_account_get_value(d->m_account, 00660 full_key.toLatin1().constData(), &val); 00661 if (source == AG_SETTING_SOURCE_NONE) 00662 return NONE; 00663 00664 value = gvalueToVariant(&val); 00665 g_value_unset(&val); 00666 00667 return (source == AG_SETTING_SOURCE_ACCOUNT) ? ACCOUNT : TEMPLATE; 00668 } 00669 00679 QString Account::valueAsString(const QString &key, 00680 QString default_value, 00681 SettingSource *source) const 00682 { 00683 QVariant var = default_value; 00684 SettingSource src = value(key, var); 00685 if (source) 00686 *source = src; 00687 return var.toString(); 00688 } 00689 00699 int Account::valueAsInt(const QString &key, 00700 int default_value, 00701 SettingSource *source) const 00702 { 00703 QVariant var = default_value; 00704 SettingSource src = value(key, var); 00705 if (source) 00706 *source = src; 00707 return var.toInt(); 00708 } 00709 00719 quint64 Account::valueAsUInt64(const QString &key, 00720 quint64 default_value, 00721 SettingSource *source) const 00722 { 00723 QVariant var = default_value; 00724 SettingSource src = value(key, var); 00725 if (source) 00726 *source = src; 00727 return var.toULongLong(); 00728 } 00729 00739 bool Account::valueAsBool(const QString &key, 00740 bool default_value, 00741 SettingSource *source) const 00742 { 00743 QVariant var = default_value; 00744 SettingSource src = value(key, var); 00745 if (source) 00746 *source = src; 00747 return var.toBool(); 00748 } 00749 00750 void Watch::Private::account_notify_cb(AgAccount *account, const gchar *key, 00751 Watch *watch) 00752 { 00753 emit watch->notify(key); 00754 00755 Q_UNUSED(account); 00756 } 00757 00768 Watch *Account::watchKey(const QString &key) 00769 { 00770 AgAccountWatch ag_watch; 00771 Watch *watch = new Watch(this); 00772 00773 if (!key.isEmpty()) 00774 { 00775 QString full_key = d->prefix + key; 00776 ag_watch = ag_account_watch_key 00777 (d->m_account, full_key.toLatin1().constData(), 00778 (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch); 00779 } 00780 else 00781 { 00782 ag_watch = ag_account_watch_dir 00783 (d->m_account, d->prefix.toLatin1().constData(), 00784 (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch); 00785 } 00786 00787 if (!ag_watch) 00788 { 00789 delete watch; 00790 return NULL; 00791 } 00792 00793 watch->setWatch(ag_watch); 00794 return watch; 00795 } 00796 00801 void Account::remove() 00802 { 00803 TRACE(); 00804 ag_account_delete(d->m_account); 00805 } 00806 00816 void Account::sign(const QString &key, const char *token) 00817 { 00818 ag_account_sign (d->m_account, key.toUtf8().constData(), token); 00819 } 00820 00832 bool Account::verify(const QString &key, const char **token) 00833 { 00834 return ag_account_verify(d->m_account, key.toUtf8().constData(), token); 00835 } 00836 00849 bool Account::verifyWithTokens(const QString &key, QList<const char*> tokens) 00850 { 00851 int tokensCount = tokens.count(); 00852 00853 const char *tmp[tokensCount + 1]; 00854 00855 for (int i = 0; i < tokensCount; ++i) 00856 { 00857 tmp[i] = tokens.at(i); 00858 } 00859 tmp[tokensCount] = NULL; 00860 00861 return ag_account_verify_with_tokens(d->m_account, key.toUtf8().constData(), tmp); 00862 } 00863 00864 qint32 Account::credentialsId() 00865 { 00866 QString key = ACCOUNTS_KEY_CREDENTIALS_ID; 00867 QVariant val(QVariant::Int); 00868 00869 if (value(key, val) != NONE) 00870 return val.toInt(); 00871 00872 qint32 id = 0; 00873 Service *service = selectedService(); 00874 if (service) { 00875 selectService(NULL); 00876 if (value(key, val) != NONE) 00877 id = val.toInt(); 00878 selectService(service); 00879 } 00880 return id; 00881 } 00882 00883 AgAccount *Account::account() 00884 { 00885 return d->m_account; 00886 }