Line data Source code
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-2016 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.h>
32 :
33 : namespace Accounts {
34 :
35 : /*!
36 : * @class Watch
37 : * @headerfile account.h Accounts/Account
38 : *
39 : * @brief Monitors an account key or group of keys.
40 : *
41 : * @details A watch is created via the Account::watch method and is a simple
42 : * object which will emit the notify() signal when the value of the key (or
43 : * group) that it is monitoring is changed.
44 : */
45 :
46 : /*!
47 : * @class Account
48 : * @headerfile account.h Accounts/Account
49 : *
50 : * @brief The Account class provides an interface to account settings.
51 : *
52 : * @details The Account class is used to access the account and service settings.
53 : * This class has no constructor, therefore to instantiate one Account object
54 : * one has to either use the Manager::createAccount method (to create a new
55 : * empty account) or Manager::account (to load an existing account).
56 : *
57 : * @attention Do not call setParent() on an account object; the Account class
58 : * assumes that the parent is always the Manager, and changing it will have
59 : * unpredictable results.
60 : *
61 : * Most of the methods in the Account class act on the selected service: for
62 : * example, calling setEnabled(false) on the NULL service (this is the service
63 : * to be used for changing settings globally on the account) will disable the
64 : * account, while the code
65 : * \code
66 : * account->selectService(myService);
67 : * account->setEnabled(false);
68 : * \endcode
69 : * will disable the "myService" service.
70 : *
71 : * All changes made on an account (including deletion) are not stored until
72 : * sync() is called.
73 : */
74 :
75 : class Account::Private
76 : {
77 : public:
78 : Private(Manager *manager, const QString &providerName, Account *account);
79 : Private(Manager *manager, AgAccount *agAccount);
80 :
81 33 : ~Private()
82 33 : {
83 33 : g_cancellable_cancel(m_cancellable);
84 33 : g_object_unref(m_cancellable);
85 33 : m_cancellable = NULL;
86 33 : }
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 :
117 : /*!
118 : * @fn Watch::notify(const char *key)
119 : *
120 : * Emitted when the value of the keys monitored by this watch change.
121 : * @param key The string that was used to create this watch. Note that if
122 : * this watch is monitor multiple keys this param only identifies their
123 : * common prefix, and not the actual key being changed.
124 : */
125 :
126 3 : Watch::Watch(QObject *parent):
127 3 : QObject(parent)
128 : {
129 3 : }
130 :
131 9 : Watch::~Watch()
132 : {
133 3 : 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 3 : Q_ASSERT(account != NULL);
137 3 : ag_account_remove_watch(account->d->m_account, watch);
138 6 : }
139 :
140 30 : Account::Private::Private(Manager *manager, const QString &providerName,
141 30 : Account *account):
142 : m_manager(manager),
143 30 : m_cancellable(g_cancellable_new())
144 : {
145 30 : m_account = ag_manager_create_account(manager->d->m_manager,
146 60 : providerName.toUtf8().constData());
147 30 : init(account);
148 30 : }
149 :
150 3 : Account::Private::Private(Manager *manager, AgAccount *agAccount):
151 : m_manager(manager),
152 : m_account(agAccount),
153 3 : m_cancellable(g_cancellable_new())
154 : {
155 3 : }
156 :
157 33 : void Account::Private::init(Account *account)
158 : {
159 33 : if (m_account == nullptr) return;
160 33 : g_signal_connect_swapped(m_account, "display-name-changed",
161 : G_CALLBACK(&Private::on_display_name_changed),
162 : account);
163 33 : g_signal_connect_swapped(m_account, "enabled",
164 : G_CALLBACK(&Private::on_enabled), account);
165 33 : g_signal_connect_swapped(m_account, "deleted",
166 : G_CALLBACK(&Private::on_deleted), account);
167 : }
168 :
169 2 : void Account::Private::on_display_name_changed(Account *self)
170 : {
171 2 : const gchar *name = ag_account_get_display_name(self->d->m_account);
172 :
173 2 : Q_EMIT self->displayNameChanged(UTF8(name));
174 2 : }
175 :
176 18 : void Account::Private::on_enabled(Account *self, const gchar *service_name,
177 : gboolean enabled)
178 : {
179 18 : Q_EMIT self->enabledChanged(UTF8(service_name), enabled);
180 18 : }
181 :
182 2 : void Account::Private::on_deleted(Account *self)
183 : {
184 2 : Q_EMIT self->removed();
185 2 : }
186 :
187 : /*!
188 : * @fn Account::error(Accounts::Error error)
189 : *
190 : * Emitted when an error occurs.
191 : */
192 :
193 : /*!
194 : * Constructs a new Account. The account exists only in memory and is not
195 : * visible to other applications (or Manager instances) until sync() has been
196 : * called.
197 : * @param manager The account manager. Do not destroy it while the account
198 : * object is in use.
199 : * @param providerName Name of the provider for the account.
200 : * @param parent Parent object.
201 : */
202 30 : Account::Account(Manager *manager, const QString &providerName,
203 30 : QObject *parent):
204 : QObject(parent),
205 30 : d(new Private(manager, providerName, this))
206 : {
207 30 : }
208 :
209 3 : Account::Account(Private *d, QObject *parent):
210 : QObject(parent),
211 3 : d(d)
212 : {
213 3 : d->init(this);
214 3 : }
215 :
216 : /*!
217 : * Constructs an Account object representing an account stored in the database.
218 : * @param manager The account manager. Do not destroy it while the account
219 : * object is in use.
220 : * @param id The numeric identifier of the account.
221 : * @param parent Parent object.
222 : *
223 : * @return A new account object, or 0 if an error occurred.
224 : */
225 5 : Account *Account::fromId(Manager *manager, AccountId id, QObject *parent)
226 : {
227 5 : GError *error = nullptr;
228 5 : AgAccount *account = ag_manager_load_account(manager->d->m_manager, id,
229 5 : &error);
230 5 : if (account == nullptr) {
231 2 : Q_ASSERT(error != nullptr);
232 2 : manager->d->lastError = Error(error);
233 2 : g_error_free(error);
234 2 : return 0;
235 : }
236 3 : Q_ASSERT(error == nullptr);
237 3 : return new Account(new Private(manager, account), parent);
238 : }
239 :
240 : /*!
241 : * Destroys the current account object and free all resources.
242 : */
243 99 : Account::~Account()
244 : {
245 66 : QObjectList list = children();
246 35 : for (int i = 0; i < list.count(); i++)
247 : {
248 2 : QObject *o = list.at(i);
249 2 : if (qobject_cast<Watch *>(o))
250 2 : delete o;
251 : }
252 :
253 33 : g_signal_handlers_disconnect_by_func
254 : (d->m_account, (void *)&Private::on_display_name_changed, this);
255 33 : g_signal_handlers_disconnect_by_func
256 : (d->m_account, (void *)&Private::on_enabled, this);
257 33 : g_signal_handlers_disconnect_by_func
258 : (d->m_account, (void *)&Private::on_deleted, this);
259 33 : g_object_unref(d->m_account);
260 33 : delete d;
261 33 : d = nullptr;
262 66 : }
263 :
264 : /*!
265 : * Returns the AccountId of this account (0 if the account has not yet been
266 : * stored into the database).
267 : */
268 10 : AccountId Account::id() const
269 : {
270 10 : return d->m_account ? d->m_account->id : 0;
271 : }
272 :
273 : /*!
274 : * Returns the Manager.
275 : */
276 6 : Manager *Account::manager() const
277 : {
278 6 : return d->m_manager;
279 : }
280 :
281 : /*!
282 : * Checks whether the account supports the given service.
283 : */
284 2 : bool Account::supportsService(const QString &serviceType) const
285 : {
286 2 : return ag_account_supports_service(d->m_account,
287 4 : serviceType.toUtf8().constData());
288 : }
289 :
290 : /*!
291 : * Returns a list of services supported by this account. If the manager was
292 : * constructed with given service type only the services which supports the
293 : * service type will be returned.
294 : *
295 : * This is currently computed by returning all services having the same
296 : * provider as the account.
297 : */
298 3 : ServiceList Account::services(const QString &serviceType) const
299 : {
300 : GList *list;
301 3 : if (serviceType.isEmpty()) {
302 1 : list = ag_account_list_services(d->m_account);
303 : } else {
304 2 : list = ag_account_list_services_by_type(d->m_account,
305 4 : serviceType.toUtf8().constData());
306 : }
307 :
308 : /* convert glist -> ServiceList */
309 3 : ServiceList servList;
310 : GList *iter;
311 5 : for (iter = list; iter; iter = iter->next)
312 : {
313 2 : AgService *service = (AgService*)iter->data;
314 2 : servList.append(Service(service, StealReference));
315 : }
316 :
317 3 : g_list_free(list);
318 :
319 3 : return servList;
320 : }
321 :
322 : /*!
323 : * Returns a list of enabled services supported by this account. If the manager
324 : * was constructed with given service type only the services which supports the
325 : * service type will be returned.
326 : */
327 2 : ServiceList Account::enabledServices() const
328 : {
329 : GList *list;
330 2 : list = ag_account_list_enabled_services(d->m_account);
331 :
332 : /* convert glist -> ServiceList */
333 2 : ServiceList servList;
334 : GList *iter;
335 3 : for (iter = list; iter; iter = g_list_next(iter))
336 : {
337 1 : AgService *service = (AgService*)iter->data;
338 1 : servList.append(Service(service, StealReference));
339 : }
340 :
341 2 : g_list_free(list);
342 :
343 2 : return servList;
344 : }
345 :
346 : /*!
347 : * Checks whether the account or selected service is enabled.
348 : *
349 : * This method operates on the currently selected service or
350 : * globally, if none selected.
351 : *
352 : * @note this is just a wrapper of isEnabled
353 : * @see isEnabled()
354 : * @deprecated use isEnabled instead
355 : */
356 2 : bool Account::enabled() const
357 : {
358 2 : return isEnabled();
359 : }
360 :
361 : /*!
362 : * Checks whether the account or selected service is enabled.
363 : *
364 : * This method operates on the currently selected service or
365 : * globally, if none selected.
366 : */
367 2 : bool Account::isEnabled() const
368 : {
369 2 : return ag_account_get_enabled(d->m_account);
370 : }
371 :
372 : /*!
373 : * Enables/disables the account or selected service.
374 : * The change will be written only when sync() is called.
375 : *
376 : * This method operates on the currently selected service or
377 : * globally, if none selected.
378 : */
379 15 : void Account::setEnabled(bool enabled)
380 : {
381 15 : ag_account_set_enabled(d->m_account, enabled);
382 15 : }
383 :
384 : /*!
385 : * Returns the display name of the account.
386 : *
387 : * This method operates on the currently selected service.
388 : */
389 3 : QString Account::displayName() const
390 : {
391 3 : return UTF8(ag_account_get_display_name(d->m_account));
392 : }
393 :
394 : /*!
395 : * Changes the display name of the account.
396 : * The change will be written only when sync() is called.
397 : */
398 2 : void Account::setDisplayName(const QString &displayName)
399 : {
400 2 : ag_account_set_display_name(d->m_account,
401 4 : displayName.toUtf8().constData());
402 2 : }
403 :
404 : /*!
405 : * Returns the name of the provider of the account.
406 : */
407 6 : QString Account::providerName() const
408 : {
409 6 : return UTF8(ag_account_get_provider_name(d->m_account));
410 : }
411 :
412 : /*!
413 : * Returns the provider of the account.
414 : */
415 1 : Provider Account::provider() const
416 : {
417 1 : return manager()->provider(providerName());
418 : }
419 :
420 : /*!
421 : * Select the Service for the subsequent operations.
422 : * @param service The Service to select. If this is invalid, the global
423 : * account settings will be selected.
424 : */
425 19 : void Account::selectService(const Service &service)
426 : {
427 19 : AgService *agService = NULL;
428 :
429 19 : if (service.isValid())
430 13 : agService = service.service();
431 :
432 19 : ag_account_select_service(d->m_account, agService);
433 19 : d->prefix = QString();
434 19 : }
435 :
436 : /*!
437 : * @return The currently selected service.
438 : */
439 3 : Service Account::selectedService() const
440 : {
441 3 : AgService *agService = ag_account_get_selected_service(d->m_account);
442 3 : return Service(agService);
443 : }
444 :
445 : /*!
446 : * Returns all keys in the current group.
447 : *
448 : * This method operates on the currently selected service.
449 : */
450 12 : QStringList Account::allKeys() const
451 : {
452 12 : QStringList allKeys;
453 : AgAccountSettingIter iter;
454 : const gchar *key;
455 : GVariant *val;
456 :
457 : /* iterate the settings */
458 24 : QByteArray tmp = d->prefix.toLatin1();
459 12 : ag_account_settings_iter_init(d->m_account, &iter, tmp.constData());
460 130 : while (ag_account_settings_iter_get_next(&iter, &key, &val))
461 : {
462 59 : allKeys.append(QString(ASCII(key)));
463 : }
464 24 : return allKeys;
465 : }
466 :
467 : /*!
468 : * Enters a group. This method never fails.
469 : * @param prefix
470 : *
471 : * This method operates on the currently selected service.
472 : */
473 7 : void Account::beginGroup(const QString &prefix)
474 : {
475 7 : d->prefix += prefix + slash;
476 7 : }
477 :
478 : /*!
479 : * Returns all the groups which are direct children of the current group.
480 : *
481 : * This method operates on the currently selected service.
482 : */
483 2 : QStringList Account::childGroups() const
484 : {
485 4 : QStringList groups, all_keys;
486 :
487 2 : all_keys = allKeys();
488 15 : Q_FOREACH (const QString &key, all_keys)
489 : {
490 13 : if (key.contains(slash)) {
491 16 : QString group = key.section(slash, 0, 0);
492 8 : if (!groups.contains(group))
493 3 : groups.append(group);
494 : }
495 : }
496 4 : return groups;
497 : }
498 :
499 : /*!
500 : * Return all the keys which are direct children of the current group.
501 : *
502 : * This method operates on the currently selected service.
503 : */
504 4 : QStringList Account::childKeys() const
505 : {
506 8 : QStringList keys, all_keys;
507 :
508 4 : all_keys = allKeys();
509 25 : Q_FOREACH (const QString &key, all_keys)
510 : {
511 21 : if (!key.contains(slash))
512 9 : keys.append(key);
513 : }
514 8 : return keys;
515 : }
516 :
517 : /*!
518 : * Removes all the keys in the currently selected service.
519 : * @see remove(const QString &key)
520 : */
521 1 : void Account::clear()
522 : {
523 : /* clear() must ignore the group: so, temporarily reset it and call
524 : * remove("") */
525 2 : QString saved_prefix = d->prefix;
526 1 : d->prefix = QString();
527 1 : remove(QString());
528 1 : d->prefix = saved_prefix;
529 1 : }
530 :
531 : /*!
532 : * Checks whether the given key is in the current group.
533 : * @param key The key name of the settings.
534 : *
535 : * This method operates on the currently selected service.
536 : */
537 2 : bool Account::contains(const QString &key) const
538 : {
539 2 : return childKeys().contains(key);
540 : }
541 :
542 : /*!
543 : * Exits a group.
544 : *
545 : * This method operates on the currently selected service.
546 : */
547 5 : void Account::endGroup()
548 : {
549 15 : d->prefix = d->prefix.section(slash, 0, -3,
550 10 : QString::SectionIncludeTrailingSep);
551 5 : if (d->prefix[0] == slash) d->prefix.remove(0, 1);
552 5 : }
553 :
554 : /*!
555 : * Returns the name of the current group.
556 : *
557 : * This method operates on the currently selected service.
558 : */
559 4 : QString Account::group() const
560 : {
561 4 : if (d->prefix.endsWith(slash))
562 4 : return d->prefix.left(d->prefix.size() - 1);
563 0 : return d->prefix;
564 : }
565 :
566 : /*!
567 : * Checks whether the account is writable. This always returns true.
568 : */
569 1 : bool Account::isWritable() const
570 : {
571 1 : return true;
572 : }
573 :
574 : /*!
575 : * Removes the given key. If the key is the empty string, all keys in the
576 : * current group are removed.
577 : * @param key The key name of the settings.
578 : *
579 : * This method operates on the currently selected service.
580 : */
581 11 : void Account::remove(const QString &key)
582 : {
583 11 : if (key.isEmpty())
584 : {
585 : /* delete all keys in the group */
586 4 : QStringList keys = allKeys();
587 10 : Q_FOREACH (const QString &key, keys)
588 : {
589 8 : if (!key.isEmpty())
590 8 : remove(key);
591 : }
592 : }
593 : else
594 : {
595 18 : QString full_key = d->prefix + key;
596 18 : QByteArray tmpkey = full_key.toLatin1();
597 9 : ag_account_set_variant(d->m_account, tmpkey.constData(), NULL);
598 : }
599 11 : }
600 :
601 : /*!
602 : * Changes the value of an account setting.
603 : * @param key The key name of the setting.
604 : * @param value The new value.
605 : *
606 : * This method operates on the currently selected service.
607 : */
608 34 : void Account::setValue(const QString &key, const QVariant &value)
609 : {
610 34 : GVariant *variant = qVariantToGVariant(value);
611 34 : if (variant == nullptr) {
612 0 : return;
613 : }
614 :
615 68 : QString full_key = d->prefix + key;
616 68 : QByteArray tmpkey = full_key.toLatin1();
617 34 : ag_account_set_variant(d->m_account, tmpkey.constData(), variant);
618 : }
619 :
620 7 : void Account::Private::account_store_cb(AgAccount *account,
621 : GAsyncResult *res,
622 : Account *self)
623 : {
624 7 : GError *error = NULL;
625 7 : ag_account_store_finish(account, res, &error);
626 7 : if (error) {
627 10 : if (error->domain == G_IO_ERROR &&
628 5 : error->code == G_IO_ERROR_CANCELLED) {
629 : } else {
630 0 : Q_EMIT self->error(Error(error));
631 : }
632 5 : g_error_free(error);
633 : } else {
634 2 : Q_EMIT self->synced();
635 : }
636 7 : }
637 :
638 : /*!
639 : * Retrieves the value of an account setting, as a QVariant.
640 : * @param key The key whose value must be retrieved.
641 : * @param defaultValue Value returned if the key is unset.
642 : * @param source Indicates whether the value comes from the account, the
643 : * service template or was unset.
644 : * @see valueAsString
645 : * @see valueAsInt
646 : * @see valueAsBool
647 : *
648 : * @return The value associated to \a key.
649 : *
650 : * This method operates on the currently selected service.
651 : */
652 20 : QVariant Account::value(const QString &key, const QVariant &defaultValue,
653 : SettingSource *source) const
654 : {
655 40 : QString full_key = d->prefix + key;
656 40 : QByteArray ba = full_key.toLatin1();
657 : AgSettingSource settingSource;
658 : GVariant *variant =
659 20 : ag_account_get_variant(d->m_account, ba.constData(), &settingSource);
660 20 : if (source != nullptr) {
661 16 : switch (settingSource) {
662 12 : case AG_SETTING_SOURCE_ACCOUNT: *source = ACCOUNT; break;
663 2 : case AG_SETTING_SOURCE_PROFILE: *source = TEMPLATE; break;
664 2 : default: *source = NONE; break;
665 : }
666 : }
667 :
668 40 : return (variant != nullptr) ? gVariantToQVariant(variant) : defaultValue;
669 : }
670 :
671 : /*!
672 : * Retrieves the value of an account setting, as a QVariant.
673 : * @param key The key whose value must be retrieved.
674 : * @param value A QVariant initialized to the expected type of the value.
675 : * @see valueAsString
676 : * @see valueAsInt
677 : * @see valueAsBool
678 : *
679 : * @return Whether the value comes from the account, the service template
680 : * or was unset.
681 : *
682 : * This method operates on the currently selected service.
683 : * @deprecated Use value(const QString &key, const QVariant &defaultValue,
684 : * SettingSource *source) const instead.
685 : */
686 16 : SettingSource Account::value(const QString &key, QVariant &value) const
687 : {
688 : SettingSource source;
689 32 : QVariant variant = this->value(key, QVariant(), &source);
690 16 : if (variant.isValid()) {
691 14 : if (value.type() != variant.type()) {
692 3 : if (!variant.convert(value.type())) source = NONE;
693 : }
694 14 : value = variant;
695 : }
696 :
697 32 : return source;
698 : }
699 :
700 : /*!
701 : * Gets an account setting as a string.
702 : * @param key The key whose value must be retrieved.
703 : * @param default_value Value returned if the key is unset.
704 : * @param source Indicates whether the value comes from the account, the
705 : * service template or was unset.
706 : *
707 : * This method operates on the currently selected service.
708 : */
709 3 : QString Account::valueAsString(const QString &key,
710 : QString default_value,
711 : SettingSource *source) const
712 : {
713 6 : QVariant var = default_value;
714 3 : SettingSource src = value(key, var);
715 3 : if (source)
716 1 : *source = src;
717 6 : return var.toString();
718 : }
719 :
720 : /*!
721 : * Gets an account setting as an integer.
722 : * @param key The key whose value must be retrieved.
723 : * @param default_value Value returned if the key is unset.
724 : * @param source Indicates whether the value comes from the account, the
725 : * service template or was unset.
726 : *
727 : * This method operates on the currently selected service.
728 : */
729 2 : int Account::valueAsInt(const QString &key,
730 : int default_value,
731 : SettingSource *source) const
732 : {
733 4 : QVariant var = default_value;
734 2 : SettingSource src = value(key, var);
735 2 : if (source)
736 1 : *source = src;
737 4 : return var.toInt();
738 : }
739 :
740 : /*!
741 : * Gets an account setting as an unsigned long integer.
742 : * @param key The key of which value must be retrieved.
743 : * @param default_value Value returned if the key is unset.
744 : * @param source Indicates whether the value comes from the account, the
745 : * service template or was unset.
746 : *
747 : * This method operates on the currently selected service.
748 : */
749 2 : quint64 Account::valueAsUInt64(const QString &key,
750 : quint64 default_value,
751 : SettingSource *source) const
752 : {
753 4 : QVariant var = default_value;
754 2 : SettingSource src = value(key, var);
755 2 : if (source)
756 1 : *source = src;
757 4 : return var.toULongLong();
758 : }
759 :
760 : /*!
761 : * Gets an account setting as a boolean.
762 : * @param key The key whose value must be retrieved.
763 : * @param default_value Value returned if the key is unset.
764 : * @param source Indicates whether the value comes from the account, the
765 : * service template or was unset.
766 : *
767 : * This method operates on the currently selected service.
768 : */
769 2 : bool Account::valueAsBool(const QString &key,
770 : bool default_value,
771 : SettingSource *source) const
772 : {
773 4 : QVariant var = default_value;
774 2 : SettingSource src = value(key, var);
775 2 : if (source)
776 1 : *source = src;
777 4 : return var.toBool();
778 : }
779 :
780 6 : void Watch::Private::account_notify_cb(AgAccount *account, const gchar *key,
781 : Watch *watch)
782 : {
783 6 : Q_EMIT watch->notify(key);
784 :
785 : Q_UNUSED(account);
786 6 : }
787 :
788 : /*!
789 : * Installs a key or group watch.
790 : *
791 : * @param key The key to watch; if %NULL, watches the currently selected
792 : * group.
793 : *
794 : * @return A watch object.
795 : *
796 : * This method operates on the currently selected service.
797 : */
798 3 : Watch *Account::watchKey(const QString &key)
799 : {
800 : AgAccountWatch ag_watch;
801 3 : Watch *watch = new Watch(this);
802 :
803 3 : if (!key.isEmpty())
804 : {
805 4 : QString full_key = d->prefix + key;
806 2 : ag_watch = ag_account_watch_key
807 4 : (d->m_account, full_key.toLatin1().constData(),
808 : (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch);
809 : }
810 : else
811 : {
812 1 : ag_watch = ag_account_watch_dir
813 2 : (d->m_account, d->prefix.toLatin1().constData(),
814 : (AgAccountNotifyCb)&Watch::Private::account_notify_cb, watch);
815 : }
816 :
817 3 : if (!ag_watch)
818 : {
819 0 : delete watch;
820 0 : return NULL;
821 : }
822 :
823 3 : watch->setWatch(ag_watch);
824 3 : return watch;
825 : }
826 :
827 : /*!
828 : * Stores all account settings into the database.
829 : * The signal synced() will be emitted in case of success, or
830 : * error() in case of failure. No assumption must be made about when these
831 : * signals will be emitted: if the database is locked, the signals might
832 : * be emitted asynchronously, whereas if the operation can happen
833 : * synchronously then the signals can be emitted before this method
834 : * returns.
835 : * If for some reason one would want to process the signals asynchronously
836 : * from the event loop, one can use the Qt::QueuedConnection connection
837 : * type as last parameter of the QObject::connect call.
838 : */
839 28 : void Account::sync()
840 : {
841 28 : ag_account_store_async(d->m_account,
842 28 : d->m_cancellable,
843 : (GAsyncReadyCallback)&Private::account_store_cb,
844 : this);
845 28 : }
846 :
847 : /*!
848 : * Blocking version of the sync() method: execution of the current thread
849 : * will block until the operation has completed.
850 : * Usage of this method is discouraged, especially for UI applications.
851 : *
852 : * @return True on success, false otherwise.
853 : */
854 10 : bool Account::syncAndBlock()
855 : {
856 10 : GError *error = NULL;
857 : bool ret;
858 :
859 10 : ret = ag_account_store_blocking(d->m_account, &error);
860 10 : if (error)
861 : {
862 0 : qWarning() << "Store operation failed: " << error->message;
863 0 : g_error_free(error);
864 : }
865 :
866 10 : return ret;
867 : }
868 :
869 : /*!
870 : * Marks the account for removal.
871 : * The account will be deleted only when the sync() method is called.
872 : */
873 2 : void Account::remove()
874 : {
875 2 : ag_account_delete(d->m_account);
876 2 : }
877 :
878 : /*!
879 : * Creates signature of key with given aegis token. The calling application
880 : * must possess (request) the given aegis token. The account needs to be
881 : * stored prior to executing this method.
882 : * @param key The key or the prefix of set of the keys to be signed.
883 : * @param token The aegis token to be used for signing the key.
884 : *
885 : * This method operates on the currently selected service.
886 : */
887 0 : void Account::sign(const QString &key, const char *token)
888 : {
889 0 : ag_account_sign (d->m_account, key.toUtf8().constData(), token);
890 0 : }
891 :
892 : /*!
893 : * Verifies if the key is signed and the signature matches the value
894 : * and provides the aegis token which was used for signing the key.
895 : *
896 : * @param key The name of the key or prefix of the keys to be verified.
897 : * @param token Aegis token to be retrieved.
898 : *
899 : * @return True if the key is signed and the signature matches the value.
900 : *
901 : * This method operates on the currently selected service.
902 : */
903 0 : bool Account::verify(const QString &key, const char **token)
904 : {
905 0 : return ag_account_verify(d->m_account, key.toUtf8().constData(), token);
906 : }
907 :
908 : /*!
909 : * Verifies if the key is signed with any of the aegis tokens and the
910 : * signature is valid.
911 : *
912 : * @param key The name of the key or prefix of the keys to be verified.
913 : * @param tokens Array of aegis tokens.
914 : *
915 : * @return True if the key is signed with any of the aegis tokens and
916 : * the signature is valid.
917 : *
918 : * This method operates on the currently selected service.
919 : */
920 0 : bool Account::verifyWithTokens(const QString &key, QList<const char*> tokens)
921 : {
922 0 : int tokensCount = tokens.count();
923 :
924 0 : const char *tmp[tokensCount + 1];
925 :
926 0 : for (int i = 0; i < tokensCount; ++i)
927 : {
928 0 : tmp[i] = tokens.at(i);
929 : }
930 0 : tmp[tokensCount] = NULL;
931 :
932 0 : return ag_account_verify_with_tokens(d->m_account, key.toUtf8().constData(), tmp);
933 : }
934 :
935 3 : uint Account::credentialsId()
936 : {
937 9 : QString key = ACCOUNTS_KEY_CREDENTIALS_ID;
938 6 : QVariant val(QVariant::Int);
939 :
940 3 : if (value(key, val) != NONE)
941 2 : return val.toUInt();
942 :
943 1 : uint id = 0;
944 2 : Service service = selectedService();
945 1 : if (service.isValid()) {
946 1 : selectService();
947 1 : if (value(key, val) != NONE)
948 1 : id = val.toUInt();
949 1 : selectService(service);
950 : }
951 1 : return id;
952 : }
953 :
954 4 : AgAccount *Account::account()
955 : {
956 4 : return d->m_account;
957 : }
|