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