accounts-qt: Accounts/account.cpp Source File

accounts-qt 1.12

- Main Page
- Related Pages
- Classes
- Files

- File List

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 }
Accounts::Service::isValid
bool isValid() const
Check whether this object represents a Service.
Definition: service.cpp:104
Accounts::Manager
Manager of accounts, services and providers.
Definition: manager.h:51
Accounts::Watch
Monitors an account key or group of keys.
Definition: account.h:70
Accounts::Provider
Representation of an account provider.
Definition: provider.h:48
Accounts::Service
Representation of an account service.
Definition: service.h:48
Accounts::Error
Base object definition for accounts error handling.
Definition: error.h:42
Accounts::Manager::provider
Provider provider(const QString &providerName) const
Gets an object representing a provider.
Definition: manager.cpp:392
Accounts::Manager::lastError
Error lastError() const
Gets the last error.
Definition: manager.cpp:554