accounts-qt  1.11
account.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-2011 Nokia Corporation.
6  * Copyright (C) 2012-2013 Canonical Ltd.
7  *
8  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * version 2.1 as published by the Free Software Foundation.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22  * 02110-1301 USA
23  */
24 
25 #include "account.h"
26 #include "manager.h"
27 #include "manager_p.h"
28 #include "utils.h"
29 
30 #include <QPointer>
31 #include <libaccounts-glib/ag-account.h>
32 
33 namespace Accounts {
34 
75 class Account::Private
76 {
77 public:
78  Private(Manager *manager, const QString &providerName, Account *account);
79  Private(Manager *manager, AgAccount *agAccount);
80 
81  ~Private()
82  {
83  g_cancellable_cancel(m_cancellable);
84  g_object_unref(m_cancellable);
85  m_cancellable = NULL;
86  }
87 
88  void init(Account *account);
89 
90  QPointer<Manager> m_manager;
91  AgAccount *m_account; //real account
92  GCancellable *m_cancellable;
93  QString prefix;
94 
95  static void on_display_name_changed(Account *self);
96  static void on_enabled(Account *self, const gchar *service_name,
97  gboolean enabled);
98  static void account_store_cb(AgAccount *account,
99  GAsyncResult *res,
100  Account *self);
101  static void on_deleted(Account *self);
102 };
103 
104 class Watch::Private
105 {
106 public:
107  static void account_notify_cb(AgAccount *account, const gchar *key,
108  Watch *self);
109 };
110 } //namespace Accounts
111 
112 
113 using namespace Accounts;
114 
115 static QChar slash = QChar::fromLatin1('/');
116 
126 Watch::Watch(QObject *parent):
127  QObject(parent)
128 {
129 }
130 
131 Watch::~Watch()
132 {
133  Account *account = qobject_cast<Account *>(QObject::parent());
134  /* The destructor of Account deletes the child Watches before detaching
135  * them, so here account should always be not NULL */
136  Q_ASSERT(account != NULL);
137  ag_account_remove_watch(account->d->m_account, watch);
138 }
139 
140 Account::Private::Private(Manager *manager, const QString &providerName,
141  Account *account):
142  m_manager(manager),
143  m_cancellable(g_cancellable_new())
144 {
145  m_account = ag_manager_create_account(manager->d->m_manager,
146  providerName.toUtf8().constData());
147  init(account);
148 }
149 
150 Account::Private::Private(Manager *manager, AgAccount *agAccount):
151  m_manager(manager),
152  m_account(agAccount),
153  m_cancellable(g_cancellable_new())
154 {
155 }
156 
157 void Account::Private::init(Account *account)
158 {
159  if (m_account == 0) return;
160  g_signal_connect_swapped(m_account, "display-name-changed",
161  G_CALLBACK(&Private::on_display_name_changed),
162  account);
163  g_signal_connect_swapped(m_account, "enabled",
164  G_CALLBACK(&Private::on_enabled), account);
165  g_signal_connect_swapped(m_account, "deleted",
166  G_CALLBACK(&Private::on_deleted), account);
167 }
168 
169 void Account::Private::on_display_name_changed(Account *self)
170 {
171  const gchar *name = ag_account_get_display_name(self->d->m_account);
172 
173  Q_EMIT self->displayNameChanged(UTF8(name));
174 }
175 
176 void Account::Private::on_enabled(Account *self, const gchar *service_name,
177  gboolean enabled)
178 {
179  Q_EMIT self->enabledChanged(UTF8(service_name), enabled);
180 }
181 
182 void Account::Private::on_deleted(Account *self)
183 {
184  TRACE();
185 
186  Q_EMIT self->removed();
187 }
188 
204 Account::Account(Manager *manager, const QString &providerName,
205  QObject *parent):
206  QObject(parent),
207  d(new Private(manager, providerName, this))
208 {
209 }
210 
211 Account::Account(Private *d, QObject *parent):
212  QObject(parent),
213  d(d)
214 {
215  d->init(this);
216 }
217 
227 Account *Account::fromId(Manager *manager, AccountId id, QObject *parent)
228 {
229  GError *error = 0;
230  AgAccount *account = ag_manager_load_account(manager->d->m_manager, id,
231  &error);
232  if (account == 0) {
233  Q_ASSERT(error != 0);
234  manager->d->lastError = Error(error);
235  g_error_free(error);
236  return 0;
237  }
238  Q_ASSERT(error == 0);
239  return new Account(new Private(manager, account), parent);
240 }
241 
245 Account::~Account()
246 {
247  QObjectList list = children();
248  for (int i = 0; i < list.count(); i++)
249  {
250  QObject *o = list.at(i);
251  if (qobject_cast<Watch *>(o))
252  delete o;
253  }
254 
255  g_signal_handlers_disconnect_by_func
256  (d->m_account, (void *)&Private::on_display_name_changed, this);
257  g_signal_handlers_disconnect_by_func
258  (d->m_account, (void *)&Private::on_enabled, this);
259  g_signal_handlers_disconnect_by_func
260  (d->m_account, (void *)&Private::on_deleted, this);
261  g_object_unref(d->m_account);
262  delete d;
263  d = 0;
264 }
265 
270 AccountId Account::id() const
271 {
272  return d->m_account ? d->m_account->id : 0;
273 }
274 
278 Manager *Account::manager() const
279 {
280  return d->m_manager;
281 }
282 
286 bool Account::supportsService(const QString &serviceType) const
287 {
288  return ag_account_supports_service(d->m_account,
289  serviceType.toUtf8().constData());
290 }
291 
300 ServiceList Account::services(const QString &serviceType) const
301 {
302  GList *list;
303  if (serviceType.isEmpty()) {
304  list = ag_account_list_services(d->m_account);
305  } else {
306  list = ag_account_list_services_by_type(d->m_account,
307  serviceType.toUtf8().constData());
308  }
309 
310  /* convert glist -> ServiceList */
311  ServiceList servList;
312  GList *iter;
313  for (iter = list; iter; iter = iter->next)
314  {
315  AgService *service = (AgService*)iter->data;
316  servList.append(Service(service, StealReference));
317  }
318 
319  g_list_free(list);
320 
321  return servList;
322 }
323 
329 ServiceList Account::enabledServices() const
330 {
331  GList *list;
332  list = ag_account_list_enabled_services(d->m_account);
333 
334  /* convert glist -> ServiceList */
335  ServiceList servList;
336  GList *iter;
337  for (iter = list; iter; iter = g_list_next(iter))
338  {
339  AgService *service = (AgService*)iter->data;
340  servList.append(Service(service, StealReference));
341  }
342 
343  g_list_free(list);
344 
345  return servList;
346 }
347 
358 bool Account::enabled() const
359 {
360  return isEnabled();
361 }
362 
369 bool Account::isEnabled() const
370 {
371  return ag_account_get_enabled(d->m_account);
372 }
373 
381 void Account::setEnabled(bool enabled)
382 {
383  ag_account_set_enabled(d->m_account, enabled);
384 }
385 
391 QString Account::displayName() const
392 {
393  return UTF8(ag_account_get_display_name(d->m_account));
394 }
395 
400 void Account::setDisplayName(const QString &displayName)
401 {
402  ag_account_set_display_name(d->m_account,
403  displayName.toUtf8().constData());
404 }
405 
409 QString Account::providerName() const
410 {
411  return UTF8(ag_account_get_provider_name(d->m_account));
412 }
413 
417 Provider Account::provider() const
418 {
419  return manager()->provider(providerName());
420 }
421 
427 void Account::selectService(const Service &service)
428 {
429  AgService *agService = NULL;
430 
431  if (service.isValid())
432  agService = service.service();
433 
434  ag_account_select_service(d->m_account, agService);
435  d->prefix = QString();
436 }
437 
441 Service Account::selectedService() const
442 {
443  AgService *agService = ag_account_get_selected_service(d->m_account);
444  return Service(agService);
445 }
446 
452 QStringList Account::allKeys() const
453 {
454  QStringList allKeys;
455  AgAccountSettingIter iter;
456  const gchar *key;
457  GVariant *val;
458 
459  /* iterate the settings */
460  QByteArray tmp = d->prefix.toLatin1();
461  ag_account_settings_iter_init(d->m_account, &iter, tmp.constData());
462  while (ag_account_settings_iter_get_next(&iter, &key, &val))
463  {
464  allKeys.append(QString(ASCII(key)));
465  }
466  return allKeys;
467 }
468 
475 void Account::beginGroup(const QString &prefix)
476 {
477  d->prefix += prefix + slash;
478 }
479 
485 QStringList Account::childGroups() const
486 {
487  QStringList groups, all_keys;
488 
489  all_keys = allKeys();
490  Q_FOREACH (QString key, all_keys)
491  {
492  if (key.contains(slash)) {
493  QString group = key.section(slash, 0, 0);
494  if (!groups.contains(group))
495  groups.append(group);
496  }
497  }
498  return groups;
499 }
500 
506 QStringList Account::childKeys() const
507 {
508  QStringList keys, all_keys;
509 
510  all_keys = allKeys();
511  Q_FOREACH (QString key, all_keys)
512  {
513  if (!key.contains(slash))
514  keys.append(key);
515  }
516  return keys;
517 }
518 
523 void Account::clear()
524 {
525  /* clear() must ignore the group: so, temporarily reset it and call
526  * remove("") */
527  QString saved_prefix = d->prefix;
528  d->prefix = QString();
529  remove(QString());
530  d->prefix = saved_prefix;
531 }
532 
539 bool Account::contains(const QString &key) const
540 {
541  return childKeys().contains(key);
542 }
543 
549 void Account::endGroup()
550 {
551  d->prefix = d->prefix.section(slash, 0, -3,
552  QString::SectionIncludeTrailingSep);
553  if (d->prefix[0] == slash) d->prefix.remove(0, 1);
554 }
555 
561 QString Account::group() const
562 {
563  if (d->prefix.endsWith(slash))
564  return d->prefix.left(d->prefix.size() - 1);
565  return d->prefix;
566 }
567 
571 bool Account::isWritable() const
572 {
573  return true;
574 }
575 
583 void Account::remove(const QString &key)
584 {
585  if (key.isEmpty())
586  {
587  /* delete all keys in the group */
588  QStringList keys = allKeys();
589  Q_FOREACH (QString key, keys)
590  {
591  if (!key.isEmpty())
592  remove(key);
593  }
594  }
595  else
596  {
597  QString full_key = d->prefix + key;
598  QByteArray tmpkey = full_key.toLatin1();
599  ag_account_set_variant(d->m_account, tmpkey.constData(), NULL);
600  }
601 }
602 
610 void Account::setValue(const QString &key, const QVariant &value)
611 {
612  GVariant *variant = qVariantToGVariant(value);
613  if (variant == 0) {
614  return;
615  }
616 
617  QString full_key = d->prefix + key;
618  QByteArray tmpkey = full_key.toLatin1();
619  ag_account_set_variant(d->m_account, tmpkey.constData(), variant);
620 }
621 
622 void Account::Private::account_store_cb(AgAccount *account,
623  GAsyncResult *res,
624  Account *self)
625 {
626  TRACE() << "Saved accunt ID:" << account->id;
627 
628  GError *error = NULL;
629  ag_account_store_finish(account, res, &error);
630  if (error) {
631  if (error->domain == G_IO_ERROR &&
632  error->code == G_IO_ERROR_CANCELLED) {
633  TRACE() << "Account destroyed, operation cancelled";
634  } else {
635  Q_EMIT self->error(Error(error));
636  }
637  g_error_free(error);
638  } else {
639  Q_EMIT self->synced();
640  }
641 }
642 
657 QVariant Account::value(const QString &key, const QVariant &defaultValue,
658  SettingSource *source) const
659 {
660  QString full_key = d->prefix + key;
661  QByteArray ba = full_key.toLatin1();
662  AgSettingSource settingSource;
663  GVariant *variant =
664  ag_account_get_variant(d->m_account, ba.constData(), &settingSource);
665  if (source != 0) {
666  switch (settingSource) {
667  case AG_SETTING_SOURCE_ACCOUNT: *source = ACCOUNT; break;
668  case AG_SETTING_SOURCE_PROFILE: *source = TEMPLATE; break;
669  default: *source = NONE; break;
670  }
671  }
672 
673  return (variant != 0) ? gVariantToQVariant(variant) : defaultValue;
674 }
675 
691 SettingSource Account::value(const QString &key, QVariant &value) const
692 {
693  SettingSource source;
694  QVariant variant = this->value(key, QVariant(), &source);
695  if (variant.isValid()) {
696  if (value.type() != variant.type()) {
697  if (!variant.convert(value.type())) source = NONE;
698  }
699  value = variant;
700  }
701 
702  return source;
703 }
704 
714 QString Account::valueAsString(const QString &key,
715  QString default_value,
716  SettingSource *source) const
717 {
718  QVariant var = default_value;
719  SettingSource src = value(key, var);
720  if (source)
721  *source = src;
722  return var.toString();
723 }
724 
734 int Account::valueAsInt(const QString &key,
735  int default_value,
736  SettingSource *source) const
737 {
738  QVariant var = default_value;
739  SettingSource src = value(key, var);
740  if (source)
741  *source = src;
742  return var.toInt();
743 }
744 
754 quint64 Account::valueAsUInt64(const QString &key,
755  quint64 default_value,
756  SettingSource *source) const
757 {
758  QVariant var = default_value;
759  SettingSource src = value(key, var);
760  if (source)
761  *source = src;
762  return var.toULongLong();
763 }
764 
774 bool Account::valueAsBool(const QString &key,
775  bool default_value,
776  SettingSource *source) const
777 {
778  QVariant var = default_value;
779  SettingSource src = value(key, var);
780  if (source)
781  *source = src;
782  return var.toBool();
783 }
784 
785 void Watch::Private::account_notify_cb(AgAccount *account, const gchar *key,
786  Watch *watch)
787 {
788  Q_EMIT watch->notify(key);
789 
790  Q_UNUSED(account);
791 }
792 
803 Watch *Account::watchKey(const QString &key)
804 {
805  AgAccountWatch ag_watch;
806  Watch *watch = new Watch(this);
807 
808  if (!key.isEmpty())
809  {
810  QString full_key = d->prefix + key;
811  ag_watch = ag_account_watch_key
812  (d->m_account, full_key.toLatin1().constData(),
813  (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch);
814  }
815  else
816  {
817  ag_watch = ag_account_watch_dir
818  (d->m_account, d->prefix.toLatin1().constData(),
819  (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch);
820  }
821 
822  if (!ag_watch)
823  {
824  delete watch;
825  return NULL;
826  }
827 
828  watch->setWatch(ag_watch);
829  return watch;
830 }
831 
844 void Account::sync()
845 {
846  ag_account_store_async(d->m_account,
847  d->m_cancellable,
848  (GAsyncReadyCallback)&Private::account_store_cb,
849  this);
850 }
851 
859 bool Account::syncAndBlock()
860 {
861  GError *error = NULL;
862  bool ret;
863 
864  ret = ag_account_store_blocking(d->m_account, &error);
865  if (error)
866  {
867  qWarning() << "Store operation failed: " << error->message;
868  g_error_free(error);
869  }
870 
871  return ret;
872 }
873 
878 void Account::remove()
879 {
880  ag_account_delete(d->m_account);
881 }
882 
892 void Account::sign(const QString &key, const char *token)
893 {
894  ag_account_sign (d->m_account, key.toUtf8().constData(), token);
895 }
896 
908 bool Account::verify(const QString &key, const char **token)
909 {
910  return ag_account_verify(d->m_account, key.toUtf8().constData(), token);
911 }
912 
925 bool Account::verifyWithTokens(const QString &key, QList<const char*> tokens)
926 {
927  int tokensCount = tokens.count();
928 
929  const char *tmp[tokensCount + 1];
930 
931  for (int i = 0; i < tokensCount; ++i)
932  {
933  tmp[i] = tokens.at(i);
934  }
935  tmp[tokensCount] = NULL;
936 
937  return ag_account_verify_with_tokens(d->m_account, key.toUtf8().constData(), tmp);
938 }
939 
940 uint Account::credentialsId()
941 {
942  QString key = ACCOUNTS_KEY_CREDENTIALS_ID;
943  QVariant val(QVariant::Int);
944 
945  if (value(key, val) != NONE)
946  return val.toUInt();
947 
948  uint id = 0;
949  Service service = selectedService();
950  if (service.isValid()) {
951  selectService();
952  if (value(key, val) != NONE)
953  id = val.toUInt();
954  selectService(service);
955  }
956  return id;
957 }
958 
959 AgAccount *Account::account()
960 {
961  return d->m_account;
962 }
QStringList allKeys() const
Return all the keys in the current group.
Manager of accounts, services and providers.
Definition: manager.h:51
Provider provider(const QString &providerName) const
Gets an object representing a provider.
Definition: manager.cpp:367
Monitors an account key or group of keys.
Definition: account.h:70
bool isEnabled() const
Check whether the account service is enabled.
Service service() const
Return the Service.
QStringList childKeys() const
Return all the keys which are direct children of the current group.
Representation of an account provider.
Definition: provider.h:48
QString group() const
Return the name of the current group.
bool enabled() const
Check whether the account service is enabled.
Representation of an account service.
Definition: service.h:48
Error lastError() const
Gets the last error.
Definition: manager.cpp:512
QVariant value(const QString &key, const QVariant &defaultValue, SettingSource *source=0) const
Retrieves the value of an account setting, as a QVariant.
bool isValid() const
Check whether this object represents a Service.
Definition: service.cpp:104
Base object definition for accounts error handling.
Definition: error.h:42
Account * account() const
Return the Account.