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 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 "application.h"
26 : : #include "service.h"
27 : : #include "manager.h"
28 : :
29 : : #undef signals
30 : : #include <libaccounts-glib/ag-manager.h>
31 : : #include <libaccounts-glib/ag-account.h>
32 : :
33 : :
34 : : namespace Accounts {
35 : :
36 : : /*!
37 : : * @class Manager
38 : : * @headerfile manager.h Accounts/Manager
39 : : *
40 : : * @brief Manager of accounts, services and providers.
41 : : *
42 : : * @details The Manager offers ways to create accounts, list accounts, services
43 : : * and providers. It also emits signals when accounts are created and removed.
44 : : */
45 : :
46 : : /*!
47 : : * @fn Manager::accountCreated(Accounts::AccountId id)
48 : : *
49 : : * The signal is emitted when new account is created.
50 : : *
51 : : * @param id Identifier of the Account
52 : : */
53 : :
54 : : /*!
55 : : * @fn Manager::accountRemoved(Accounts::AccountId id)
56 : : *
57 : : * The signal is emitted when existing account is removed.
58 : : *
59 : : * @param id Identifier of the Account
60 : : */
61 : :
62 : : /*!
63 : : * @fn Manager::accountUpdated(Accounts::AccountId id)
64 : : *
65 : : * The signal is emitted when any account property for a particular service is
66 : : * updated.
67 : : *
68 : : * To receive this notification user has to create accounts manager using
69 : : * Manager(const QString &serviceType, QObject *parent) constructor.
70 : : * Update notification is only emitted when manager is created for particular
71 : : * type of service.
72 : : *
73 : : * @param id Identifier of the Account
74 : : */
75 : :
76 : : /*!
77 : : * @fn Manager::enabledEvent(Accounts::AccountId id)
78 : : *
79 : : * If the manager has been created with serviceType, this
80 : : * signal will be emitted when an account (identified by AccountId) has been
81 : : * modified in such a way that the application might be interested to
82 : : * start/stop using it: the "enabled" flag on the account or in some service
83 : : * supported by the account and matching the AgManager::serviceType have
84 : : * changed.
85 : : * @note In practice, this signal might be emitted more often than when
86 : : * strictly needed; applications must call Account::enabledServices() to get
87 : : * the current state.
88 : : *
89 : : * @param id identifier of the Account
90 : : */
91 : :
92 : : class Manager::Private
93 : : {
94 : : Q_DECLARE_PUBLIC(Manager)
95 : :
96 : : public:
97 : 32 : Private():
98 : : q_ptr(0),
99 : 32 : m_manager(0)
100 : : {
101 : 32 : }
102 : :
103 : 32 : ~Private() {
104 : 32 : }
105 : :
106 : : void init(Manager *q, AgManager *manager);
107 : :
108 : : mutable Manager *q_ptr;
109 : : AgManager *m_manager; //real manager
110 : : Error lastError;
111 : :
112 : : static void on_account_created(Manager *self, AgAccountId id);
113 : : static void on_account_deleted(Manager *self, AgAccountId id);
114 : : static void on_account_updated(Manager *self, AgAccountId id);
115 : : static void on_enabled_event(Manager *self, AgAccountId id);
116 : : };
117 : :
118 : : } //namespace Accounts
119 : :
120 : : using namespace Accounts;
121 : :
122 : 32 : void Manager::Private::init(Manager *q, AgManager *manager)
123 : : {
124 : : Q_ASSERT(q_ptr == 0);
125 : : Q_ASSERT(m_manager == 0);
126 : :
127 : 32 : q_ptr = q;
128 : 32 : m_manager = manager;
129 : :
130 [ + - ]: 32 : if (manager) {
131 : : g_signal_connect_swapped
132 : : (manager, "account-created",
133 : 32 : G_CALLBACK(&Private::on_account_created), q);
134 : : g_signal_connect_swapped
135 : : (manager, "account-deleted",
136 : 32 : G_CALLBACK(&Private::on_account_deleted), q);
137 : : g_signal_connect_swapped
138 : : (manager, "account-updated",
139 : 32 : G_CALLBACK(&Private::on_account_updated), q);
140 : : g_signal_connect_swapped
141 : : (manager, "enabled-event",
142 : 32 : G_CALLBACK(&Private::on_enabled_event), q);
143 : : } else {
144 : 0 : qWarning() << Q_FUNC_INFO << "Initializing with NULL AgManager!";
145 : : }
146 : 32 : }
147 : :
148 : 22 : void Manager::Private::on_account_created(Manager *self, AgAccountId id)
149 : : {
150 : 22 : TRACE() << "id =" << id;
151 : :
152 : 22 : emit self->accountCreated(id);
153 : 22 : }
154 : :
155 : 2 : void Manager::Private::on_account_deleted(Manager *self, AgAccountId id)
156 : : {
157 : 2 : TRACE() << "id =" << id;
158 : :
159 : 2 : emit self->accountRemoved(id);
160 : 2 : }
161 : :
162 : 2 : void Manager::Private::on_account_updated(Manager *self, AgAccountId id)
163 : : {
164 : 2 : TRACE() << "id =" << id;
165 : :
166 : 2 : emit self->accountUpdated(id);
167 : 2 : }
168 : :
169 : 3 : void Manager::Private::on_enabled_event(Manager *self, AgAccountId id)
170 : : {
171 : 3 : TRACE() << "id =" << id;
172 : :
173 : 3 : emit self->enabledEvent(id);
174 : 3 : }
175 : :
176 : : /*!
177 : : * Constructor.
178 : : * Users should check for manager->lastError() to check if manager construction
179 : : * was fully succesful.
180 : : */
181 : 29 : Manager::Manager(QObject *parent):
182 : : QObject(parent),
183 : 29 : d(new Private)
184 : : {
185 : 29 : g_type_init();
186 : :
187 : 29 : AgManager *manager = ag_manager_new();
188 : :
189 [ + - ]: 29 : if (manager != 0) {
190 : 29 : d->init(this, manager);
191 : : } else {
192 : 0 : qWarning() << "Manager could not be created. DB is locked";
193 : 0 : d->lastError = Error::DatabaseLocked;
194 : : }
195 : :
196 : 29 : }
197 : :
198 : : /*!
199 : : * Constructs a manager initialized with service type. This constructor
200 : : * should be used when there is an interest for just one service type.
201 : : * Such a manager has influence on some class methods. When listing the
202 : : * accounts and services only the ones supporting the given service type
203 : : * will be returned. Also the creating account with this manager will
204 : : * affect the acccount class method for listing services in same manner.
205 : : * The signal enabledEvent() will be emitted only when manager is created
206 : : * with this constructor.
207 : : * Users should check for manager->lastError() to check if manager construction
208 : : * was fully succesful.
209 : : */
210 : 3 : Manager::Manager(const QString &serviceType, QObject *parent):
211 : : QObject(parent),
212 : 3 : d(new Private)
213 : : {
214 : 3 : g_type_init();
215 : :
216 : : AgManager *manager =
217 : 3 : ag_manager_new_for_service_type(serviceType.toUtf8().constData());
218 : :
219 [ + - ]: 3 : if (manager != 0) {
220 : 3 : d->init(this, manager);
221 : : } else {
222 : 0 : qWarning() << "Manager could not be created, DB is locked";
223 : 0 : d->lastError = Error::DatabaseLocked;
224 : : }
225 : :
226 : 3 : }
227 : :
228 : : /*!
229 : : * Destructor.
230 : : */
231 : 32 : Manager::~Manager()
232 : : {
233 : 32 : TRACE();
234 : :
235 : 32 : g_signal_handlers_disconnect_by_func
236 : 32 : (d->m_manager, (void *)&Private::on_enabled_event, this);
237 : 32 : g_signal_handlers_disconnect_by_func
238 : 32 : (d->m_manager, (void *)&Private::on_account_updated, this);
239 : 32 : g_signal_handlers_disconnect_by_func
240 : 32 : (d->m_manager, (void *)&Private::on_account_deleted, this);
241 : 32 : g_signal_handlers_disconnect_by_func
242 : 32 : (d->m_manager, (void *)&Private::on_account_created, this);
243 : 32 : g_object_unref(d->m_manager);
244 : :
245 [ + - ]: 32 : delete d;
246 : 32 : d = 0;
247 : 64 : }
248 : :
249 : : /*!
250 : : * Loads an account from the database.
251 : : * @param id Id of the account to be retrieved.
252 : : *
253 : : * @return Requested account or NULL if not found. If NULL is returned,
254 : : * call lastError() to find out why.
255 : : */
256 : 2 : Account *Manager::account(const AccountId &id) const
257 : : {
258 : 2 : TRACE() << "get account id: " << id;
259 : :
260 : 2 : GError *error = NULL;
261 : 2 : AgAccount *account = ag_manager_load_account(d->m_manager, id, &error);
262 : :
263 [ + + ]: 2 : if (account != NULL) {
264 : : Q_ASSERT(error == NULL);
265 : 1 : Account *tmp = new Account(account, const_cast<Manager*>(this));
266 : 1 : g_object_unref(account);
267 : : return tmp;
268 : : } else {
269 : : Q_ASSERT(error != NULL);
270 : 1 : d->lastError = Error(error);
271 : 2 : g_error_free(error);
272 : : }
273 : : return NULL;
274 : : }
275 : :
276 : : /*!
277 : : * Lists the accounts which support the requested service.
278 : : *
279 : : * @param serviceType Type of service that returned accounts must support.
280 : : * If not given and the manager is not constructed with service type,
281 : : * all accounts are returned.
282 : : *
283 : : * @return List of account IDs.
284 : : */
285 : 1 : AccountIdList Manager::accountList(const QString &serviceType) const
286 : : {
287 : : GList *list = NULL;
288 : :
289 [ + - ]: 1 : if (serviceType.isEmpty()) {
290 : 1 : list = ag_manager_list(d->m_manager);
291 : : } else {
292 : : list = ag_manager_list_by_service_type(d->m_manager,
293 : 0 : serviceType.toUtf8().constData());
294 : : }
295 : :
296 : : /* convert glist -> AccountIdList */
297 : : AccountIdList idList;
298 : : GList *iter;
299 : :
300 [ + - ][ + + ]: 2 : for (iter = list; iter; iter = g_list_next(iter))
301 : : {
302 : 1 : idList.append((AccountId)GPOINTER_TO_INT(iter->data));
303 : : }
304 : :
305 : 1 : ag_manager_list_free(list);
306 : :
307 : 1 : return idList;
308 : : }
309 : :
310 : : /*!
311 : : * Lists the enabled accounts which support the requested service that also
312 : : * must be enabled.
313 : : *
314 : : * @param serviceType Type of service that returned accounts must support.
315 : : * If not given and the manager is not constructed with service type,
316 : : * all enabled accounts are returned.
317 : : *
318 : : * @return List of account IDs.
319 : : */
320 : 2 : AccountIdList Manager::accountListEnabled(const QString &serviceType) const
321 : : {
322 : : GList *list = NULL;
323 [ - + ]: 2 : if (serviceType.isEmpty()) {
324 : 0 : list = ag_manager_list_enabled(d->m_manager);
325 : : } else {
326 : : list = ag_manager_list_enabled_by_service_type(d->m_manager,
327 : 2 : serviceType.toUtf8().constData());
328 : : }
329 : :
330 : : /* convert glist -> AccountIdList */
331 : : AccountIdList idList;
332 : : GList *iter;
333 : :
334 [ + - ][ + + ]: 3 : for (iter = list; iter; iter = g_list_next(iter))
335 : : {
336 : 1 : idList.append((AccountId)GPOINTER_TO_INT(iter->data));
337 : : }
338 : :
339 : 2 : ag_manager_list_free(list);
340 : :
341 : 2 : return idList;
342 : : }
343 : :
344 : : /*!
345 : : * Creates a new account.
346 : : * @param providerName Name of account provider.
347 : : *
348 : : * @return Created account or NULL if some error occurs.
349 : : */
350 : 27 : Account *Manager::createAccount(const QString &providerName)
351 : : {
352 : 27 : TRACE() << providerName;
353 : :
354 : : AgAccount *account =
355 : : ag_manager_create_account(d->m_manager,
356 : 27 : providerName.toUtf8().constData());
357 : :
358 [ + - ]: 27 : if (account != NULL) {
359 : : /* convert gaccount into qaccount */
360 : 27 : Account *tmp = new Account(account, this);
361 : 27 : g_object_unref(account);
362 : 27 : return tmp;
363 : : }
364 : :
365 : : return NULL;
366 : : }
367 : :
368 : : /*!
369 : : * Gets an object representing a service.
370 : : * @param serviceName Name of service to get.
371 : : *
372 : : * @return The requested service or an invalid service if not found.
373 : : */
374 : 14 : Service Manager::service(const QString &serviceName) const
375 : : {
376 : 14 : TRACE() << serviceName;
377 : : AgService *service =
378 : : ag_manager_get_service(d->m_manager,
379 : 14 : serviceName.toUtf8().constData());
380 : 14 : return Service(service, StealReference);
381 : : }
382 : :
383 : : /*!
384 : : * Gets the service list. If the manager is constructed with given service type
385 : : * only the services which supports the service type will be returned.
386 : : *
387 : : * @param serviceType Type of services to be listed. If not given and
388 : : * the manager is not constructed with service type, all
389 : : * services are listed.
390 : : *
391 : : * @return List of Service objects.
392 : : */
393 : 1 : ServiceList Manager::serviceList(const QString &serviceType) const
394 : : {
395 : 1 : TRACE() << serviceType;
396 : : GList *list;
397 : :
398 [ + - ]: 1 : if (serviceType.isEmpty()) {
399 : 1 : list = ag_manager_list_services(d->m_manager);
400 : : } else {
401 : : list = ag_manager_list_services_by_type(d->m_manager,
402 : 0 : serviceType.toUtf8().constData());
403 : : }
404 : 1 : TRACE() << "found:" << g_list_length(list);
405 : :
406 : : /* convert glist -> ServiceList */
407 : : ServiceList servList;
408 : : GList *iter;
409 : :
410 [ + - ][ + + ]: 3 : for (iter = list; iter; iter = g_list_next(iter))
411 : : {
412 : 2 : AgService *service = (AgService*)iter->data;
413 : 2 : servList.append(Service(service, StealReference));
414 : : }
415 : :
416 : 1 : g_list_free(list);
417 : :
418 : 1 : return servList;
419 : : }
420 : :
421 : : /*!
422 : : * Gets an object representing a provider.
423 : : * @param providerName Name of provider to get.
424 : : *
425 : : * @return Requested provider or NULL if not found.
426 : : */
427 : 1 : Provider Manager::provider(const QString &providerName) const
428 : : {
429 : 1 : TRACE() << providerName;
430 : : AgProvider *provider;
431 : :
432 : : provider = ag_manager_get_provider(d->m_manager,
433 : 1 : providerName.toUtf8().constData());
434 : 1 : return Provider(provider, StealReference);
435 : : }
436 : :
437 : : /*!
438 : : * Gets a provider list.
439 : : *
440 : : * @return List of registered providers.
441 : : */
442 : 1 : ProviderList Manager::providerList() const
443 : : {
444 : : GList *list;
445 : :
446 : 1 : list = ag_manager_list_providers(d->m_manager);
447 : :
448 : : /* convert glist -> ProviderList */
449 : : ProviderList provList;
450 : : GList *iter;
451 : :
452 [ + - ][ + + ]: 2 : for (iter = list; iter; iter = g_list_next(iter))
453 : : {
454 : 1 : AgProvider *provider = (AgProvider*)iter->data;
455 : 1 : provList.append(Provider(provider, StealReference));
456 : : }
457 : :
458 : 1 : g_list_free(list);
459 : :
460 : 1 : return provList;
461 : : }
462 : :
463 : : /*!
464 : : * Gets an object representing a service type.
465 : : * @param name Name of service type to load.
466 : : *
467 : : * @return Requested service type or NULL if not found.
468 : : */
469 : 2 : ServiceType Manager::serviceType(const QString &name) const
470 : : {
471 : : AgServiceType *type;
472 : : type = ag_manager_load_service_type(d->m_manager,
473 : 2 : name.toUtf8().constData());
474 : 2 : return ServiceType(type, StealReference);
475 : : }
476 : :
477 : : /*!
478 : : * Get an object representing an application.
479 : : * @param applicationName Name of the application to load.
480 : : *
481 : : * @return The requested Application, or an invalid Application object if not
482 : : * found.
483 : : */
484 : 1 : Application Manager::application(const QString &applicationName) const
485 : : {
486 : 1 : QByteArray ba = applicationName.toUtf8();
487 : : AgApplication *application =
488 : 1 : ag_manager_get_application(d->m_manager, ba.constData());
489 : 1 : return Application(application);
490 : : }
491 : :
492 : : /*!
493 : : * List the registered applications which support the given service.
494 : : * @param service The service to be supported.
495 : : *
496 : : * @return A list of Application objects.
497 : : */
498 : 2 : ApplicationList Manager::applicationList(const Service &service) const
499 : : {
500 : : ApplicationList ret;
501 : : GList *applications, *list;
502 : :
503 : : applications = ag_manager_list_applications_by_service(d->m_manager,
504 : 2 : service.service());
505 [ + + ]: 4 : for (list = applications; list != NULL; list = list->next) {
506 : 2 : AgApplication *application = (AgApplication *)list->data;
507 : 2 : ret.append(Application(application));
508 : : }
509 : 2 : g_list_free (applications);
510 : 2 : return ret;
511 : : }
512 : :
513 : : /*!
514 : : * Gets the service type if given in manager constructor.
515 : : *
516 : : * @return Service type or NULL if not given.
517 : : */
518 : 0 : QString Manager::serviceType() const
519 : : {
520 : 0 : return UTF8(ag_manager_get_service_type (d->m_manager));
521 : : }
522 : :
523 : : /*!
524 : : * Sets the timeout for database operations.
525 : : * @param timeout The new timeout in milliseconds.
526 : : *
527 : : * This tells the library how long it is allowed to block while waiting
528 : : * for a locked DB to become accessible. Higher values mean a higher
529 : : * chance of successful reads, but also mean that the execution might be
530 : : * blocked for a longer time. The default is 5 seconds.
531 : : */
532 : 0 : void Manager::setTimeout(quint32 timeout)
533 : : {
534 : 0 : ag_manager_set_db_timeout(d->m_manager, timeout);
535 : 0 : }
536 : :
537 : : /*!
538 : : * Gets the database timeout.
539 : : * @return The timeout (in milliseconds) for database operations.
540 : : */
541 : 0 : quint32 Manager::timeout()
542 : : {
543 : 0 : return ag_manager_get_db_timeout(d->m_manager);
544 : : }
545 : :
546 : : /*!
547 : : * Sets whether to abort the application when a database timeout occurs.
548 : : * By default the library does not abort the application.
549 : : */
550 : 0 : void Manager::setAbortOnTimeout(bool abort)
551 : : {
552 : 0 : ag_manager_set_abort_on_db_timeout(d->m_manager, abort);
553 : 0 : }
554 : :
555 : : /*!
556 : : * @return Whether the application will be aborted when a database timeout
557 : : * occurs.
558 : : */
559 : 0 : bool Manager::abortOnTimeout() const
560 : : {
561 : 0 : return ag_manager_get_abort_on_db_timeout(d->m_manager);
562 : : }
563 : :
564 : : /*!
565 : : * Gets the last error. Not all operations set/reset the error; see the
566 : : * individual methods' documentation to see if they set the last error or
567 : : * not. Call this method right after an account operation
568 : : * has failed; if no error occurred, the result of this method are
569 : : * undefined.
570 : : *
571 : : * @return The last error.
572 : : */
573 : 1 : Error Manager::lastError() const
574 : : {
575 : 1 : return d->lastError;
576 : 2 : }
577 : :
|