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