accounts-qt
1.13
|
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 * Copyright (C) 2012-2013 Canonical Ltd. 00007 * 00008 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public License 00012 * version 2.1 as published by the Free Software Foundation. 00013 * 00014 * This library is distributed in the hope that it will be useful, but 00015 * WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00022 * 02110-1301 USA 00023 */ 00024 00025 #include "account.h" 00026 #include "manager.h" 00027 #include "manager_p.h" 00028 #include "utils.h" 00029 00030 #include <QPointer> 00031 #include <libaccounts-glib/ag-account.h> 00032 00033 namespace Accounts { 00034 00075 class Account::Private 00076 { 00077 public: 00078 Private(Manager *manager, const QString &providerName, Account *account); 00079 Private(Manager *manager, AgAccount *agAccount); 00080 00081 ~Private() 00082 { 00083 g_cancellable_cancel(m_cancellable); 00084 g_object_unref(m_cancellable); 00085 m_cancellable = NULL; 00086 } 00087 00088 void init(Account *account); 00089 00090 QPointer<Manager> m_manager; 00091 AgAccount *m_account; //real account 00092 GCancellable *m_cancellable; 00093 QString prefix; 00094 00095 static void on_display_name_changed(Account *self); 00096 static void on_enabled(Account *self, const gchar *service_name, 00097 gboolean enabled); 00098 static void account_store_cb(AgAccount *account, 00099 GAsyncResult *res, 00100 Account *self); 00101 static void on_deleted(Account *self); 00102 }; 00103 00104 class Watch::Private 00105 { 00106 public: 00107 static void account_notify_cb(AgAccount *account, const gchar *key, 00108 Watch *self); 00109 }; 00110 } //namespace Accounts 00111 00112 00113 using namespace Accounts; 00114 00115 static QChar slash = QChar::fromLatin1('/'); 00116 00126 Watch::Watch(QObject *parent): 00127 QObject(parent) 00128 { 00129 } 00130 00131 Watch::~Watch() 00132 { 00133 Account *account = qobject_cast<Account *>(QObject::parent()); 00134 /* The destructor of Account deletes the child Watches before detaching 00135 * them, so here account should always be not NULL */ 00136 Q_ASSERT(account != NULL); 00137 ag_account_remove_watch(account->d->m_account, watch); 00138 } 00139 00140 Account::Private::Private(Manager *manager, const QString &providerName, 00141 Account *account): 00142 m_manager(manager), 00143 m_cancellable(g_cancellable_new()) 00144 { 00145 m_account = ag_manager_create_account(manager->d->m_manager, 00146 providerName.toUtf8().constData()); 00147 init(account); 00148 } 00149 00150 Account::Private::Private(Manager *manager, AgAccount *agAccount): 00151 m_manager(manager), 00152 m_account(agAccount), 00153 m_cancellable(g_cancellable_new()) 00154 { 00155 } 00156 00157 void Account::Private::init(Account *account) 00158 { 00159 if (m_account == 0) return; 00160 g_signal_connect_swapped(m_account, "display-name-changed", 00161 G_CALLBACK(&Private::on_display_name_changed), 00162 account); 00163 g_signal_connect_swapped(m_account, "enabled", 00164 G_CALLBACK(&Private::on_enabled), account); 00165 g_signal_connect_swapped(m_account, "deleted", 00166 G_CALLBACK(&Private::on_deleted), account); 00167 } 00168 00169 void Account::Private::on_display_name_changed(Account *self) 00170 { 00171 const gchar *name = ag_account_get_display_name(self->d->m_account); 00172 00173 Q_EMIT self->displayNameChanged(UTF8(name)); 00174 } 00175 00176 void Account::Private::on_enabled(Account *self, const gchar *service_name, 00177 gboolean enabled) 00178 { 00179 Q_EMIT self->enabledChanged(UTF8(service_name), enabled); 00180 } 00181 00182 void Account::Private::on_deleted(Account *self) 00183 { 00184 TRACE(); 00185 00186 Q_EMIT self->removed(); 00187 } 00188 00204 Account::Account(Manager *manager, const QString &providerName, 00205 QObject *parent): 00206 QObject(parent), 00207 d(new Private(manager, providerName, this)) 00208 { 00209 } 00210 00211 Account::Account(Private *d, QObject *parent): 00212 QObject(parent), 00213 d(d) 00214 { 00215 d->init(this); 00216 } 00217 00227 Account *Account::fromId(Manager *manager, AccountId id, QObject *parent) 00228 { 00229 GError *error = 0; 00230 AgAccount *account = ag_manager_load_account(manager->d->m_manager, id, 00231 &error); 00232 if (account == 0) { 00233 Q_ASSERT(error != 0); 00234 manager->d->lastError = Error(error); 00235 g_error_free(error); 00236 return 0; 00237 } 00238 Q_ASSERT(error == 0); 00239 return new Account(new Private(manager, account), parent); 00240 } 00241 00245 Account::~Account() 00246 { 00247 QObjectList list = children(); 00248 for (int i = 0; i < list.count(); i++) 00249 { 00250 QObject *o = list.at(i); 00251 if (qobject_cast<Watch *>(o)) 00252 delete o; 00253 } 00254 00255 g_signal_handlers_disconnect_by_func 00256 (d->m_account, (void *)&Private::on_display_name_changed, this); 00257 g_signal_handlers_disconnect_by_func 00258 (d->m_account, (void *)&Private::on_enabled, this); 00259 g_signal_handlers_disconnect_by_func 00260 (d->m_account, (void *)&Private::on_deleted, this); 00261 g_object_unref(d->m_account); 00262 delete d; 00263 d = 0; 00264 } 00265 00270 AccountId Account::id() const 00271 { 00272 return d->m_account ? d->m_account->id : 0; 00273 } 00274 00278 Manager *Account::manager() const 00279 { 00280 return d->m_manager; 00281 } 00282 00286 bool Account::supportsService(const QString &serviceType) const 00287 { 00288 return ag_account_supports_service(d->m_account, 00289 serviceType.toUtf8().constData()); 00290 } 00291 00300 ServiceList Account::services(const QString &serviceType) const 00301 { 00302 GList *list; 00303 if (serviceType.isEmpty()) { 00304 list = ag_account_list_services(d->m_account); 00305 } else { 00306 list = ag_account_list_services_by_type(d->m_account, 00307 serviceType.toUtf8().constData()); 00308 } 00309 00310 /* convert glist -> ServiceList */ 00311 ServiceList servList; 00312 GList *iter; 00313 for (iter = list; iter; iter = iter->next) 00314 { 00315 AgService *service = (AgService*)iter->data; 00316 servList.append(Service(service, StealReference)); 00317 } 00318 00319 g_list_free(list); 00320 00321 return servList; 00322 } 00323 00329 ServiceList Account::enabledServices() const 00330 { 00331 GList *list; 00332 list = ag_account_list_enabled_services(d->m_account); 00333 00334 /* convert glist -> ServiceList */ 00335 ServiceList servList; 00336 GList *iter; 00337 for (iter = list; iter; iter = g_list_next(iter)) 00338 { 00339 AgService *service = (AgService*)iter->data; 00340 servList.append(Service(service, StealReference)); 00341 } 00342 00343 g_list_free(list); 00344 00345 return servList; 00346 } 00347 00358 bool Account::enabled() const 00359 { 00360 return isEnabled(); 00361 } 00362 00369 bool Account::isEnabled() const 00370 { 00371 return ag_account_get_enabled(d->m_account); 00372 } 00373 00381 void Account::setEnabled(bool enabled) 00382 { 00383 ag_account_set_enabled(d->m_account, enabled); 00384 } 00385 00391 QString Account::displayName() const 00392 { 00393 return UTF8(ag_account_get_display_name(d->m_account)); 00394 } 00395 00400 void Account::setDisplayName(const QString &displayName) 00401 { 00402 ag_account_set_display_name(d->m_account, 00403 displayName.toUtf8().constData()); 00404 } 00405 00409 QString Account::providerName() const 00410 { 00411 return UTF8(ag_account_get_provider_name(d->m_account)); 00412 } 00413 00417 Provider Account::provider() const 00418 { 00419 return manager()->provider(providerName()); 00420 } 00421 00427 void Account::selectService(const Service &service) 00428 { 00429 AgService *agService = NULL; 00430 00431 if (service.isValid()) 00432 agService = service.service(); 00433 00434 ag_account_select_service(d->m_account, agService); 00435 d->prefix = QString(); 00436 } 00437 00441 Service Account::selectedService() const 00442 { 00443 AgService *agService = ag_account_get_selected_service(d->m_account); 00444 return Service(agService); 00445 } 00446 00452 QStringList Account::allKeys() const 00453 { 00454 QStringList allKeys; 00455 AgAccountSettingIter iter; 00456 const gchar *key; 00457 GVariant *val; 00458 00459 /* iterate the settings */ 00460 QByteArray tmp = d->prefix.toLatin1(); 00461 ag_account_settings_iter_init(d->m_account, &iter, tmp.constData()); 00462 while (ag_account_settings_iter_get_next(&iter, &key, &val)) 00463 { 00464 allKeys.append(QString(ASCII(key))); 00465 } 00466 return allKeys; 00467 } 00468 00475 void Account::beginGroup(const QString &prefix) 00476 { 00477 d->prefix += prefix + slash; 00478 } 00479 00485 QStringList Account::childGroups() const 00486 { 00487 QStringList groups, all_keys; 00488 00489 all_keys = allKeys(); 00490 Q_FOREACH (QString key, all_keys) 00491 { 00492 if (key.contains(slash)) { 00493 QString group = key.section(slash, 0, 0); 00494 if (!groups.contains(group)) 00495 groups.append(group); 00496 } 00497 } 00498 return groups; 00499 } 00500 00506 QStringList Account::childKeys() const 00507 { 00508 QStringList keys, all_keys; 00509 00510 all_keys = allKeys(); 00511 Q_FOREACH (QString key, all_keys) 00512 { 00513 if (!key.contains(slash)) 00514 keys.append(key); 00515 } 00516 return keys; 00517 } 00518 00523 void Account::clear() 00524 { 00525 /* clear() must ignore the group: so, temporarily reset it and call 00526 * remove("") */ 00527 QString saved_prefix = d->prefix; 00528 d->prefix = QString(); 00529 remove(QString()); 00530 d->prefix = saved_prefix; 00531 } 00532 00539 bool Account::contains(const QString &key) const 00540 { 00541 return childKeys().contains(key); 00542 } 00543 00549 void Account::endGroup() 00550 { 00551 d->prefix = d->prefix.section(slash, 0, -3, 00552 QString::SectionIncludeTrailingSep); 00553 if (d->prefix[0] == slash) d->prefix.remove(0, 1); 00554 } 00555 00561 QString Account::group() const 00562 { 00563 if (d->prefix.endsWith(slash)) 00564 return d->prefix.left(d->prefix.size() - 1); 00565 return d->prefix; 00566 } 00567 00571 bool Account::isWritable() const 00572 { 00573 return true; 00574 } 00575 00583 void Account::remove(const QString &key) 00584 { 00585 if (key.isEmpty()) 00586 { 00587 /* delete all keys in the group */ 00588 QStringList keys = allKeys(); 00589 Q_FOREACH (QString key, keys) 00590 { 00591 if (!key.isEmpty()) 00592 remove(key); 00593 } 00594 } 00595 else 00596 { 00597 QString full_key = d->prefix + key; 00598 QByteArray tmpkey = full_key.toLatin1(); 00599 ag_account_set_variant(d->m_account, tmpkey.constData(), NULL); 00600 } 00601 } 00602 00610 void Account::setValue(const QString &key, const QVariant &value) 00611 { 00612 GVariant *variant = qVariantToGVariant(value); 00613 if (variant == 0) { 00614 return; 00615 } 00616 00617 QString full_key = d->prefix + key; 00618 QByteArray tmpkey = full_key.toLatin1(); 00619 ag_account_set_variant(d->m_account, tmpkey.constData(), variant); 00620 } 00621 00622 void Account::Private::account_store_cb(AgAccount *account, 00623 GAsyncResult *res, 00624 Account *self) 00625 { 00626 TRACE() << "Saved accunt ID:" << account->id; 00627 00628 GError *error = NULL; 00629 ag_account_store_finish(account, res, &error); 00630 if (error) { 00631 if (error->domain == G_IO_ERROR && 00632 error->code == G_IO_ERROR_CANCELLED) { 00633 TRACE() << "Account destroyed, operation cancelled"; 00634 } else { 00635 Q_EMIT self->error(Error(error)); 00636 } 00637 g_error_free(error); 00638 } else { 00639 Q_EMIT self->synced(); 00640 } 00641 } 00642 00657 QVariant Account::value(const QString &key, const QVariant &defaultValue, 00658 SettingSource *source) const 00659 { 00660 QString full_key = d->prefix + key; 00661 QByteArray ba = full_key.toLatin1(); 00662 AgSettingSource settingSource; 00663 GVariant *variant = 00664 ag_account_get_variant(d->m_account, ba.constData(), &settingSource); 00665 if (source != 0) { 00666 switch (settingSource) { 00667 case AG_SETTING_SOURCE_ACCOUNT: *source = ACCOUNT; break; 00668 case AG_SETTING_SOURCE_PROFILE: *source = TEMPLATE; break; 00669 default: *source = NONE; break; 00670 } 00671 } 00672 00673 return (variant != 0) ? gVariantToQVariant(variant) : defaultValue; 00674 } 00675 00691 SettingSource Account::value(const QString &key, QVariant &value) const 00692 { 00693 SettingSource source; 00694 QVariant variant = this->value(key, QVariant(), &source); 00695 if (variant.isValid()) { 00696 if (value.type() != variant.type()) { 00697 if (!variant.convert(value.type())) source = NONE; 00698 } 00699 value = variant; 00700 } 00701 00702 return source; 00703 } 00704 00714 QString Account::valueAsString(const QString &key, 00715 QString default_value, 00716 SettingSource *source) const 00717 { 00718 QVariant var = default_value; 00719 SettingSource src = value(key, var); 00720 if (source) 00721 *source = src; 00722 return var.toString(); 00723 } 00724 00734 int Account::valueAsInt(const QString &key, 00735 int default_value, 00736 SettingSource *source) const 00737 { 00738 QVariant var = default_value; 00739 SettingSource src = value(key, var); 00740 if (source) 00741 *source = src; 00742 return var.toInt(); 00743 } 00744 00754 quint64 Account::valueAsUInt64(const QString &key, 00755 quint64 default_value, 00756 SettingSource *source) const 00757 { 00758 QVariant var = default_value; 00759 SettingSource src = value(key, var); 00760 if (source) 00761 *source = src; 00762 return var.toULongLong(); 00763 } 00764 00774 bool Account::valueAsBool(const QString &key, 00775 bool default_value, 00776 SettingSource *source) const 00777 { 00778 QVariant var = default_value; 00779 SettingSource src = value(key, var); 00780 if (source) 00781 *source = src; 00782 return var.toBool(); 00783 } 00784 00785 void Watch::Private::account_notify_cb(AgAccount *account, const gchar *key, 00786 Watch *watch) 00787 { 00788 Q_EMIT watch->notify(key); 00789 00790 Q_UNUSED(account); 00791 } 00792 00803 Watch *Account::watchKey(const QString &key) 00804 { 00805 AgAccountWatch ag_watch; 00806 Watch *watch = new Watch(this); 00807 00808 if (!key.isEmpty()) 00809 { 00810 QString full_key = d->prefix + key; 00811 ag_watch = ag_account_watch_key 00812 (d->m_account, full_key.toLatin1().constData(), 00813 (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch); 00814 } 00815 else 00816 { 00817 ag_watch = ag_account_watch_dir 00818 (d->m_account, d->prefix.toLatin1().constData(), 00819 (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch); 00820 } 00821 00822 if (!ag_watch) 00823 { 00824 delete watch; 00825 return NULL; 00826 } 00827 00828 watch->setWatch(ag_watch); 00829 return watch; 00830 } 00831 00844 void Account::sync() 00845 { 00846 ag_account_store_async(d->m_account, 00847 d->m_cancellable, 00848 (GAsyncReadyCallback)&Private::account_store_cb, 00849 this); 00850 } 00851 00859 bool Account::syncAndBlock() 00860 { 00861 GError *error = NULL; 00862 bool ret; 00863 00864 ret = ag_account_store_blocking(d->m_account, &error); 00865 if (error) 00866 { 00867 qWarning() << "Store operation failed: " << error->message; 00868 g_error_free(error); 00869 } 00870 00871 return ret; 00872 } 00873 00878 void Account::remove() 00879 { 00880 ag_account_delete(d->m_account); 00881 } 00882 00892 void Account::sign(const QString &key, const char *token) 00893 { 00894 ag_account_sign (d->m_account, key.toUtf8().constData(), token); 00895 } 00896 00908 bool Account::verify(const QString &key, const char **token) 00909 { 00910 return ag_account_verify(d->m_account, key.toUtf8().constData(), token); 00911 } 00912 00925 bool Account::verifyWithTokens(const QString &key, QList<const char*> tokens) 00926 { 00927 int tokensCount = tokens.count(); 00928 00929 const char *tmp[tokensCount + 1]; 00930 00931 for (int i = 0; i < tokensCount; ++i) 00932 { 00933 tmp[i] = tokens.at(i); 00934 } 00935 tmp[tokensCount] = NULL; 00936 00937 return ag_account_verify_with_tokens(d->m_account, key.toUtf8().constData(), tmp); 00938 } 00939 00940 uint Account::credentialsId() 00941 { 00942 QString key = ACCOUNTS_KEY_CREDENTIALS_ID; 00943 QVariant val(QVariant::Int); 00944 00945 if (value(key, val) != NONE) 00946 return val.toUInt(); 00947 00948 uint id = 0; 00949 Service service = selectedService(); 00950 if (service.isValid()) { 00951 selectService(); 00952 if (value(key, val) != NONE) 00953 id = val.toUInt(); 00954 selectService(service); 00955 } 00956 return id; 00957 } 00958 00959 AgAccount *Account::account() 00960 { 00961 return d->m_account; 00962 }