~ubuntu-branches/ubuntu/quantal/evolution-data-server/quantal

« back to all changes in this revision

Viewing changes to libedataserver/e-source-registry.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2012-07-03 22:41:23 UTC
  • mfrom: (1.1.100)
  • Revision ID: package-import@ubuntu.com-20120703224123-90dydkyfyvff8s0s
Tags: 3.5.3.1-0ubuntu1
* New upstream release 3.5.3.1.
* debian/control:
  - Drop libgconf2-dev from Build-Depends.
  - Bump versions for glib, goa, and libsoup in Build-Depends.
  - Add a Build-Depends on libgcr-3-dev (>= 3.4)
  - Rename packages following upstream SONAME changes.
  - Add Depends on libgnome-keyring-dev to libedataserver1.2-dev.
* debian/rules:
  - Update mkshlibs arguments for libcamel-1.2-38 instead of -33; as it was
    renamed in control due to the soname change.
  - Strip out -Bsymbolic-functions from LDFLAGS.
* Renamed install files in debian/:
  - libcamel-1.2-33.install => libcamel-1.2-38.install
  - libebackend-1.2-2.install => libebackend-1.2-4.install
  - libebook-1.2-13.install => libebook-1.2-17.install
  - libecal-1.2-11.install => libecal-1.2-15.install
  - libedata-book-1.2-13.install => libedata-book-1.2-15.install
  - libedata-cal-1.2-15.install => libedata-cal-1.2-18.install
  - libedataserver-1.2-16.install => libedataserver-1.2-17.install
  - libedataserverui-3.0-1.install => libedataserverui-3.0-4.install
* debian/patches/google_tests_fpic.patch: build tests with -fPIC; otherwise
  build fails.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * e-source-registry.c
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) version 3.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with the program; if not, see <http://www.gnu.org/licenses/>
 
16
 *
 
17
 */
 
18
 
 
19
/**
 
20
 * SECTION: e-source-registry
 
21
 * @include: libedataserver/libedataserver.h
 
22
 * @short_description: A central repository for data sources
 
23
 *
 
24
 * The #ESourceRegistry is a global singleton store for all #ESource
 
25
 * instances.  It uses file monitors to react to key file creation and
 
26
 * deletion events, either constructing an #ESource instance from the
 
27
 * newly created key file, or removing from the logical #ESource
 
28
 * hierarchy the instance corresponding to the deleted key file.
 
29
 *
 
30
 * The #ESourceRegistry can be queried for individual #ESource instances
 
31
 * by their unique identifier string or key file path, for collections of
 
32
 * #ESource instances having a particular extension, or for all available
 
33
 * #ESource instances.
 
34
 *
 
35
 * The #ESourceRegistry API also provides a front-end for the
 
36
 * "org.gnome.Evolution.DefaultSources" #GSettings schema which tracks
 
37
 * which #ESource instances are designated to be the user's default address
 
38
 * book, calendar, memo list and task list for desktop integration.
 
39
 **/
 
40
 
 
41
#include "e-source-registry.h"
 
42
 
 
43
#include <config.h>
 
44
#include <glib/gstdio.h>
 
45
#include <glib/gi18n-lib.h>
 
46
 
 
47
/* XXX Yeah, yeah... */
 
48
#define GCR_API_SUBJECT_TO_CHANGE
 
49
 
 
50
#include <gcr/gcr-base.h>
 
51
 
 
52
/* Private D-Bus classes. */
 
53
#include <e-dbus-source.h>
 
54
#include <e-dbus-source-manager.h>
 
55
 
 
56
#include <libedataserver/e-marshal.h>
 
57
#include <libedataserver/e-data-server-util.h>
 
58
#include <libedataserver/e-source-collection.h>
 
59
 
 
60
/* Needed for the defaults API. */
 
61
#include <libedataserver/e-source-address-book.h>
 
62
#include <libedataserver/e-source-calendar.h>
 
63
#include <libedataserver/e-source-mail-account.h>
 
64
#include <libedataserver/e-source-mail-identity.h>
 
65
 
 
66
#include "e-dbus-authenticator.h"
 
67
 
 
68
#define E_SOURCE_REGISTRY_GET_PRIVATE(obj) \
 
69
        (G_TYPE_INSTANCE_GET_PRIVATE \
 
70
        ((obj), E_TYPE_SOURCE_REGISTRY, ESourceRegistryPrivate))
 
71
 
 
72
#define DBUS_OBJECT_PATH "/org/gnome/evolution/dataserver/SourceManager"
 
73
#define GSETTINGS_SCHEMA "org.gnome.Evolution.DefaultSources"
 
74
 
 
75
/* Built-in data source UIDs. */
 
76
#define E_SOURCE_BUILTIN_ADDRESS_BOOK_UID       "system-address-book"
 
77
#define E_SOURCE_BUILTIN_CALENDAR_UID           "system-calendar"
 
78
#define E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID       "local"
 
79
#define E_SOURCE_BUILTIN_MEMO_LIST_UID          "system-memo-list"
 
80
#define E_SOURCE_BUILTIN_TASK_LIST_UID          "system-task-list"
 
81
 
 
82
/* GSettings keys for default data sources. */
 
83
#define E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY     "default-address-book"
 
84
#define E_SETTINGS_DEFAULT_CALENDAR_KEY         "default-calendar"
 
85
#define E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY     "default-mail-account"
 
86
#define E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY    "default-mail-identity"
 
87
#define E_SETTINGS_DEFAULT_MEMO_LIST_KEY        "default-memo-list"
 
88
#define E_SETTINGS_DEFAULT_TASK_LIST_KEY        "default-task-list"
 
89
 
 
90
typedef struct _AsyncContext AsyncContext;
 
91
typedef struct _AuthContext AuthContext;
 
92
typedef struct _SourceClosure SourceClosure;
 
93
typedef struct _ThreadClosure ThreadClosure;
 
94
 
 
95
struct _ESourceRegistryPrivate {
 
96
        GMainContext *main_context;
 
97
 
 
98
        GThread *manager_thread;
 
99
        ThreadClosure *thread_closure;
 
100
 
 
101
        GDBusObjectManager *dbus_object_manager;
 
102
        EDBusSourceManager *dbus_source_manager;
 
103
 
 
104
        GHashTable *object_path_table;
 
105
        GMutex *object_path_table_lock;
 
106
 
 
107
        GHashTable *sources;
 
108
        GMutex *sources_lock;
 
109
 
 
110
        GSettings *settings;
 
111
};
 
112
 
 
113
struct _AsyncContext {
 
114
        ESource *source;
 
115
        GList *list_of_sources;
 
116
        ESourceAuthenticator *auth;
 
117
};
 
118
 
 
119
/* Used in e_source_registry_authenticate_sync() */
 
120
struct _AuthContext {
 
121
        ESourceAuthenticator *auth;
 
122
        EDBusAuthenticator *dbus_auth;
 
123
        GCancellable *cancellable;
 
124
        GMainLoop *main_loop;
 
125
        ESourceAuthenticationResult auth_result;
 
126
        GcrSecretExchange *secret_exchange;
 
127
        gboolean authenticating;
 
128
        gboolean success;
 
129
        GError **error;
 
130
};
 
131
 
 
132
struct _SourceClosure {
 
133
        ESourceRegistry *registry;
 
134
        ESource *source;
 
135
};
 
136
 
 
137
struct _ThreadClosure {
 
138
        ESourceRegistry *registry;
 
139
        GMainContext *main_context;
 
140
        GMainLoop *main_loop;
 
141
        GCond *main_loop_cond;
 
142
        GMutex *main_loop_mutex;
 
143
};
 
144
 
 
145
enum {
 
146
        PROP_0,
 
147
        PROP_DEFAULT_ADDRESS_BOOK,
 
148
        PROP_DEFAULT_CALENDAR,
 
149
        PROP_DEFAULT_MAIL_ACCOUNT,
 
150
        PROP_DEFAULT_MAIL_IDENTITY,
 
151
        PROP_DEFAULT_MEMO_LIST,
 
152
        PROP_DEFAULT_TASK_LIST
 
153
};
 
154
 
 
155
enum {
 
156
        SOURCE_ADDED,
 
157
        SOURCE_CHANGED,
 
158
        SOURCE_REMOVED,
 
159
        SOURCE_ENABLED,
 
160
        SOURCE_DISABLED,
 
161
        LAST_SIGNAL
 
162
};
 
163
 
 
164
/* Forward Declarations */
 
165
static void     source_registry_add_source      (ESourceRegistry *registry,
 
166
                                                 ESource *source);
 
167
static void     e_source_registry_initable_init (GInitableIface *interface);
 
168
 
 
169
static guint signals[LAST_SIGNAL];
 
170
 
 
171
/* By default, the GAsyncInitable interface calls GInitable.init()
 
172
 * from a separate thread, so we only have to override GInitable. */
 
173
G_DEFINE_TYPE_WITH_CODE (
 
174
        ESourceRegistry,
 
175
        e_source_registry,
 
176
        G_TYPE_OBJECT,
 
177
        G_IMPLEMENT_INTERFACE (
 
178
                G_TYPE_INITABLE, e_source_registry_initable_init)
 
179
        G_IMPLEMENT_INTERFACE (
 
180
                G_TYPE_ASYNC_INITABLE, NULL))
 
181
 
 
182
static void
 
183
async_context_free (AsyncContext *async_context)
 
184
{
 
185
        if (async_context->source != NULL)
 
186
                g_object_unref (async_context->source);
 
187
 
 
188
        g_list_free_full (
 
189
                async_context->list_of_sources,
 
190
                (GDestroyNotify) g_object_unref);
 
191
 
 
192
        if (async_context->auth != NULL)
 
193
                g_object_unref (async_context->auth);
 
194
 
 
195
        g_slice_free (AsyncContext, async_context);
 
196
}
 
197
 
 
198
static void
 
199
auth_context_free (AuthContext *auth_context)
 
200
{
 
201
        if (auth_context->auth != NULL)
 
202
                g_object_unref (auth_context->auth);
 
203
 
 
204
        if (auth_context->dbus_auth != NULL)
 
205
                g_object_unref (auth_context->dbus_auth);
 
206
 
 
207
        if (auth_context->cancellable != NULL)
 
208
                g_object_unref (auth_context->cancellable);
 
209
 
 
210
        if (auth_context->main_loop != NULL)
 
211
                g_main_loop_unref (auth_context->main_loop);
 
212
 
 
213
        if (auth_context->secret_exchange != NULL)
 
214
                g_object_unref (auth_context->secret_exchange);
 
215
 
 
216
        g_slice_free (AuthContext, auth_context);
 
217
}
 
218
 
 
219
static void
 
220
source_closure_free (SourceClosure *closure)
 
221
{
 
222
        g_object_unref (closure->registry);
 
223
        g_object_unref (closure->source);
 
224
 
 
225
        g_slice_free (SourceClosure, closure);
 
226
}
 
227
 
 
228
static void
 
229
thread_closure_free (ThreadClosure *closure)
 
230
{
 
231
        /* The registry member is not referenced. */
 
232
 
 
233
        g_main_context_unref (closure->main_context);
 
234
        g_main_loop_unref (closure->main_loop);
 
235
        g_cond_free (closure->main_loop_cond);
 
236
        g_mutex_free (closure->main_loop_mutex);
 
237
 
 
238
        g_slice_free (ThreadClosure, closure);
 
239
}
 
240
 
 
241
static void
 
242
source_registry_object_path_table_insert (ESourceRegistry *registry,
 
243
                                          const gchar *object_path,
 
244
                                          ESource *source)
 
245
{
 
246
        g_return_if_fail (object_path != NULL);
 
247
        g_return_if_fail (E_IS_SOURCE (source));
 
248
 
 
249
        g_mutex_lock (registry->priv->object_path_table_lock);
 
250
 
 
251
        g_hash_table_insert (
 
252
                registry->priv->object_path_table,
 
253
                g_strdup (object_path),
 
254
                g_object_ref (source));
 
255
 
 
256
        g_mutex_unlock (registry->priv->object_path_table_lock);
 
257
}
 
258
 
 
259
static ESource *
 
260
source_registry_object_path_table_lookup (ESourceRegistry *registry,
 
261
                                          const gchar *object_path)
 
262
{
 
263
        ESource *source;
 
264
 
 
265
        g_return_val_if_fail (object_path != NULL, NULL);
 
266
 
 
267
        g_mutex_lock (registry->priv->object_path_table_lock);
 
268
 
 
269
        source = g_hash_table_lookup (
 
270
                registry->priv->object_path_table, object_path);
 
271
        if (source != NULL)
 
272
                g_object_ref (source);
 
273
 
 
274
        g_mutex_unlock (registry->priv->object_path_table_lock);
 
275
 
 
276
        return source;
 
277
}
 
278
 
 
279
static gboolean
 
280
source_registry_object_path_table_remove (ESourceRegistry *registry,
 
281
                                          const gchar *object_path)
 
282
{
 
283
        gboolean removed;
 
284
 
 
285
        g_return_val_if_fail (object_path != NULL, FALSE);
 
286
 
 
287
        g_mutex_lock (registry->priv->object_path_table_lock);
 
288
 
 
289
        removed = g_hash_table_remove (
 
290
                registry->priv->object_path_table, object_path);
 
291
 
 
292
        g_mutex_unlock (registry->priv->object_path_table_lock);
 
293
 
 
294
        return removed;
 
295
}
 
296
 
 
297
static void
 
298
source_registry_sources_insert (ESourceRegistry *registry,
 
299
                                ESource *source)
 
300
{
 
301
        const gchar *uid;
 
302
 
 
303
        uid = e_source_get_uid (source);
 
304
        g_return_if_fail (uid != NULL);
 
305
 
 
306
        g_mutex_lock (registry->priv->sources_lock);
 
307
 
 
308
        g_hash_table_insert (
 
309
                registry->priv->sources,
 
310
                g_strdup (uid), g_object_ref (source));
 
311
 
 
312
        g_mutex_unlock (registry->priv->sources_lock);
 
313
}
 
314
 
 
315
static gboolean
 
316
source_registry_sources_remove (ESourceRegistry *registry,
 
317
                                ESource *source)
 
318
{
 
319
        const gchar *uid;
 
320
        gboolean removed;
 
321
 
 
322
        uid = e_source_get_uid (source);
 
323
        g_return_val_if_fail (uid != NULL, FALSE);
 
324
 
 
325
        g_mutex_lock (registry->priv->sources_lock);
 
326
 
 
327
        removed = g_hash_table_remove (registry->priv->sources, uid);
 
328
 
 
329
        g_mutex_unlock (registry->priv->sources_lock);
 
330
 
 
331
        return removed;
 
332
}
 
333
 
 
334
static ESource *
 
335
source_registry_sources_lookup (ESourceRegistry *registry,
 
336
                                const gchar *uid)
 
337
{
 
338
        ESource *source;
 
339
 
 
340
        g_return_val_if_fail (uid != NULL, NULL);
 
341
 
 
342
        g_mutex_lock (registry->priv->sources_lock);
 
343
 
 
344
        source = g_hash_table_lookup (registry->priv->sources, uid);
 
345
 
 
346
        if (source != NULL)
 
347
                g_object_ref (source);
 
348
 
 
349
        g_mutex_unlock (registry->priv->sources_lock);
 
350
 
 
351
        return source;
 
352
}
 
353
 
 
354
static GList *
 
355
source_registry_sources_get_values (ESourceRegistry *registry)
 
356
{
 
357
        GList *values;
 
358
 
 
359
        g_mutex_lock (registry->priv->sources_lock);
 
360
 
 
361
        values = g_hash_table_get_values (registry->priv->sources);
 
362
 
 
363
        g_list_foreach (values, (GFunc) g_object_ref, NULL);
 
364
 
 
365
        g_mutex_unlock (registry->priv->sources_lock);
 
366
 
 
367
        return values;
 
368
}
 
369
 
 
370
static GNode *
 
371
source_registry_sources_build_tree (ESourceRegistry *registry)
 
372
{
 
373
        GNode *root;
 
374
        GHashTable *index;
 
375
        GHashTableIter iter;
 
376
        gpointer key, value;
 
377
 
 
378
        g_mutex_lock (registry->priv->sources_lock);
 
379
 
 
380
        root = g_node_new (NULL);
 
381
        index = g_hash_table_new (g_str_hash, g_str_equal);
 
382
 
 
383
        /* Add a GNode for each ESource to the index. */
 
384
        g_hash_table_iter_init (&iter, registry->priv->sources);
 
385
        while (g_hash_table_iter_next (&iter, &key, &value)) {
 
386
                ESource *source = g_object_ref (value);
 
387
                g_hash_table_insert (index, key, g_node_new (source));
 
388
        }
 
389
 
 
390
        /* Traverse the index and link the nodes together. */
 
391
        g_hash_table_iter_init (&iter, index);
 
392
        while (g_hash_table_iter_next (&iter, NULL, &value)) {
 
393
                ESource *source;
 
394
                GNode *source_node;
 
395
                GNode *parent_node;
 
396
                const gchar *parent_uid;
 
397
 
 
398
                source_node = (GNode *) value;
 
399
                source = E_SOURCE (source_node->data);
 
400
                parent_uid = e_source_get_parent (source);
 
401
 
 
402
                if (parent_uid == NULL || *parent_uid == '\0') {
 
403
                        parent_node = root;
 
404
                } else {
 
405
                        parent_node = g_hash_table_lookup (index, parent_uid);
 
406
                        g_warn_if_fail (parent_node != NULL);
 
407
                }
 
408
 
 
409
                /* Should never be NULL, but just to be safe. */
 
410
                if (parent_node != NULL)
 
411
                        g_node_append (parent_node, source_node);
 
412
        }
 
413
 
 
414
        g_hash_table_destroy (index);
 
415
 
 
416
        g_mutex_unlock (registry->priv->sources_lock);
 
417
 
 
418
        return root;
 
419
}
 
420
 
 
421
static void
 
422
source_registry_settings_changed_cb (GSettings *settings,
 
423
                                     const gchar *key,
 
424
                                     ESourceRegistry *registry)
 
425
{
 
426
        /* We define a property name that matches every key in
 
427
         * the "org.gnome.Evolution.DefaultSources" schema. */
 
428
        g_object_notify (G_OBJECT (registry), key);
 
429
}
 
430
 
 
431
static gboolean
 
432
source_registry_source_changed_idle_cb (gpointer user_data)
 
433
{
 
434
        SourceClosure *closure = user_data;
 
435
 
 
436
        g_signal_emit (
 
437
                closure->registry,
 
438
                signals[SOURCE_CHANGED], 0,
 
439
                closure->source);
 
440
 
 
441
        return FALSE;
 
442
}
 
443
 
 
444
static gboolean
 
445
source_registry_source_notify_enabled_idle_cb (gpointer user_data)
 
446
{
 
447
        SourceClosure *closure = user_data;
 
448
 
 
449
        if (e_source_get_enabled (closure->source))
 
450
                g_signal_emit (
 
451
                        closure->registry,
 
452
                        signals[SOURCE_ENABLED], 0,
 
453
                        closure->source);
 
454
        else
 
455
                g_signal_emit (
 
456
                        closure->registry,
 
457
                        signals[SOURCE_DISABLED], 0,
 
458
                        closure->source);
 
459
 
 
460
        return FALSE;
 
461
}
 
462
 
 
463
static void
 
464
source_registry_source_changed_cb (ESource *source,
 
465
                                   ESourceRegistry *registry)
 
466
{
 
467
        GSource *idle_source;
 
468
        SourceClosure *closure;
 
469
 
 
470
        closure = g_slice_new0 (SourceClosure);
 
471
        closure->registry = g_object_ref (registry);
 
472
        closure->source = g_object_ref (source);
 
473
 
 
474
        idle_source = g_idle_source_new ();
 
475
        g_source_set_callback (
 
476
                idle_source,
 
477
                source_registry_source_changed_idle_cb,
 
478
                closure, (GDestroyNotify) source_closure_free);
 
479
        g_source_attach (idle_source, registry->priv->main_context);
 
480
        g_source_unref (idle_source);
 
481
}
 
482
 
 
483
static void
 
484
source_registry_source_notify_enabled_cb (ESource *source,
 
485
                                          GParamSpec *pspec,
 
486
                                          ESourceRegistry *registry)
 
487
{
 
488
        GSource *idle_source;
 
489
        SourceClosure *closure;
 
490
 
 
491
        closure = g_slice_new0 (SourceClosure);
 
492
        closure->registry = g_object_ref (registry);
 
493
        closure->source = g_object_ref (source);
 
494
 
 
495
        idle_source = g_idle_source_new ();
 
496
        g_source_set_callback (
 
497
                idle_source,
 
498
                source_registry_source_notify_enabled_idle_cb,
 
499
                closure, (GDestroyNotify) source_closure_free);
 
500
        g_source_attach (idle_source, registry->priv->main_context);
 
501
        g_source_unref (idle_source);
 
502
}
 
503
 
 
504
static ESource *
 
505
source_registry_new_source (ESourceRegistry *registry,
 
506
                            GDBusObject *dbus_object)
 
507
{
 
508
        GMainContext *main_context;
 
509
        ESource *source;
 
510
        const gchar *object_path;
 
511
        GError *error = NULL;
 
512
 
 
513
        /* We don't want the ESource emitting "changed" signals from
 
514
         * the manager thread, so we pass it the same main context the
 
515
         * registry uses for scheduling signal emissions. */
 
516
        main_context = registry->priv->main_context;
 
517
        source = e_source_new (dbus_object, main_context, &error);
 
518
        object_path = g_dbus_object_get_object_path (dbus_object);
 
519
 
 
520
        /* The likelihood of an error here is slim, so it's
 
521
         * sufficient to just print a warning if one occurs. */
 
522
        if (error != NULL) {
 
523
                g_warn_if_fail (source == NULL);
 
524
                g_critical (
 
525
                        "ESourceRegistry: Failed to create a "
 
526
                        "data source object for path '%s': %s",
 
527
                        object_path, error->message);
 
528
                g_error_free (error);
 
529
                return NULL;
 
530
        }
 
531
 
 
532
        g_return_val_if_fail (E_IS_SOURCE (source), NULL);
 
533
 
 
534
        /* Add the ESource to the object path table immediately. */
 
535
        source_registry_object_path_table_insert (
 
536
                registry, object_path, source);
 
537
 
 
538
        return source;
 
539
}
 
540
 
 
541
static void
 
542
source_registry_unref_source (ESource *source)
 
543
{
 
544
        g_signal_handlers_disconnect_matched (
 
545
                source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
 
546
                source_registry_source_changed_cb, NULL);
 
547
 
 
548
        g_signal_handlers_disconnect_matched (
 
549
                source, G_SIGNAL_MATCH_FUNC, 0, 0, NULL,
 
550
                source_registry_source_notify_enabled_cb, NULL);
 
551
 
 
552
        g_object_unref (source);
 
553
}
 
554
 
 
555
static void
 
556
source_registry_add_source (ESourceRegistry *registry,
 
557
                            ESource *source)
 
558
{
 
559
        const gchar *uid;
 
560
 
 
561
        uid = e_source_get_uid (source);
 
562
        g_return_if_fail (uid != NULL);
 
563
 
 
564
        g_mutex_lock (registry->priv->sources_lock);
 
565
 
 
566
        /* Check if we already have this source in the registry. */
 
567
        if (g_hash_table_lookup (registry->priv->sources, uid) != NULL) {
 
568
                g_mutex_unlock (registry->priv->sources_lock);
 
569
                return;
 
570
        }
 
571
 
 
572
        g_signal_connect (
 
573
                source, "changed",
 
574
                G_CALLBACK (source_registry_source_changed_cb),
 
575
                registry);
 
576
 
 
577
        g_signal_connect (
 
578
                source, "notify::enabled",
 
579
                G_CALLBACK (source_registry_source_notify_enabled_cb),
 
580
                registry);
 
581
 
 
582
        g_mutex_unlock (registry->priv->sources_lock);
 
583
 
 
584
        source_registry_sources_insert (registry, source);
 
585
 
 
586
        g_signal_emit (registry, signals[SOURCE_ADDED], 0, source);
 
587
}
 
588
 
 
589
static void
 
590
source_registry_remove_source (ESourceRegistry *registry,
 
591
                               ESource *source)
 
592
{
 
593
        g_object_ref (source);
 
594
 
 
595
        if (source_registry_sources_remove (registry, source))
 
596
                g_signal_emit (registry, signals[SOURCE_REMOVED], 0, source);
 
597
 
 
598
        g_object_unref (source);
 
599
}
 
600
 
 
601
static gboolean
 
602
source_registry_object_added_idle_cb (gpointer user_data)
 
603
{
 
604
        SourceClosure *closure = user_data;
 
605
 
 
606
        source_registry_add_source (closure->registry, closure->source);
 
607
 
 
608
        return FALSE;
 
609
}
 
610
 
 
611
static void
 
612
source_registry_object_added_cb (GDBusObjectManager *object_manager,
 
613
                                 GDBusObject *dbus_object,
 
614
                                 ESourceRegistry *registry)
 
615
{
 
616
        SourceClosure *closure;
 
617
        GSource *idle_source;
 
618
        ESource *source;
 
619
 
 
620
        g_return_if_fail (E_DBUS_IS_OBJECT (dbus_object));
 
621
 
 
622
        source = source_registry_new_source (registry, dbus_object);
 
623
        g_return_if_fail (source != NULL);
 
624
 
 
625
        /* Schedule a callback on the ESourceRegistry's GMainContext. */
 
626
 
 
627
        closure = g_slice_new0 (SourceClosure);
 
628
        closure->registry = g_object_ref (registry);
 
629
        closure->source = g_object_ref (source);
 
630
 
 
631
        idle_source = g_idle_source_new ();
 
632
        g_source_set_callback (
 
633
                idle_source,
 
634
                source_registry_object_added_idle_cb,
 
635
                closure, (GDestroyNotify) source_closure_free);
 
636
        g_source_attach (idle_source, registry->priv->main_context);
 
637
        g_source_unref (idle_source);
 
638
 
 
639
        g_object_unref (source);
 
640
}
 
641
 
 
642
static gboolean
 
643
source_registry_object_removed_idle_cb (gpointer user_data)
 
644
{
 
645
        SourceClosure *closure = user_data;
 
646
 
 
647
        source_registry_remove_source (closure->registry, closure->source);
 
648
 
 
649
        return FALSE;
 
650
}
 
651
 
 
652
static void
 
653
source_registry_object_removed_cb (GDBusObjectManager *manager,
 
654
                                   GDBusObject *dbus_object,
 
655
                                   ESourceRegistry *registry)
 
656
{
 
657
        SourceClosure *closure;
 
658
        GSource *idle_source;
 
659
        ESource *source;
 
660
        const gchar *object_path;
 
661
 
 
662
        /* Find the corresponding ESource in the object path table.
 
663
         * Note that the lookup returns a new ESource reference. */
 
664
        object_path = g_dbus_object_get_object_path (dbus_object);
 
665
        source = source_registry_object_path_table_lookup (
 
666
                registry, object_path);
 
667
        g_return_if_fail (E_IS_SOURCE (source));
 
668
 
 
669
        /* Remove the ESource from the object path table immediately. */
 
670
        source_registry_object_path_table_remove (registry, object_path);
 
671
 
 
672
        /* Schedule a callback on the ESourceRegistry's GMainContext. */
 
673
 
 
674
        closure = g_slice_new0 (SourceClosure);
 
675
        closure->registry = g_object_ref (registry);
 
676
        closure->source = g_object_ref (source);
 
677
 
 
678
        idle_source = g_idle_source_new ();
 
679
        g_source_set_callback (
 
680
                idle_source,
 
681
                source_registry_object_removed_idle_cb,
 
682
                closure, (GDestroyNotify) source_closure_free);
 
683
        g_source_attach (idle_source, registry->priv->main_context);
 
684
        g_source_unref (idle_source);
 
685
 
 
686
        g_object_unref (source);
 
687
}
 
688
 
 
689
static gboolean
 
690
source_registry_object_manager_running (gpointer data)
 
691
{
 
692
        ThreadClosure *closure = data;
 
693
 
 
694
        g_mutex_lock (closure->main_loop_mutex);
 
695
        g_cond_broadcast (closure->main_loop_cond);
 
696
        g_mutex_unlock (closure->main_loop_mutex);
 
697
 
 
698
        return FALSE;
 
699
}
 
700
 
 
701
static gpointer
 
702
source_registry_object_manager_thread (gpointer data)
 
703
{
 
704
        GDBusObjectManager *object_manager;
 
705
        ThreadClosure *closure = data;
 
706
        GSource *idle_source;
 
707
        GList *list, *link;
 
708
        gulong object_added_id;
 
709
        gulong object_removed_id;
 
710
        GError *error = NULL;
 
711
 
 
712
        /* GDBusObjectManagerClient grabs the thread-default GMainContext
 
713
         * at creation time and only emits signals from that GMainContext.
 
714
         * Running it in a separate thread prevents its signal emissions
 
715
         * from being inhibited by someone overriding the thread-default
 
716
         * GMainContext. */
 
717
 
 
718
        /* This becomes the GMainContext that GDBusObjectManagerClient
 
719
         * will emit signals from.  Make it the thread-default context
 
720
         * for this thread before creating the client. */
 
721
        g_main_context_push_thread_default (closure->main_context);
 
722
 
 
723
        object_manager = e_dbus_object_manager_client_new_for_bus_sync (
 
724
                G_BUS_TYPE_SESSION,
 
725
                G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
 
726
                SOURCES_DBUS_SERVICE_NAME,
 
727
                DBUS_OBJECT_PATH,
 
728
                NULL, &error);
 
729
 
 
730
        /* If this fails there's really no point in continuing
 
731
         * since we rely on the object manager to populate the
 
732
         * registry.  Abort the process with a fatal error. */
 
733
        if (error != NULL) {
 
734
                g_error ("%s", error->message);
 
735
                g_assert_not_reached ();
 
736
        }
 
737
 
 
738
        /* Give the registry a handle to the object manager. */
 
739
        closure->registry->priv->dbus_object_manager =
 
740
                g_object_ref (object_manager);
 
741
 
 
742
        /* Now populate the registry with an initial set of ESources. */
 
743
 
 
744
        list = g_dbus_object_manager_get_objects (object_manager);
 
745
 
 
746
        for (link = list; link != NULL; link = g_list_next (link)) {
 
747
                GDBusObject *dbus_object;
 
748
                ESource *source;
 
749
 
 
750
                dbus_object = G_DBUS_OBJECT (link->data);
 
751
 
 
752
                source = source_registry_new_source (
 
753
                        closure->registry, dbus_object);
 
754
 
 
755
                if (source != NULL) {
 
756
                        source_registry_add_source (
 
757
                                closure->registry, source);
 
758
                        g_object_unref (source);
 
759
                }
 
760
        }
 
761
 
 
762
        g_list_free_full (list, (GDestroyNotify) g_object_unref);
 
763
 
 
764
        /* Schedule a one-time idle callback to broadcast through a
 
765
         * condition variable that our main loop is up and running. */
 
766
 
 
767
        idle_source = g_idle_source_new ();
 
768
        g_source_set_callback (
 
769
                idle_source,
 
770
                source_registry_object_manager_running,
 
771
                closure, (GDestroyNotify) NULL);
 
772
        g_source_attach (idle_source, closure->main_context);
 
773
        g_source_unref (idle_source);
 
774
 
 
775
        /* Listen for D-Bus object additions and removals. */
 
776
 
 
777
        object_added_id = g_signal_connect (
 
778
                object_manager, "object-added",
 
779
                G_CALLBACK (source_registry_object_added_cb),
 
780
                closure->registry);
 
781
 
 
782
        object_removed_id = g_signal_connect (
 
783
                object_manager, "object-removed",
 
784
                G_CALLBACK (source_registry_object_removed_cb),
 
785
                closure->registry);
 
786
 
 
787
        /* Now we mostly idle here for the rest of the session. */
 
788
 
 
789
        g_main_loop_run (closure->main_loop);
 
790
 
 
791
        /* Clean up and exit. */
 
792
 
 
793
        g_signal_handler_disconnect (object_manager, object_added_id);
 
794
        g_signal_handler_disconnect (object_manager, object_removed_id);
 
795
 
 
796
        g_object_unref (object_manager);
 
797
 
 
798
        g_main_context_pop_thread_default (closure->main_context);
 
799
 
 
800
        return NULL;
 
801
}
 
802
 
 
803
static void
 
804
source_registry_set_property (GObject *object,
 
805
                              guint property_id,
 
806
                              const GValue *value,
 
807
                              GParamSpec *pspec)
 
808
{
 
809
        switch (property_id) {
 
810
                case PROP_DEFAULT_ADDRESS_BOOK:
 
811
                        e_source_registry_set_default_address_book (
 
812
                                E_SOURCE_REGISTRY (object),
 
813
                                g_value_get_object (value));
 
814
                        return;
 
815
 
 
816
                case PROP_DEFAULT_CALENDAR:
 
817
                        e_source_registry_set_default_calendar (
 
818
                                E_SOURCE_REGISTRY (object),
 
819
                                g_value_get_object (value));
 
820
                        return;
 
821
 
 
822
                case PROP_DEFAULT_MAIL_ACCOUNT:
 
823
                        e_source_registry_set_default_mail_account (
 
824
                                E_SOURCE_REGISTRY (object),
 
825
                                g_value_get_object (value));
 
826
                        return;
 
827
 
 
828
                case PROP_DEFAULT_MAIL_IDENTITY:
 
829
                        e_source_registry_set_default_mail_identity (
 
830
                                E_SOURCE_REGISTRY (object),
 
831
                                g_value_get_object (value));
 
832
                        return;
 
833
 
 
834
                case PROP_DEFAULT_MEMO_LIST:
 
835
                        e_source_registry_set_default_memo_list (
 
836
                                E_SOURCE_REGISTRY (object),
 
837
                                g_value_get_object (value));
 
838
                        return;
 
839
 
 
840
                case PROP_DEFAULT_TASK_LIST:
 
841
                        e_source_registry_set_default_task_list (
 
842
                                E_SOURCE_REGISTRY (object),
 
843
                                g_value_get_object (value));
 
844
                        return;
 
845
        }
 
846
 
 
847
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
848
}
 
849
 
 
850
static void
 
851
source_registry_get_property (GObject *object,
 
852
                              guint property_id,
 
853
                              GValue *value,
 
854
                              GParamSpec *pspec)
 
855
{
 
856
        switch (property_id) {
 
857
                case PROP_DEFAULT_ADDRESS_BOOK:
 
858
                        g_value_take_object (
 
859
                                value,
 
860
                                e_source_registry_ref_default_address_book (
 
861
                                E_SOURCE_REGISTRY (object)));
 
862
                        return;
 
863
 
 
864
                case PROP_DEFAULT_CALENDAR:
 
865
                        g_value_take_object (
 
866
                                value,
 
867
                                e_source_registry_ref_default_calendar (
 
868
                                E_SOURCE_REGISTRY (object)));
 
869
                        return;
 
870
 
 
871
                case PROP_DEFAULT_MAIL_ACCOUNT:
 
872
                        g_value_take_object (
 
873
                                value,
 
874
                                e_source_registry_ref_default_mail_account (
 
875
                                E_SOURCE_REGISTRY (object)));
 
876
                        return;
 
877
 
 
878
                case PROP_DEFAULT_MAIL_IDENTITY:
 
879
                        g_value_take_object (
 
880
                                value,
 
881
                                e_source_registry_ref_default_mail_identity (
 
882
                                E_SOURCE_REGISTRY (object)));
 
883
                        return;
 
884
 
 
885
                case PROP_DEFAULT_MEMO_LIST:
 
886
                        g_value_take_object (
 
887
                                value,
 
888
                                e_source_registry_ref_default_memo_list (
 
889
                                E_SOURCE_REGISTRY (object)));
 
890
                        return;
 
891
 
 
892
                case PROP_DEFAULT_TASK_LIST:
 
893
                        g_value_take_object (
 
894
                                value,
 
895
                                e_source_registry_ref_default_task_list (
 
896
                                E_SOURCE_REGISTRY (object)));
 
897
                        return;
 
898
        }
 
899
 
 
900
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
901
}
 
902
 
 
903
static void
 
904
source_registry_dispose (GObject *object)
 
905
{
 
906
        ESourceRegistryPrivate *priv;
 
907
 
 
908
        priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
 
909
 
 
910
        /* Terminate the manager thread first. */
 
911
        if (priv->manager_thread != NULL) {
 
912
                g_main_loop_quit (priv->thread_closure->main_loop);
 
913
                g_thread_join (priv->manager_thread);
 
914
                thread_closure_free (priv->thread_closure);
 
915
                priv->manager_thread = NULL;
 
916
                priv->thread_closure = NULL;
 
917
        }
 
918
 
 
919
        if (priv->main_context != NULL) {
 
920
                g_main_context_unref (priv->main_context);
 
921
                priv->main_context = NULL;
 
922
        }
 
923
 
 
924
        if (priv->dbus_object_manager != NULL) {
 
925
                g_object_unref (priv->dbus_object_manager);
 
926
                priv->dbus_object_manager = NULL;
 
927
        }
 
928
 
 
929
        if (priv->dbus_source_manager != NULL) {
 
930
                g_object_unref (priv->dbus_source_manager);
 
931
                priv->dbus_source_manager = NULL;
 
932
        }
 
933
 
 
934
        g_hash_table_remove_all (priv->object_path_table);
 
935
 
 
936
        g_hash_table_remove_all (priv->sources);
 
937
 
 
938
        if (priv->settings != NULL) {
 
939
                g_object_unref (priv->settings);
 
940
                priv->settings = NULL;
 
941
        }
 
942
 
 
943
        /* Chain up to parent's finalize() method. */
 
944
        G_OBJECT_CLASS (e_source_registry_parent_class)->dispose (object);
 
945
}
 
946
 
 
947
static void
 
948
source_registry_finalize (GObject *object)
 
949
{
 
950
        ESourceRegistryPrivate *priv;
 
951
 
 
952
        priv = E_SOURCE_REGISTRY_GET_PRIVATE (object);
 
953
 
 
954
        g_hash_table_destroy (priv->object_path_table);
 
955
        g_mutex_free (priv->object_path_table_lock);
 
956
 
 
957
        g_hash_table_destroy (priv->sources);
 
958
        g_mutex_free (priv->sources_lock);
 
959
 
 
960
        /* Chain up to parent's finalize() method. */
 
961
        G_OBJECT_CLASS (e_source_registry_parent_class)->finalize (object);
 
962
}
 
963
 
 
964
static gboolean
 
965
source_registry_initable_init (GInitable *initable,
 
966
                               GCancellable *cancellable,
 
967
                               GError **error)
 
968
{
 
969
        ESourceRegistry *registry;
 
970
        ThreadClosure *closure;
 
971
 
 
972
        registry = E_SOURCE_REGISTRY (initable);
 
973
 
 
974
        closure = g_slice_new0 (ThreadClosure);
 
975
        closure->registry = registry;  /* do not reference */
 
976
        closure->main_context = g_main_context_new ();
 
977
        /* It's important to pass 'is_running=FALSE' here because
 
978
         * we wait for the main loop to start running as a way of
 
979
         * synchronizing with the manager thread. */
 
980
        closure->main_loop = g_main_loop_new (closure->main_context, FALSE);
 
981
        closure->main_loop_cond = g_cond_new ();
 
982
        closure->main_loop_mutex = g_mutex_new ();
 
983
 
 
984
        registry->priv->thread_closure = closure;
 
985
 
 
986
        registry->priv->manager_thread = g_thread_create (
 
987
                source_registry_object_manager_thread,
 
988
                closure, TRUE /* joinable */, error);
 
989
 
 
990
        if (registry->priv->manager_thread == NULL)
 
991
                return FALSE;
 
992
 
 
993
        /* Wait for notification that the manager
 
994
         * thread's main loop has been started. */
 
995
        g_mutex_lock (closure->main_loop_mutex);
 
996
        while (!g_main_loop_is_running (closure->main_loop))
 
997
                g_cond_wait (
 
998
                        closure->main_loop_cond,
 
999
                        closure->main_loop_mutex);
 
1000
        g_mutex_unlock (closure->main_loop_mutex);
 
1001
 
 
1002
        /* We should now have a GDBusObjectManagerClient available. */
 
1003
        g_return_val_if_fail (
 
1004
                G_IS_DBUS_OBJECT_MANAGER_CLIENT (
 
1005
                registry->priv->dbus_object_manager), FALSE);
 
1006
 
 
1007
        /* The registry should now be populated with sources. */
 
1008
        g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0);
 
1009
 
 
1010
        /* The EDBusSourceManagerProxy is just another D-Bus interface
 
1011
         * that resides at the same object path.  It's unrelated to the
 
1012
         * GDBusObjectManagerClient and doesn't need its own thread. */
 
1013
        registry->priv->dbus_source_manager =
 
1014
                e_dbus_source_manager_proxy_new_for_bus_sync (
 
1015
                        G_BUS_TYPE_SESSION,
 
1016
                        G_DBUS_PROXY_FLAGS_NONE,
 
1017
                        SOURCES_DBUS_SERVICE_NAME,
 
1018
                        DBUS_OBJECT_PATH,
 
1019
                        cancellable, error);
 
1020
 
 
1021
        if (registry->priv->dbus_source_manager == NULL)
 
1022
                return FALSE;
 
1023
 
 
1024
        return TRUE;
 
1025
}
 
1026
 
 
1027
static void
 
1028
e_source_registry_class_init (ESourceRegistryClass *class)
 
1029
{
 
1030
        GObjectClass *object_class;
 
1031
 
 
1032
        g_type_class_add_private (class, sizeof (ESourceRegistryPrivate));
 
1033
 
 
1034
        object_class = G_OBJECT_CLASS (class);
 
1035
        object_class->set_property = source_registry_set_property;
 
1036
        object_class->get_property = source_registry_get_property;
 
1037
        object_class->dispose = source_registry_dispose;
 
1038
        object_class->finalize = source_registry_finalize;
 
1039
 
 
1040
        /* The property names correspond to the key names in the
 
1041
         * "org.gnome.Evolution.DefaultSources" GSettings schema. */
 
1042
 
 
1043
        /**
 
1044
         * ESourceRegistry:default-address-book:
 
1045
         *
 
1046
         * The default address book #ESource.
 
1047
         **/
 
1048
        g_object_class_install_property (
 
1049
                object_class,
 
1050
                PROP_DEFAULT_ADDRESS_BOOK,
 
1051
                g_param_spec_object (
 
1052
                        "default-address-book",
 
1053
                        "Default Address Book",
 
1054
                        "The default address book ESource",
 
1055
                        E_TYPE_SOURCE,
 
1056
                        G_PARAM_READWRITE |
 
1057
                        G_PARAM_STATIC_STRINGS));
 
1058
 
 
1059
        /**
 
1060
         * ESourceRegistry:default-calendar:
 
1061
         *
 
1062
         * The default calendar #ESource.
 
1063
         **/
 
1064
        g_object_class_install_property (
 
1065
                object_class,
 
1066
                PROP_DEFAULT_CALENDAR,
 
1067
                g_param_spec_object (
 
1068
                        "default-calendar",
 
1069
                        "Default Calendar",
 
1070
                        "The default calendar ESource",
 
1071
                        E_TYPE_SOURCE,
 
1072
                        G_PARAM_READWRITE |
 
1073
                        G_PARAM_STATIC_STRINGS));
 
1074
 
 
1075
        /**
 
1076
         * ESourceRegistry:default-mail-account:
 
1077
         *
 
1078
         * The default mail account #ESource.
 
1079
         **/
 
1080
        g_object_class_install_property (
 
1081
                object_class,
 
1082
                PROP_DEFAULT_MAIL_ACCOUNT,
 
1083
                g_param_spec_object (
 
1084
                        "default-mail-account",
 
1085
                        "Default Mail Account",
 
1086
                        "The default mail account ESource",
 
1087
                        E_TYPE_SOURCE,
 
1088
                        G_PARAM_READWRITE |
 
1089
                        G_PARAM_STATIC_STRINGS));
 
1090
 
 
1091
        /**
 
1092
         * ESourceRegistry:default-mail-identity:
 
1093
         *
 
1094
         * The default mail identity #ESource.
 
1095
         **/
 
1096
        g_object_class_install_property (
 
1097
                object_class,
 
1098
                PROP_DEFAULT_MAIL_IDENTITY,
 
1099
                g_param_spec_object (
 
1100
                        "default-mail-identity",
 
1101
                        "Default Mail Identity",
 
1102
                        "The default mail identity ESource",
 
1103
                        E_TYPE_SOURCE,
 
1104
                        G_PARAM_READWRITE |
 
1105
                        G_PARAM_STATIC_STRINGS));
 
1106
 
 
1107
        /**
 
1108
         * ESourceRegistry:default-memo-list:
 
1109
         *
 
1110
         * The default memo list #ESource.
 
1111
         **/
 
1112
        g_object_class_install_property (
 
1113
                object_class,
 
1114
                PROP_DEFAULT_MEMO_LIST,
 
1115
                g_param_spec_object (
 
1116
                        "default-memo-list",
 
1117
                        "Default Memo List",
 
1118
                        "The default memo list ESource",
 
1119
                        E_TYPE_SOURCE,
 
1120
                        G_PARAM_READWRITE |
 
1121
                        G_PARAM_STATIC_STRINGS));
 
1122
 
 
1123
        /**
 
1124
         * ESourceRegistry:default-task-list:
 
1125
         *
 
1126
         * The default task list #ESource.
 
1127
         **/
 
1128
        g_object_class_install_property (
 
1129
                object_class,
 
1130
                PROP_DEFAULT_TASK_LIST,
 
1131
                g_param_spec_object (
 
1132
                        "default-task-list",
 
1133
                        "Default Task List",
 
1134
                        "The default task list ESource",
 
1135
                        E_TYPE_SOURCE,
 
1136
                        G_PARAM_READWRITE |
 
1137
                        G_PARAM_STATIC_STRINGS));
 
1138
 
 
1139
        /**
 
1140
         * ESourceRegistry::source-added:
 
1141
         * @registry: the #ESourceRegistry which emitted the signal
 
1142
         * @source: the newly-added #ESource
 
1143
         *
 
1144
         * Emitted when an #ESource is added to @registry.
 
1145
         **/
 
1146
        signals[SOURCE_ADDED] = g_signal_new (
 
1147
                "source-added",
 
1148
                G_OBJECT_CLASS_TYPE (object_class),
 
1149
                G_SIGNAL_RUN_LAST,
 
1150
                G_STRUCT_OFFSET (ESourceRegistryClass, source_added),
 
1151
                NULL, NULL,
 
1152
                g_cclosure_marshal_VOID__OBJECT,
 
1153
                G_TYPE_NONE, 1,
 
1154
                E_TYPE_SOURCE);
 
1155
 
 
1156
        /**
 
1157
         * ESourceRegistry::source-changed:
 
1158
         * @registry: the #ESourceRegistry which emitted the signal
 
1159
         * @source: the #ESource that changed
 
1160
         *
 
1161
         * Emitted when an #ESource registered with @registry emits
 
1162
         * its #ESource::changed signal.
 
1163
         **/
 
1164
        signals[SOURCE_CHANGED] = g_signal_new (
 
1165
                "source-changed",
 
1166
                G_OBJECT_CLASS_TYPE (object_class),
 
1167
                G_SIGNAL_RUN_LAST,
 
1168
                G_STRUCT_OFFSET (ESourceRegistryClass, source_changed),
 
1169
                NULL, NULL,
 
1170
                g_cclosure_marshal_VOID__OBJECT,
 
1171
                G_TYPE_NONE, 1,
 
1172
                E_TYPE_SOURCE);
 
1173
 
 
1174
        /**
 
1175
         * ESourceRegistry::source-removed:
 
1176
         * @registry: the #ESourceRegistry which emitted the signal
 
1177
         * @source: the #ESource that got removed
 
1178
         *
 
1179
         * Emitted when an #ESource is removed from @registry.
 
1180
         **/
 
1181
        signals[SOURCE_REMOVED] = g_signal_new (
 
1182
                "source-removed",
 
1183
                G_OBJECT_CLASS_TYPE (object_class),
 
1184
                G_SIGNAL_RUN_LAST,
 
1185
                G_STRUCT_OFFSET (ESourceRegistryClass, source_removed),
 
1186
                NULL, NULL,
 
1187
                g_cclosure_marshal_VOID__OBJECT,
 
1188
                G_TYPE_NONE, 1,
 
1189
                E_TYPE_SOURCE);
 
1190
 
 
1191
        /**
 
1192
         * ESourceRegistry::source-enabled:
 
1193
         * @registry: the #ESourceRegistry which emitted the signal
 
1194
         * @source: the #ESource that got enabled
 
1195
         *
 
1196
         * Emitted when an #ESource #ESource:enabled property becomes %TRUE.
 
1197
         **/
 
1198
        signals[SOURCE_ENABLED] = g_signal_new (
 
1199
                "source-enabled",
 
1200
                G_OBJECT_CLASS_TYPE (object_class),
 
1201
                G_SIGNAL_RUN_LAST,
 
1202
                G_STRUCT_OFFSET (ESourceRegistryClass, source_enabled),
 
1203
                NULL, NULL,
 
1204
                g_cclosure_marshal_VOID__OBJECT,
 
1205
                G_TYPE_NONE, 1,
 
1206
                E_TYPE_SOURCE);
 
1207
 
 
1208
        /**
 
1209
         * ESourceRegistry::source-disabled:
 
1210
         * @registry: the #ESourceRegistry which emitted the signal
 
1211
         * @source: the #ESource that got disabled
 
1212
         *
 
1213
         * Emitted when an #ESource #ESource:enabled property becomes %FALSE.
 
1214
         **/
 
1215
        signals[SOURCE_DISABLED] = g_signal_new (
 
1216
                "source-disabled",
 
1217
                G_OBJECT_CLASS_TYPE (object_class),
 
1218
                G_SIGNAL_RUN_LAST,
 
1219
                G_STRUCT_OFFSET (ESourceRegistryClass, source_disabled),
 
1220
                NULL, NULL,
 
1221
                g_cclosure_marshal_VOID__OBJECT,
 
1222
                G_TYPE_NONE, 1,
 
1223
                E_TYPE_SOURCE);
 
1224
}
 
1225
 
 
1226
static void
 
1227
e_source_registry_initable_init (GInitableIface *interface)
 
1228
{
 
1229
        interface->init = source_registry_initable_init;
 
1230
}
 
1231
 
 
1232
static void
 
1233
e_source_registry_init (ESourceRegistry *registry)
 
1234
{
 
1235
        registry->priv = E_SOURCE_REGISTRY_GET_PRIVATE (registry);
 
1236
 
 
1237
        /* This is so the object manager thread can schedule signal
 
1238
         * emissions on the thread-default context for this thread. */
 
1239
        registry->priv->main_context = g_main_context_ref_thread_default ();
 
1240
 
 
1241
        /* D-Bus object path -> ESource */
 
1242
        registry->priv->object_path_table =
 
1243
                g_hash_table_new_full (
 
1244
                        (GHashFunc) g_str_hash,
 
1245
                        (GEqualFunc) g_str_equal,
 
1246
                        (GDestroyNotify) g_free,
 
1247
                        (GDestroyNotify) g_object_unref);
 
1248
 
 
1249
        registry->priv->object_path_table_lock = g_mutex_new ();
 
1250
 
 
1251
        /* UID string -> ESource */
 
1252
        registry->priv->sources = g_hash_table_new_full (
 
1253
                (GHashFunc) g_str_hash,
 
1254
                (GEqualFunc) g_str_equal,
 
1255
                (GDestroyNotify) g_free,
 
1256
                (GDestroyNotify) source_registry_unref_source);
 
1257
 
 
1258
        registry->priv->sources_lock = g_mutex_new ();
 
1259
 
 
1260
        registry->priv->settings = g_settings_new (GSETTINGS_SCHEMA);
 
1261
 
 
1262
        g_signal_connect (
 
1263
                registry->priv->settings, "changed",
 
1264
                G_CALLBACK (source_registry_settings_changed_cb), registry);
 
1265
}
 
1266
 
 
1267
/**
 
1268
 * e_source_registry_new_sync:
 
1269
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 
1270
 * @error: return location for a #GError, or %NULL
 
1271
 *
 
1272
 * Creates a new #ESourceRegistry front-end for the registry D-Bus service.
 
1273
 * If an error occurs in connecting to the D-Bus service, the function sets
 
1274
 * @error and returns %NULL.
 
1275
 *
 
1276
 * Returns: a new #ESourceRegistry, or %NULL
 
1277
 *
 
1278
 * Since: 3.6
 
1279
 **/
 
1280
ESourceRegistry *
 
1281
e_source_registry_new_sync (GCancellable *cancellable,
 
1282
                            GError **error)
 
1283
{
 
1284
        return g_initable_new (
 
1285
                E_TYPE_SOURCE_REGISTRY,
 
1286
                cancellable, error, NULL);
 
1287
}
 
1288
 
 
1289
/**
 
1290
 * e_source_registry_new:
 
1291
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 
1292
 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
 
1293
 *            is satisfied
 
1294
 * @user_data: (closure): data to pass to the callback function
 
1295
 *
 
1296
 * Asynchronously creates a new #ESourceRegistry front-end for the registry
 
1297
 * D-Bus service.
 
1298
 *
 
1299
 * When the operation is finished, @callback will be called.  You can then
 
1300
 * call e_source_registry_new_finish() to get the result of the operation.
 
1301
 *
 
1302
 * Since: 3.6
 
1303
 **/
 
1304
void
 
1305
e_source_registry_new (GCancellable *cancellable,
 
1306
                       GAsyncReadyCallback callback,
 
1307
                       gpointer user_data)
 
1308
{
 
1309
        g_async_initable_new_async (
 
1310
                E_TYPE_SOURCE_REGISTRY,
 
1311
                G_PRIORITY_DEFAULT, cancellable,
 
1312
                callback, user_data, NULL);
 
1313
}
 
1314
 
 
1315
/**
 
1316
 * e_source_registry_new_finish:
 
1317
 * @result: a #GAsyncResult
 
1318
 * @error: return location for a #GError, or %NULL
 
1319
 *
 
1320
 * Finishes the operation started with e_source_registry_new_finish().
 
1321
 * If an error occurs in connecting to the D-Bus service, the function
 
1322
 * sets @error and returns %NULL.
 
1323
 *
 
1324
 * Returns: a new #ESourceRegistry, or %NULL
 
1325
 *
 
1326
 * Since: 3.6
 
1327
 **/
 
1328
ESourceRegistry *
 
1329
e_source_registry_new_finish (GAsyncResult *result,
 
1330
                              GError **error)
 
1331
{
 
1332
        GObject *source_object;
 
1333
        GObject *object;
 
1334
 
 
1335
        g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
 
1336
 
 
1337
        source_object = g_async_result_get_source_object (result);
 
1338
        g_return_val_if_fail (source_object != NULL, NULL);
 
1339
 
 
1340
        object = g_async_initable_new_finish (
 
1341
                G_ASYNC_INITABLE (source_object), result, error);
 
1342
 
 
1343
        g_object_unref (source_object);
 
1344
 
 
1345
        return (object != NULL) ? E_SOURCE_REGISTRY (object) : NULL;
 
1346
}
 
1347
 
 
1348
/* Helper for e_source_registry_authenticate() */
 
1349
static void
 
1350
source_registry_authenticate_thread (GSimpleAsyncResult *simple,
 
1351
                                     GObject *object,
 
1352
                                     GCancellable *cancellable)
 
1353
{
 
1354
        AsyncContext *async_context;
 
1355
        GError *error = NULL;
 
1356
 
 
1357
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
1358
 
 
1359
        e_source_registry_authenticate_sync (
 
1360
                E_SOURCE_REGISTRY (object),
 
1361
                async_context->source,
 
1362
                async_context->auth,
 
1363
                cancellable, &error);
 
1364
 
 
1365
        if (error != NULL)
 
1366
                g_simple_async_result_take_error (simple, error);
 
1367
}
 
1368
 
 
1369
/* Helper for e_source_registry_authenticate_sync() */
 
1370
static gboolean
 
1371
source_registry_authenticate_respond_cb (AuthContext *auth_context)
 
1372
{
 
1373
        ESourceAuthenticationResult auth_result;
 
1374
        GError *non_fatal_error = NULL;
 
1375
 
 
1376
        g_return_val_if_fail (auth_context->authenticating, FALSE);
 
1377
 
 
1378
        auth_result = auth_context->auth_result;
 
1379
 
 
1380
        /* Allow the next authentication attempt to proceed. */
 
1381
        auth_context->authenticating = FALSE;
 
1382
 
 
1383
        /* Send the server a status update based on the authentication
 
1384
         * result.  Note, we don't really care if the D-Bus message gets
 
1385
         * through to the server at this point.  If it doesn't, the auth
 
1386
         * session will either time out on its own or the authentication
 
1387
         * dialog will eventually be dismissed by the user. */
 
1388
 
 
1389
        /* If an error occurred while attempting to authenticate,
 
1390
         * tell the server to cancel the authentication session. */
 
1391
        if (auth_result == E_SOURCE_AUTHENTICATION_ERROR) {
 
1392
                e_dbus_authenticator_call_cancel_sync (
 
1393
                        auth_context->dbus_auth,
 
1394
                        auth_context->cancellable,
 
1395
                        &non_fatal_error);
 
1396
                g_main_loop_quit (auth_context->main_loop);
 
1397
                auth_context->success = FALSE;
 
1398
 
 
1399
        /* If the password was accepted, let the server know so it
 
1400
         * can close any authentication dialogs and save the user
 
1401
         * provided password to the keyring. */
 
1402
        } else if (auth_result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
 
1403
                e_dbus_authenticator_call_accepted_sync (
 
1404
                        auth_context->dbus_auth,
 
1405
                        auth_context->cancellable,
 
1406
                        &non_fatal_error);
 
1407
                g_main_loop_quit (auth_context->main_loop);
 
1408
                auth_context->success = TRUE;
 
1409
 
 
1410
        /* If the password was rejected, let the server know so it can
 
1411
         * indicate failure and request a different password, and then
 
1412
         * wait for the next "response" signal. */
 
1413
        } else {
 
1414
                e_dbus_authenticator_call_rejected_sync (
 
1415
                        auth_context->dbus_auth,
 
1416
                        auth_context->cancellable,
 
1417
                        &non_fatal_error);
 
1418
        }
 
1419
 
 
1420
        /* Leave breadcrumbs if something went wrong,
 
1421
         * but don't fail the whole operation over it. */
 
1422
        if (non_fatal_error != NULL) {
 
1423
                g_warning ("%s: %s", G_STRFUNC, non_fatal_error->message);
 
1424
                g_error_free (non_fatal_error);
 
1425
        }
 
1426
 
 
1427
        return FALSE;
 
1428
}
 
1429
 
 
1430
/* Helper for e_source_registry_authenticate_sync() */
 
1431
static void
 
1432
source_registry_authenticate_authenticate_cb (EDBusAuthenticator *dbus_auth,
 
1433
                                              const gchar *encrypted_secret,
 
1434
                                              AuthContext *auth_context)
 
1435
{
 
1436
        GSource *idle_source;
 
1437
        GMainContext *main_context;
 
1438
        GString *password;
 
1439
        gboolean valid_secret;
 
1440
 
 
1441
        /* We should only get one secret at a time. */
 
1442
        g_return_if_fail (!auth_context->authenticating);
 
1443
 
 
1444
        valid_secret = gcr_secret_exchange_receive (
 
1445
                auth_context->secret_exchange, encrypted_secret);
 
1446
        g_return_if_fail (valid_secret);
 
1447
 
 
1448
        auth_context->authenticating = TRUE;
 
1449
 
 
1450
        /* This avoids revealing the password in a stack trace. */
 
1451
        password = g_string_new (
 
1452
                gcr_secret_exchange_get_secret (
 
1453
                auth_context->secret_exchange, NULL));
 
1454
 
 
1455
        /* Try authenticating with the given password.  We have to
 
1456
         * call this synchronously because some authenticators use
 
1457
         * mutexes to serialize I/O operations and are not prepared
 
1458
         * to make authentication attempts from a different thread.
 
1459
         *
 
1460
         * Unfortunately this means we won't notice server-side
 
1461
         * dismissals while the main loop is blocked.  We respond
 
1462
         * to the server from a low-priority idle callback so that
 
1463
         * any pending "dismissed" signals get handled first. */
 
1464
 
 
1465
        auth_context->auth_result =
 
1466
                e_source_authenticator_try_password_sync (
 
1467
                        auth_context->auth, password,
 
1468
                        auth_context->cancellable,
 
1469
                        auth_context->error);
 
1470
 
 
1471
        idle_source = g_idle_source_new ();
 
1472
        main_context = g_main_context_get_thread_default ();
 
1473
        g_source_set_callback (
 
1474
                idle_source, (GSourceFunc)
 
1475
                source_registry_authenticate_respond_cb,
 
1476
                auth_context, NULL);
 
1477
        g_source_attach (idle_source, main_context);
 
1478
        g_source_unref (idle_source);
 
1479
 
 
1480
        g_string_free (password, TRUE);
 
1481
}
 
1482
 
 
1483
/* Helper for e_source_registry_authenticate_sync() */
 
1484
static void
 
1485
source_registry_authenticate_dismissed_cb (EDBusAuthenticator *dbus_auth,
 
1486
                                           AuthContext *auth_context)
 
1487
{
 
1488
        /* Be careful not to overwrite an existing error in case this
 
1489
         * is called after e_source_authenticator_try_password_sync()
 
1490
         * but prior to the idle callback. */
 
1491
        if (auth_context->auth_result != E_SOURCE_AUTHENTICATION_ERROR) {
 
1492
                /* XXX Use a separate error code for dismissals? */
 
1493
                g_set_error_literal (
 
1494
                        auth_context->error,
 
1495
                        G_IO_ERROR, G_IO_ERROR_CANCELLED,
 
1496
                        _("The user declined to authenticate"));
 
1497
                auth_context->auth_result = E_SOURCE_AUTHENTICATION_ERROR;
 
1498
        }
 
1499
 
 
1500
        g_main_loop_quit (auth_context->main_loop);
 
1501
        auth_context->success = FALSE;
 
1502
}
 
1503
 
 
1504
/* Helper for e_source_registry_authenticate_sync() */
 
1505
static gboolean
 
1506
source_registry_call_authenticate_for_source (ESourceRegistry *registry,
 
1507
                                              ESourceAuthenticator *auth,
 
1508
                                              ESource *source,
 
1509
                                              gchar **out_object_path,
 
1510
                                              GCancellable *cancellable,
 
1511
                                              GError **error)
 
1512
{
 
1513
        ESource *collection;
 
1514
        const gchar *uid;
 
1515
        gchar *prompt_title = NULL;
 
1516
        gchar *prompt_message = NULL;
 
1517
        gchar *prompt_description = NULL;
 
1518
        gboolean success;
 
1519
 
 
1520
        /* If the source is a member of a collection, we want to store
 
1521
         * the password under the UID of the "collection" source so it
 
1522
         * will apply to the entire collection.
 
1523
         *
 
1524
         * XXX This assumes all sources in a collection share a single
 
1525
         *     password.  If that turns out not to be true in all cases
 
1526
         *     we could maybe add a "SharedPassword: true/false" key to
 
1527
         *     [Collection] and apply it here.
 
1528
         */
 
1529
        collection = e_source_registry_find_extension (
 
1530
                registry, source, E_SOURCE_EXTENSION_COLLECTION);
 
1531
        if (collection != NULL)
 
1532
                source = collection;
 
1533
        else
 
1534
                g_object_ref (source);
 
1535
 
 
1536
        uid = e_source_get_uid (source);
 
1537
 
 
1538
        e_source_authenticator_get_prompt_strings (
 
1539
                auth, source,
 
1540
                &prompt_title,
 
1541
                &prompt_message,
 
1542
                &prompt_description);
 
1543
 
 
1544
        success = e_dbus_source_manager_call_authenticate_sync (
 
1545
                registry->priv->dbus_source_manager, uid,
 
1546
                prompt_title, prompt_message, prompt_description,
 
1547
                out_object_path, cancellable, error);
 
1548
 
 
1549
        g_free (prompt_title);
 
1550
        g_free (prompt_message);
 
1551
        g_free (prompt_description);
 
1552
 
 
1553
        g_object_unref (source);
 
1554
 
 
1555
        return success;
 
1556
}
 
1557
 
 
1558
/**
 
1559
 * e_source_registry_authenticate_sync:
 
1560
 * @registry: an #ESourceRegistry
 
1561
 * @source: an #ESource
 
1562
 * @auth: an #ESourceAuthenticator
 
1563
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 
1564
 * @error: return location for a #GError, or %NULL
 
1565
 *
 
1566
 * Authenticates @source, using @auth to handle the authentication
 
1567
 * attempts.  The operation loops until authentication is successful or
 
1568
 * the user aborts further authentication attempts.  If an error occurs,
 
1569
 * the function will set @error and return %FALSE.
 
1570
 *
 
1571
 * Note that @source need not have a #GDBusObject, which means this
 
1572
 * function can test authentication on a scratch #ESource.
 
1573
 *
 
1574
 * Only backend implementations and data source editors should call this
 
1575
 * function.  The intent is for basic client applications to not have to
 
1576
 * deal with authentication at all.
 
1577
 *
 
1578
 * Returns: %TRUE on success, %FALSE on failure
 
1579
 *
 
1580
 * Since: 3.6
 
1581
 **/
 
1582
gboolean
 
1583
e_source_registry_authenticate_sync (ESourceRegistry *registry,
 
1584
                                     ESource *source,
 
1585
                                     ESourceAuthenticator *auth,
 
1586
                                     GCancellable *cancellable,
 
1587
                                     GError **error)
 
1588
{
 
1589
        AuthContext *auth_context;
 
1590
        GMainContext *main_context;
 
1591
        EDBusAuthenticator *dbus_auth;
 
1592
        gchar *encryption_key;
 
1593
        gchar *object_path = NULL;
 
1594
        gboolean success;
 
1595
 
 
1596
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
 
1597
        g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
 
1598
        g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth), FALSE);
 
1599
 
 
1600
        /* This extracts authentication prompt details for the ESource
 
1601
         * before initiating an authentication session with the server,
 
1602
         * so split it out of the main algorithm for clarity's sake. */
 
1603
        success = source_registry_call_authenticate_for_source (
 
1604
                registry, auth, source, &object_path, cancellable, error);
 
1605
 
 
1606
        if (!success) {
 
1607
                g_warn_if_fail (object_path == NULL);
 
1608
                return FALSE;
 
1609
        }
 
1610
 
 
1611
        g_return_val_if_fail (object_path != NULL, FALSE);
 
1612
 
 
1613
        main_context = g_main_context_new ();
 
1614
        g_main_context_push_thread_default (main_context);
 
1615
 
 
1616
        dbus_auth = e_dbus_authenticator_proxy_new_for_bus_sync (
 
1617
                G_BUS_TYPE_SESSION,
 
1618
                G_DBUS_PROXY_FLAGS_NONE,
 
1619
                SOURCES_DBUS_SERVICE_NAME,
 
1620
                object_path, cancellable, error);
 
1621
 
 
1622
        g_free (object_path);
 
1623
 
 
1624
        if (dbus_auth == NULL) {
 
1625
                success = FALSE;
 
1626
                goto exit;
 
1627
        }
 
1628
 
 
1629
        auth_context = g_slice_new0 (AuthContext);
 
1630
        auth_context->auth = g_object_ref (auth);
 
1631
        auth_context->dbus_auth = dbus_auth;  /* takes ownership */
 
1632
        auth_context->main_loop = g_main_loop_new (main_context, FALSE);
 
1633
        auth_context->error = error;
 
1634
 
 
1635
        /* This just needs to be something other than
 
1636
         * E_SOURCE_AUTHENTICATION_ERROR so we don't trip
 
1637
         * up source_registry_authenticate_dismissed_cb(). */
 
1638
        auth_context->auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
 
1639
 
 
1640
        if (G_IS_CANCELLABLE (cancellable))
 
1641
                auth_context->cancellable = g_object_ref (cancellable);
 
1642
 
 
1643
        auth_context->secret_exchange =
 
1644
                gcr_secret_exchange_new (GCR_SECRET_EXCHANGE_PROTOCOL_1);
 
1645
 
 
1646
        g_signal_connect (
 
1647
                dbus_auth, "authenticate",
 
1648
                G_CALLBACK (source_registry_authenticate_authenticate_cb),
 
1649
                auth_context);
 
1650
 
 
1651
        g_signal_connect (
 
1652
                dbus_auth, "dismissed",
 
1653
                G_CALLBACK (source_registry_authenticate_dismissed_cb),
 
1654
                auth_context);
 
1655
 
 
1656
        encryption_key = gcr_secret_exchange_begin (
 
1657
                auth_context->secret_exchange);
 
1658
 
 
1659
        /* Signal the D-Bus server that we're ready to begin the
 
1660
         * authentication session.  This must happen AFTER we've
 
1661
         * connected to the response signal since the server may
 
1662
         * already have a response ready and waiting for us. */
 
1663
        success = e_dbus_authenticator_call_ready_sync (
 
1664
                dbus_auth, encryption_key, cancellable, error);
 
1665
 
 
1666
        g_free (encryption_key);
 
1667
 
 
1668
        if (success) {
 
1669
                g_main_loop_run (auth_context->main_loop);
 
1670
                success = auth_context->success;
 
1671
        }
 
1672
 
 
1673
        auth_context_free (auth_context);
 
1674
 
 
1675
exit:
 
1676
        g_main_context_pop_thread_default (main_context);
 
1677
        g_main_context_unref (main_context);
 
1678
 
 
1679
        return success;
 
1680
}
 
1681
 
 
1682
/**
 
1683
 * e_source_registry_authenticate:
 
1684
 * @registry: an #ESourceRegistry
 
1685
 * @source: an #ESource
 
1686
 * @auth: an #ESourceAuthenticator
 
1687
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 
1688
 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
 
1689
 *            is satisfied
 
1690
 * @user_data: (closure): data to pass to the callback function
 
1691
 *
 
1692
 * Asynchronously authenticates @source, using @auth to handle the
 
1693
 * authentication attempts.  The operation loops until authentication
 
1694
 * is successful or the user aborts further authentication attempts.
 
1695
 *
 
1696
 * Note that @source need not have a #GDBusObject, which means this
 
1697
 * function can test authentication on a scratch #ESource.
 
1698
 *
 
1699
 * When the operation is finished, @callback will be called.  You can then
 
1700
 * call e_source_registry_authenticate_finish() to get the result of the
 
1701
 * operation.
 
1702
 *
 
1703
 * Only backend implementations and data source editors should call this
 
1704
 * function.  The intent is for basic client applications to not have to
 
1705
 * deal with authentication at all.
 
1706
 *
 
1707
 * Since: 3.6
 
1708
 **/
 
1709
void
 
1710
e_source_registry_authenticate (ESourceRegistry *registry,
 
1711
                                ESource *source,
 
1712
                                ESourceAuthenticator *auth,
 
1713
                                GCancellable *cancellable,
 
1714
                                GAsyncReadyCallback callback,
 
1715
                                gpointer user_data)
 
1716
{
 
1717
        GSimpleAsyncResult *simple;
 
1718
        AsyncContext *async_context;
 
1719
 
 
1720
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
1721
        g_return_if_fail (E_IS_SOURCE (source));
 
1722
        g_return_if_fail (E_IS_SOURCE_AUTHENTICATOR (auth));
 
1723
 
 
1724
        async_context = g_slice_new0 (AsyncContext);
 
1725
        async_context->source = g_object_ref (source);
 
1726
        async_context->auth = g_object_ref (auth);
 
1727
 
 
1728
        simple = g_simple_async_result_new (
 
1729
                G_OBJECT (registry), callback, user_data,
 
1730
                e_source_registry_authenticate);
 
1731
 
 
1732
        g_simple_async_result_set_check_cancellable (simple, cancellable);
 
1733
 
 
1734
        g_simple_async_result_set_op_res_gpointer (
 
1735
                simple, async_context, (GDestroyNotify) async_context_free);
 
1736
 
 
1737
        g_simple_async_result_run_in_thread (
 
1738
                simple, source_registry_authenticate_thread,
 
1739
                G_PRIORITY_DEFAULT, cancellable);
 
1740
 
 
1741
        g_object_unref (simple);
 
1742
}
 
1743
 
 
1744
/**
 
1745
 * e_source_registry_authenticate_finish:
 
1746
 * @registry: an #ESourceRegistry
 
1747
 * @result: a #GAsyncResult
 
1748
 * @error: return location for a #GError, or %NULL
 
1749
 *
 
1750
 * Finishes the operation started with e_source_registry_authenticate().
 
1751
 * If an error occurred, the function will set @error and return %FALSE.
 
1752
 *
 
1753
 * Returns: %TRUE on success, %FALSE on failure
 
1754
 *
 
1755
 * Since: 3.6
 
1756
 **/
 
1757
gboolean
 
1758
e_source_registry_authenticate_finish (ESourceRegistry *registry,
 
1759
                                       GAsyncResult *result,
 
1760
                                       GError **error)
 
1761
{
 
1762
        GSimpleAsyncResult *simple;
 
1763
 
 
1764
        g_return_val_if_fail (
 
1765
                g_simple_async_result_is_valid (
 
1766
                result, G_OBJECT (registry),
 
1767
                e_source_registry_authenticate), FALSE);
 
1768
 
 
1769
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
1770
 
 
1771
        /* Assume success unless a GError is set. */
 
1772
        return !g_simple_async_result_propagate_error (simple, error);
 
1773
}
 
1774
 
 
1775
/* Helper for e_source_registry_commit_source() */
 
1776
static void
 
1777
source_registry_commit_source_thread (GSimpleAsyncResult *simple,
 
1778
                                      GObject *object,
 
1779
                                      GCancellable *cancellable)
 
1780
{
 
1781
        AsyncContext *async_context;
 
1782
        GError *error = NULL;
 
1783
 
 
1784
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
1785
 
 
1786
        e_source_registry_commit_source_sync (
 
1787
                E_SOURCE_REGISTRY (object),
 
1788
                async_context->source,
 
1789
                cancellable, &error);
 
1790
 
 
1791
        if (error != NULL)
 
1792
                g_simple_async_result_take_error (simple, error);
 
1793
}
 
1794
 
 
1795
/**
 
1796
 * e_source_registry_commit_source_sync:
 
1797
 * @registry: an #ESourceRegistry
 
1798
 * @source: an #ESource with changes to commit
 
1799
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 
1800
 * @error: return location for #GError, or %NULL
 
1801
 *
 
1802
 * This is a convenience function intended for use with graphical
 
1803
 * #ESource editors.  Call this function when the user is finished
 
1804
 * making changes to @source.
 
1805
 *
 
1806
 * If @source has a #GDBusObject, its contents are submitted to the D-Bus
 
1807
 * service through e_source_write_sync().
 
1808
 *
 
1809
 * If @source does NOT have a #GDBusObject (implying it's a scratch
 
1810
 * #ESource), its contents are submitted to the D-Bus service through
 
1811
 * e_source_registry_create_sources_sync().
 
1812
 *
 
1813
 * If an error occurs, the function will set @error and return %FALSE.
 
1814
 *
 
1815
 * Returns: %TRUE on success, %FALSE on failure
 
1816
 *
 
1817
 * Since: 3.6
 
1818
 **/
 
1819
gboolean
 
1820
e_source_registry_commit_source_sync (ESourceRegistry *registry,
 
1821
                                      ESource *source,
 
1822
                                      GCancellable *cancellable,
 
1823
                                      GError **error)
 
1824
{
 
1825
        GDBusObject *dbus_object;
 
1826
        gboolean success;
 
1827
 
 
1828
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
 
1829
        g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
 
1830
 
 
1831
        dbus_object = e_source_ref_dbus_object (source);
 
1832
 
 
1833
        if (dbus_object != NULL) {
 
1834
                success = e_source_write_sync (source, cancellable, error);
 
1835
                g_object_unref (dbus_object);
 
1836
        } else {
 
1837
                GList *list = g_list_prepend (NULL, source);
 
1838
                success = e_source_registry_create_sources_sync (
 
1839
                        registry, list, cancellable, error);
 
1840
                g_list_free (list);
 
1841
        }
 
1842
 
 
1843
        return success;
 
1844
}
 
1845
 
 
1846
/**
 
1847
 * e_source_registry_commit_source:
 
1848
 * @registry: an #ESourceRegistry
 
1849
 * @source: an #ESource with changes to commit
 
1850
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 
1851
 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
 
1852
 *            is satisfied
 
1853
 * @user_data: (closure): data to pass to the callback function
 
1854
 *
 
1855
 * See e_source_registry_commit_source_sync() for details.
 
1856
 *
 
1857
 * When the operation is finished, @callback will be called.  You can then
 
1858
 * call e_source_registry_commit_source_finish() to get the result of the
 
1859
 * operation.
 
1860
 *
 
1861
 * Since: 3.6
 
1862
 **/
 
1863
void
 
1864
e_source_registry_commit_source (ESourceRegistry *registry,
 
1865
                                 ESource *source,
 
1866
                                 GCancellable *cancellable,
 
1867
                                 GAsyncReadyCallback callback,
 
1868
                                 gpointer user_data)
 
1869
{
 
1870
        GSimpleAsyncResult *simple;
 
1871
        AsyncContext *async_context;
 
1872
 
 
1873
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
1874
        g_return_if_fail (E_IS_SOURCE (source));
 
1875
 
 
1876
        async_context = g_slice_new0 (AsyncContext);
 
1877
        async_context->source = g_object_ref (source);
 
1878
 
 
1879
        simple = g_simple_async_result_new (
 
1880
                G_OBJECT (registry), callback, user_data,
 
1881
                e_source_registry_commit_source);
 
1882
 
 
1883
        g_simple_async_result_set_check_cancellable (simple, cancellable);
 
1884
 
 
1885
        g_simple_async_result_set_op_res_gpointer (
 
1886
                simple, async_context, (GDestroyNotify) async_context_free);
 
1887
 
 
1888
        g_simple_async_result_run_in_thread (
 
1889
                simple, source_registry_commit_source_thread,
 
1890
                G_PRIORITY_DEFAULT, cancellable);
 
1891
 
 
1892
        g_object_unref (simple);
 
1893
}
 
1894
 
 
1895
/**
 
1896
 * e_source_registry_commit_source_finish:
 
1897
 * @registry: an #ESourceRegistry
 
1898
 * @result: a #GAsyncResult
 
1899
 * @error: return location for a #GError, or %NULL
 
1900
 *
 
1901
 * Finishes the operation started with e_source_registry_commit_source().
 
1902
 *
 
1903
 * If an error occurred, the function will set @error and return %FALSE.
 
1904
 *
 
1905
 * Returns: %TRUE on success, %FALSE on failure
 
1906
 *
 
1907
 * Since: 3.6
 
1908
 **/
 
1909
gboolean
 
1910
e_source_registry_commit_source_finish (ESourceRegistry *registry,
 
1911
                                        GAsyncResult *result,
 
1912
                                        GError **error)
 
1913
{
 
1914
        GSimpleAsyncResult *simple;
 
1915
 
 
1916
        g_return_val_if_fail (
 
1917
                g_simple_async_result_is_valid (
 
1918
                result, G_OBJECT (registry),
 
1919
                e_source_registry_commit_source), FALSE);
 
1920
 
 
1921
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
1922
 
 
1923
        /* Assume success unless a GError is set. */
 
1924
        return !g_simple_async_result_propagate_error (simple, error);
 
1925
}
 
1926
 
 
1927
/* Helper for e_source_registry_create_sources() */
 
1928
static void
 
1929
source_registry_create_sources_thread (GSimpleAsyncResult *simple,
 
1930
                                       GObject *object,
 
1931
                                       GCancellable *cancellable)
 
1932
{
 
1933
        AsyncContext *async_context;
 
1934
        GError *error = NULL;
 
1935
 
 
1936
        async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
1937
 
 
1938
        e_source_registry_create_sources_sync (
 
1939
                E_SOURCE_REGISTRY (object),
 
1940
                async_context->list_of_sources,
 
1941
                cancellable, &error);
 
1942
 
 
1943
        if (error != NULL)
 
1944
                g_simple_async_result_take_error (simple, error);
 
1945
}
 
1946
 
 
1947
/**
 
1948
 * e_source_registry_create_sources_sync:
 
1949
 * @registry: an #ESourceRegistry
 
1950
 * @list_of_sources: (element-type ESource): a list of #ESource instances with
 
1951
 * no #GDBusObject
 
1952
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 
1953
 * @error: return location for a #GError, or %NULL
 
1954
 *
 
1955
 * Requests the D-Bus service create new key files for each #ESource in
 
1956
 * @list_of_sources.  Each list element must be a scratch #ESource with
 
1957
 * no #GDBusObject.
 
1958
 *
 
1959
 * If an error occurs, the function will set @error and return %FALSE.
 
1960
 *
 
1961
 * Returns: %TRUE on success, %FALSE on failure
 
1962
 *
 
1963
 * Since: 3.6
 
1964
 **/
 
1965
gboolean
 
1966
e_source_registry_create_sources_sync (ESourceRegistry *registry,
 
1967
                                       GList *list_of_sources,
 
1968
                                       GCancellable *cancellable,
 
1969
                                       GError **error)
 
1970
{
 
1971
        GVariantBuilder builder;
 
1972
        GVariant *variant;
 
1973
        GList *link;
 
1974
        gboolean success;
 
1975
 
 
1976
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
 
1977
 
 
1978
        /* Verify the list elements are all ESources. */
 
1979
        for (link = list_of_sources; link != NULL; link = g_list_next (link))
 
1980
                g_return_val_if_fail (E_IS_SOURCE (link->data), FALSE);
 
1981
 
 
1982
        g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
 
1983
 
 
1984
        for (link = list_of_sources; link != NULL; link = g_list_next (link)) {
 
1985
                ESource *source;
 
1986
                const gchar *uid;
 
1987
                gchar *source_data;
 
1988
 
 
1989
                source = E_SOURCE (link->data);
 
1990
                uid = e_source_get_uid (source);
 
1991
 
 
1992
                source_data = e_source_to_string (source, NULL);
 
1993
                g_variant_builder_add (&builder, "{ss}", uid, source_data);
 
1994
                g_free (source_data);
 
1995
        }
 
1996
 
 
1997
        variant = g_variant_builder_end (&builder);
 
1998
 
 
1999
        /* This function sinks the floating GVariant reference. */
 
2000
        success = e_dbus_source_manager_call_create_sources_sync (
 
2001
                registry->priv->dbus_source_manager,
 
2002
                variant, cancellable, error);
 
2003
 
 
2004
        g_variant_builder_clear (&builder);
 
2005
 
 
2006
        return success;
 
2007
}
 
2008
 
 
2009
/**
 
2010
 * e_source_registry_create_sources:
 
2011
 * @registry: an #ESourceRegistry
 
2012
 * @list_of_sources: (element-type ESource): a list of #ESource instances with
 
2013
 * no #GDBusObject
 
2014
 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
 
2015
 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
 
2016
 *            is satisfied
 
2017
 * @user_data: (closure): data to pass to the callback function
 
2018
 *
 
2019
 * Asynchronously requests the D-Bus service create new key files for each
 
2020
 * #ESource in @list_of_sources.  Each list element must be a scratch
 
2021
 * #ESource with no #GDBusObject.
 
2022
 *
 
2023
 * When the operation is finished, @callback will be called.  You can then
 
2024
 * call e_source_registry_create_sources_finish() to get the result of the
 
2025
 * operation.
 
2026
 *
 
2027
 * Since: 3.6
 
2028
 **/
 
2029
void
 
2030
e_source_registry_create_sources (ESourceRegistry *registry,
 
2031
                                  GList *list_of_sources,
 
2032
                                  GCancellable *cancellable,
 
2033
                                  GAsyncReadyCallback callback,
 
2034
                                  gpointer user_data)
 
2035
{
 
2036
        GSimpleAsyncResult *simple;
 
2037
        AsyncContext *async_context;
 
2038
        GList *link;
 
2039
 
 
2040
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
2041
 
 
2042
        /* Verify the list elements are all ESources. */
 
2043
        for (link = list_of_sources; link != NULL; link = g_list_next (link))
 
2044
                g_return_if_fail (E_IS_SOURCE (link->data));
 
2045
 
 
2046
        async_context = g_slice_new0 (AsyncContext);
 
2047
        async_context->list_of_sources = g_list_copy (list_of_sources);
 
2048
 
 
2049
        g_list_foreach (
 
2050
                async_context->list_of_sources,
 
2051
                (GFunc) g_object_ref, NULL);
 
2052
 
 
2053
        simple = g_simple_async_result_new (
 
2054
                G_OBJECT (registry), callback, user_data,
 
2055
                e_source_registry_create_sources);
 
2056
 
 
2057
        g_simple_async_result_set_check_cancellable (simple, cancellable);
 
2058
 
 
2059
        g_simple_async_result_set_op_res_gpointer (
 
2060
                simple, async_context, (GDestroyNotify) async_context_free);
 
2061
 
 
2062
        g_simple_async_result_run_in_thread (
 
2063
                simple, source_registry_create_sources_thread,
 
2064
                G_PRIORITY_DEFAULT, cancellable);
 
2065
 
 
2066
        g_object_unref (simple);
 
2067
}
 
2068
 
 
2069
/**
 
2070
 * e_source_registry_create_sources_finish:
 
2071
 * @registry: an #ESourceRegistry
 
2072
 * @result: a #GAsyncResult
 
2073
 * @error: return location for a #GError, or %NULL
 
2074
 *
 
2075
 * Finishes the operation started with e_source_registry_create_sources().
 
2076
 *
 
2077
 * If an error occurred, the function will set @error and return %FALSE.
 
2078
 *
 
2079
 * Returns: %TRUE on success, %FALSE on failure
 
2080
 *
 
2081
 * Since: 3.6
 
2082
 **/
 
2083
gboolean
 
2084
e_source_registry_create_sources_finish (ESourceRegistry *registry,
 
2085
                                         GAsyncResult *result,
 
2086
                                         GError **error)
 
2087
{
 
2088
        GSimpleAsyncResult *simple;
 
2089
 
 
2090
        g_return_val_if_fail (
 
2091
                g_simple_async_result_is_valid (
 
2092
                result, G_OBJECT (registry),
 
2093
                e_source_registry_create_sources), FALSE);
 
2094
 
 
2095
        simple = G_SIMPLE_ASYNC_RESULT (result);
 
2096
 
 
2097
        /* Assume success unless a GError is set. */
 
2098
        return !g_simple_async_result_propagate_error (simple, error);
 
2099
}
 
2100
 
 
2101
/**
 
2102
 * e_source_registry_ref_source:
 
2103
 * @registry: an #ESourceRegistry
 
2104
 * @uid: a unique identifier string
 
2105
 *
 
2106
 * Looks up an #ESource in @registry by its unique identifier string.
 
2107
 *
 
2108
 * The returned #ESource is referenced for thread-safety and must be
 
2109
 * unreferenced with g_object_unref() when finished with it.
 
2110
 *
 
2111
 * Returns: (transfer full): an #ESource, or %NULL if no match was found
 
2112
 *
 
2113
 * Since: 3.6
 
2114
 **/
 
2115
ESource *
 
2116
e_source_registry_ref_source (ESourceRegistry *registry,
 
2117
                              const gchar *uid)
 
2118
{
 
2119
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2120
        g_return_val_if_fail (uid != NULL, NULL);
 
2121
 
 
2122
        return source_registry_sources_lookup (registry, uid);
 
2123
}
 
2124
 
 
2125
/**
 
2126
 * e_source_registry_list_sources:
 
2127
 * @registry: an #ESourceRegistry
 
2128
 * @extension_name: (allow-none): an extension name, or %NULL
 
2129
 *
 
2130
 * Returns a list of registered sources, sorted by display name.  If
 
2131
 * @extension_name is given, restrict the list to sources having that
 
2132
 * extension name.
 
2133
 *
 
2134
 * The sources returned in the list are referenced for thread-safety.
 
2135
 * They must each be unreferenced with g_object_unref() when finished
 
2136
 * when them.  Free the returned list itself with g_list_free().
 
2137
 *
 
2138
 * An easy way to free the list properly in one step is as follows:
 
2139
 *
 
2140
 * |[
 
2141
 *   g_list_free_full (list, g_object_unref);
 
2142
 * ]|
 
2143
 *
 
2144
 * Returns: (element-type ESource) (transfer full): a sorted list of sources
 
2145
 *
 
2146
 * Since: 3.6
 
2147
 **/
 
2148
GList *
 
2149
e_source_registry_list_sources (ESourceRegistry *registry,
 
2150
                                const gchar *extension_name)
 
2151
{
 
2152
        GList *list, *link;
 
2153
        GQueue trash = G_QUEUE_INIT;
 
2154
 
 
2155
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2156
 
 
2157
        list = g_list_sort (
 
2158
                source_registry_sources_get_values (registry),
 
2159
                (GCompareFunc) e_source_compare_by_display_name);
 
2160
 
 
2161
        if (extension_name == NULL)
 
2162
                return list;
 
2163
 
 
2164
        for (link = list; link != NULL; link = g_list_next (link)) {
 
2165
                ESource *source = E_SOURCE (link->data);
 
2166
 
 
2167
                if (!e_source_has_extension (source, extension_name)) {
 
2168
                        g_queue_push_tail (&trash, link);
 
2169
                        g_object_unref (source);
 
2170
                }
 
2171
        }
 
2172
 
 
2173
        /* We do want pop_head() here, not pop_head_link(). */
 
2174
        while ((link = g_queue_pop_head (&trash)) != NULL)
 
2175
                list = g_list_delete_link (list, link);
 
2176
 
 
2177
        return list;
 
2178
}
 
2179
 
 
2180
/**
 
2181
 * e_source_registry_find_extension:
 
2182
 * @registry: an #ESourceRegistry
 
2183
 * @source: an #ESource
 
2184
 * @extension_name: the extension name to find
 
2185
 *
 
2186
 * Examines @source and its ancestors and returns the "deepest" #ESource
 
2187
 * having an #ESourceExtension with the given @extension_name.  If neither
 
2188
 * @source nor any of its ancestors have such an extension, the function
 
2189
 * returns %NULL.
 
2190
 *
 
2191
 * This function is useful in cases when an #ESourceExtension is meant to
 
2192
 * apply to both the #ESource it belongs to and the #ESource's descendants.
 
2193
 *
 
2194
 * A common example is the #ESourceCollection extension, where descendants
 
2195
 * of an #ESource having an #ESourceCollection extension are implied to be
 
2196
 * members of that collection.  In that example, this function can be used
 
2197
 * to test whether @source is a member of a collection.
 
2198
 *
 
2199
 * The returned #ESource is referenced for thread-safety and must be
 
2200
 * unreferenced with g_object_unref() when finished with it.
 
2201
 *
 
2202
 * Note the function returns the #ESource containing the #ESourceExtension
 
2203
 * instead of the #ESourceExtension itself because extension instances are
 
2204
 * not to be referenced directly (see e_source_get_extension()).
 
2205
 *
 
2206
 * Returns: (transfer full): an #ESource, or %NULL if no match was found
 
2207
 *
 
2208
 * Since: 3.6
 
2209
 **/
 
2210
ESource *
 
2211
e_source_registry_find_extension (ESourceRegistry *registry,
 
2212
                                  ESource *source,
 
2213
                                  const gchar *extension_name)
 
2214
{
 
2215
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2216
        g_return_val_if_fail (E_IS_SOURCE (source), NULL);
 
2217
        g_return_val_if_fail (extension_name != NULL, NULL);
 
2218
 
 
2219
        g_object_ref (source);
 
2220
 
 
2221
        while (!e_source_has_extension (source, extension_name)) {
 
2222
                gchar *uid;
 
2223
 
 
2224
                uid = e_source_dup_parent (source);
 
2225
 
 
2226
                g_object_unref (source);
 
2227
                source = NULL;
 
2228
 
 
2229
                if (uid != NULL) {
 
2230
                        source = e_source_registry_ref_source (registry, uid);
 
2231
                        g_free (uid);
 
2232
                }
 
2233
 
 
2234
                if (source == NULL)
 
2235
                        break;
 
2236
        }
 
2237
 
 
2238
        return source;
 
2239
}
 
2240
 
 
2241
/* Helper for e_source_registry_build_display_tree() */
 
2242
static gint
 
2243
source_registry_compare_nodes (GNode *node_a,
 
2244
                               GNode *node_b)
 
2245
{
 
2246
        ESource *source_a = E_SOURCE (node_a->data);
 
2247
        ESource *source_b = E_SOURCE (node_b->data);
 
2248
        const gchar *uid_a, *uid_b;
 
2249
 
 
2250
        uid_a = e_source_get_uid (source_a);
 
2251
        uid_b = e_source_get_uid (source_b);
 
2252
 
 
2253
        /* Sanity check, with runtime warnings. */
 
2254
        if (uid_a == NULL) {
 
2255
                g_warn_if_reached ();
 
2256
                uid_a = "";
 
2257
        }
 
2258
        if (uid_b == NULL) {
 
2259
                g_warn_if_reached ();
 
2260
                uid_b = "";
 
2261
        }
 
2262
 
 
2263
        /* The built-in "local-stub" source comes first at depth 1. */
 
2264
 
 
2265
        if (g_strcmp0 (uid_a, "local-stub") == 0)
 
2266
                return -1;
 
2267
 
 
2268
        if (g_strcmp0 (uid_b, "local-stub") == 0)
 
2269
                return 1;
 
2270
 
 
2271
        /* The built-in "system-*" sources come first at depth 2. */
 
2272
 
 
2273
        if (g_str_has_prefix (uid_a, "system-"))
 
2274
                return -1;
 
2275
 
 
2276
        if (g_str_has_prefix (uid_b, "system-"))
 
2277
                return 1;
 
2278
 
 
2279
        return e_source_compare_by_display_name (source_a, source_b);
 
2280
}
 
2281
 
 
2282
/* Helper for e_source_registry_build_display_tree() */
 
2283
static gboolean
 
2284
source_registry_prune_nodes (GNode *node,
 
2285
                             const gchar *extension_name)
 
2286
{
 
2287
        GQueue queue = G_QUEUE_INIT;
 
2288
        GNode *child_node;
 
2289
 
 
2290
        /* Unlink all the child nodes and place them in a queue. */
 
2291
        while ((child_node = g_node_first_child (node)) != NULL) {
 
2292
                g_node_unlink (child_node);
 
2293
                g_queue_push_tail (&queue, child_node);
 
2294
        }
 
2295
 
 
2296
        /* Sort the queue by source name. */
 
2297
        g_queue_sort (
 
2298
                &queue, (GCompareDataFunc)
 
2299
                source_registry_compare_nodes, NULL);
 
2300
 
 
2301
        /* Pop nodes off the head of the queue until the queue is empty.
 
2302
         * If the node has either its own children or the given extension
 
2303
         * name, put it back under the parent node (preserving the sorted
 
2304
         * order).  Otherwise delete the node and its descendants. */
 
2305
        while ((child_node = g_queue_pop_head (&queue)) != NULL) {
 
2306
                ESource *child = E_SOURCE (child_node->data);
 
2307
                gboolean append_child_node = FALSE;
 
2308
 
 
2309
                if (extension_name == NULL)
 
2310
                        append_child_node = e_source_get_enabled (child);
 
2311
 
 
2312
                else if (e_source_has_extension (child, extension_name))
 
2313
                        append_child_node = e_source_get_enabled (child);
 
2314
 
 
2315
                else if (g_node_first_child (child_node) != NULL)
 
2316
                        append_child_node = e_source_get_enabled (child);
 
2317
 
 
2318
                if (append_child_node)
 
2319
                        g_node_append (node, child_node);
 
2320
                else
 
2321
                        e_source_registry_free_display_tree (child_node);
 
2322
        }
 
2323
 
 
2324
        return FALSE;
 
2325
}
 
2326
 
 
2327
/**
 
2328
 * e_source_registry_build_display_tree:
 
2329
 * @registry: an #ESourceRegistry
 
2330
 * @extension_name: (allow-none): an extension name, or %NULL
 
2331
 *
 
2332
 * Returns a single #GNode tree of registered sources that can be used to
 
2333
 * populate a #GtkTreeModel.  (The root #GNode is just an empty placeholder.)
 
2334
 *
 
2335
 * Similar to e_source_registry_list_sources(), an @extension_name can be
 
2336
 * given to restrict the tree to sources having that extension name.  Parents
 
2337
 * of matched sources are included in the tree regardless of whether they have
 
2338
 * an extension named @extension_name.
 
2339
 *
 
2340
 * Disabled leaf nodes are automatically excluded from the #GNode tree.
 
2341
 *
 
2342
 * The sources returned in the tree are referenced for thread-safety.
 
2343
 * They must each be unreferenced with g_object_unref() when finished
 
2344
 * with them.  Free the returned tree itself with g_node_destroy().
 
2345
 * For convenience, e_source_registry_free_display_tree() does all
 
2346
 * that in one step.
 
2347
 *
 
2348
 * Returns: (element-type ESource) (transfer full): a tree of sources,
 
2349
 *          arranged for display
 
2350
 *
 
2351
 * Since: 3.6
 
2352
 **/
 
2353
GNode *
 
2354
e_source_registry_build_display_tree (ESourceRegistry *registry,
 
2355
                                      const gchar *extension_name)
 
2356
{
 
2357
        GNode *root;
 
2358
 
 
2359
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2360
 
 
2361
        /* Assemble all data sources into a tree. */
 
2362
        root = source_registry_sources_build_tree (registry);
 
2363
 
 
2364
        /* Prune unwanted nodes from the copied source trees.
 
2365
         * This must be done in "post" order (children first)
 
2366
         * since it reorders and deletes child nodes. */
 
2367
        g_node_traverse (
 
2368
                root, G_POST_ORDER, G_TRAVERSE_ALL, -1,
 
2369
                (GNodeTraverseFunc) source_registry_prune_nodes,
 
2370
                (gpointer) extension_name);
 
2371
 
 
2372
        return root;
 
2373
}
 
2374
 
 
2375
/* Helper for e_source_registry_free_display_tree() */
 
2376
static void
 
2377
source_registry_unref_nodes (GNode *node)
 
2378
{
 
2379
        while (node != NULL) {
 
2380
                if (node->children != NULL)
 
2381
                        source_registry_unref_nodes (node->children);
 
2382
                if (node->data != NULL)
 
2383
                        g_object_unref (node->data);
 
2384
                node = node->next;
 
2385
        }
 
2386
}
 
2387
 
 
2388
/**
 
2389
 * e_source_registry_free_display_tree:
 
2390
 * @display_tree: a tree of sources, arranged for display
 
2391
 *
 
2392
 * Convenience function to free a #GNode tree of registered
 
2393
 * sources created by e_source_registry_build_display_tree().
 
2394
 *
 
2395
 * Since: 3.6
 
2396
 **/
 
2397
void
 
2398
e_source_registry_free_display_tree (GNode *display_tree)
 
2399
{
 
2400
        g_return_if_fail (display_tree != NULL);
 
2401
 
 
2402
        /* XXX This would be easier if GLib had something like
 
2403
         *     g_node_destroy_full() which took a GDestroyNotify.
 
2404
         *     Then the tree would not have to be traversed twice. */
 
2405
 
 
2406
        source_registry_unref_nodes (display_tree);
 
2407
        g_node_destroy (display_tree);
 
2408
}
 
2409
 
 
2410
/* Helper for e_source_registry_debug_dump() */
 
2411
static gboolean
 
2412
source_registry_debug_dump_cb (GNode *node)
 
2413
{
 
2414
        guint ii, depth;
 
2415
 
 
2416
        /* Root node is an empty placeholder. */
 
2417
        if (G_NODE_IS_ROOT (node))
 
2418
                return FALSE;
 
2419
 
 
2420
        depth = g_node_depth (node);
 
2421
        for (ii = 2; ii < depth; ii++)
 
2422
                g_print ("    ");
 
2423
 
 
2424
        if (E_IS_SOURCE (node->data)) {
 
2425
                ESource *source = E_SOURCE (node->data);
 
2426
                g_print ("\"%s\" ", e_source_get_display_name (source));
 
2427
                g_print ("(%s)", e_source_get_uid (source));
 
2428
        }
 
2429
 
 
2430
        g_print ("\n");
 
2431
 
 
2432
        return FALSE;
 
2433
}
 
2434
 
 
2435
/**
 
2436
 * e_source_registry_debug_dump:
 
2437
 * @registry: an #ESourceRegistry
 
2438
 * @extension_name: (allow-none): an extension name, or %NULL
 
2439
 *
 
2440
 * Handy debugging function that uses e_source_registry_build_display_tree()
 
2441
 * to print a tree of registered sources to standard output.
 
2442
 *
 
2443
 * Since: 3.6
 
2444
 **/
 
2445
void
 
2446
e_source_registry_debug_dump (ESourceRegistry *registry,
 
2447
                              const gchar *extension_name)
 
2448
{
 
2449
        GNode *root;
 
2450
 
 
2451
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
2452
 
 
2453
        root = e_source_registry_build_display_tree (registry, extension_name);
 
2454
 
 
2455
        g_node_traverse (
 
2456
                root, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
 
2457
                (GNodeTraverseFunc) source_registry_debug_dump_cb, NULL);
 
2458
 
 
2459
        e_source_registry_free_display_tree (root);
 
2460
}
 
2461
 
 
2462
/**
 
2463
 * e_source_registry_ref_builtin_address_book:
 
2464
 * @registry: an #ESourceRegistry
 
2465
 *
 
2466
 * Returns the built-in address book #ESource.
 
2467
 *
 
2468
 * This #ESource is always present and makes for a safe fallback.
 
2469
 *
 
2470
 * The returned #ESource is referenced for thread-safety and must be
 
2471
 * unreferenced with g_object_unref() when finished with it.
 
2472
 *
 
2473
 * Returns: (transfer full): the built-in address book #ESource
 
2474
 *
 
2475
 * Since: 3.6
 
2476
 **/
 
2477
ESource *
 
2478
e_source_registry_ref_builtin_address_book (ESourceRegistry *registry)
 
2479
{
 
2480
        ESource *source;
 
2481
        const gchar *uid;
 
2482
 
 
2483
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2484
 
 
2485
        uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
 
2486
        source = e_source_registry_ref_source (registry, uid);
 
2487
        g_return_val_if_fail (source != NULL, NULL);
 
2488
 
 
2489
        return source;
 
2490
}
 
2491
 
 
2492
/**
 
2493
 * e_source_registry_ref_default_address_book:
 
2494
 * @registry: an #ESourceRegistry
 
2495
 *
 
2496
 * Returns the #ESource most recently passed to
 
2497
 * e_source_registry_set_default_address_book() either in this session
 
2498
 * or a previous session, or else falls back to the built-in address book.
 
2499
 *
 
2500
 * The returned #ESource is referenced for thread-safety and must be
 
2501
 * unreferenced with g_object_unref() when finished with it.
 
2502
 *
 
2503
 * Returns: (transfer full): the default address book #ESource
 
2504
 *
 
2505
 * Since: 3.6
 
2506
 **/
 
2507
ESource *
 
2508
e_source_registry_ref_default_address_book (ESourceRegistry *registry)
 
2509
{
 
2510
        const gchar *key;
 
2511
        ESource *source;
 
2512
        gchar *uid;
 
2513
 
 
2514
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2515
 
 
2516
        key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
 
2517
        uid = g_settings_get_string (registry->priv->settings, key);
 
2518
        source = e_source_registry_ref_source (registry, uid);
 
2519
        g_free (uid);
 
2520
 
 
2521
        /* The built-in source is always present. */
 
2522
        if (source == NULL)
 
2523
                source = e_source_registry_ref_builtin_address_book (registry);
 
2524
 
 
2525
        g_return_val_if_fail (E_IS_SOURCE (source), NULL);
 
2526
 
 
2527
        return source;
 
2528
}
 
2529
 
 
2530
/**
 
2531
 * e_source_registry_set_default_address_book:
 
2532
 * @registry: an #ESourceRegistry
 
2533
 * @default_source: (allow-none): an address book #ESource, or %NULL
 
2534
 *
 
2535
 * Sets @default_source as the default address book.  If @default_source
 
2536
 * is %NULL, the default address book is reset to the built-in address book.
 
2537
 * This setting will persist across sessions until changed.
 
2538
 *
 
2539
 * Since: 3.6
 
2540
 **/
 
2541
void
 
2542
e_source_registry_set_default_address_book (ESourceRegistry *registry,
 
2543
                                            ESource *default_source)
 
2544
{
 
2545
        const gchar *key;
 
2546
        const gchar *uid;
 
2547
 
 
2548
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
2549
 
 
2550
        if (default_source != NULL) {
 
2551
                g_return_if_fail (E_IS_SOURCE (default_source));
 
2552
                uid = e_source_get_uid (default_source);
 
2553
        } else {
 
2554
                uid = E_SOURCE_BUILTIN_ADDRESS_BOOK_UID;
 
2555
        }
 
2556
 
 
2557
        key = E_SETTINGS_DEFAULT_ADDRESS_BOOK_KEY;
 
2558
        g_settings_set_string (registry->priv->settings, key, uid);
 
2559
 
 
2560
        /* The GSettings::changed signal will trigger a "notify" signal
 
2561
         * from the registry, so no need to call g_object_notify() here. */
 
2562
}
 
2563
 
 
2564
/**
 
2565
 * e_source_registry_ref_builtin_calendar:
 
2566
 * @registry: an #ESourceRegistry
 
2567
 *
 
2568
 * Returns the built-in calendar #ESource.
 
2569
 *
 
2570
 * This #ESource is always present and makes for a safe fallback.
 
2571
 *
 
2572
 * The returned #ESource is referenced for thread-safety and must be
 
2573
 * unreferenced with g_object_unref() when finished with it.
 
2574
 *
 
2575
 * Returns: (transfer full): the built-in calendar #ESource
 
2576
 *
 
2577
 * Since: 3.6
 
2578
 **/
 
2579
ESource *
 
2580
e_source_registry_ref_builtin_calendar (ESourceRegistry *registry)
 
2581
{
 
2582
        ESource *source;
 
2583
        const gchar *uid;
 
2584
 
 
2585
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2586
 
 
2587
        uid = E_SOURCE_BUILTIN_CALENDAR_UID;
 
2588
        source = e_source_registry_ref_source (registry, uid);
 
2589
        g_return_val_if_fail (source != NULL, NULL);
 
2590
 
 
2591
        return source;
 
2592
}
 
2593
 
 
2594
/**
 
2595
 * e_source_registry_ref_default_calendar:
 
2596
 * @registry: an #ESourceRegistry
 
2597
 *
 
2598
 * Returns the #ESource most recently passed to
 
2599
 * e_source_registry_set_default_calendar() either in this session
 
2600
 * or a previous session, or else falls back to the built-in calendar.
 
2601
 *
 
2602
 * The returned #ESource is referenced for thread-safety and must be
 
2603
 * unreferenced with g_object_unref() when finished with it.
 
2604
 *
 
2605
 * Returns: (transfer full): the default calendar #ESource
 
2606
 *
 
2607
 * Since: 3.6
 
2608
 **/
 
2609
ESource *
 
2610
e_source_registry_ref_default_calendar (ESourceRegistry *registry)
 
2611
{
 
2612
        const gchar *key;
 
2613
        ESource *source;
 
2614
        gchar *uid;
 
2615
 
 
2616
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2617
 
 
2618
        key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
 
2619
        uid = g_settings_get_string (registry->priv->settings, key);
 
2620
        source = e_source_registry_ref_source (registry, uid);
 
2621
        g_free (uid);
 
2622
 
 
2623
        /* The built-in source is always present. */
 
2624
        if (source == NULL)
 
2625
                source = e_source_registry_ref_builtin_calendar (registry);
 
2626
 
 
2627
        g_return_val_if_fail (E_IS_SOURCE (source), NULL);
 
2628
 
 
2629
        return source;
 
2630
}
 
2631
 
 
2632
/**
 
2633
 * e_source_registry_set_default_calendar:
 
2634
 * @registry: an #ESourceRegistry
 
2635
 * @default_source: (allow-none): a calendar #ESource, or %NULL
 
2636
 *
 
2637
 * Sets @default_source as the default calendar.  If @default_source
 
2638
 * is %NULL, the default calendar is reset to the built-in calendar.
 
2639
 * This setting will persist across sessions until changed.
 
2640
 *
 
2641
 * Since: 3.6
 
2642
 **/
 
2643
void
 
2644
e_source_registry_set_default_calendar (ESourceRegistry *registry,
 
2645
                                        ESource *default_source)
 
2646
{
 
2647
        const gchar *key;
 
2648
        const gchar *uid;
 
2649
 
 
2650
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
2651
 
 
2652
        if (default_source != NULL) {
 
2653
                g_return_if_fail (E_IS_SOURCE (default_source));
 
2654
                uid = e_source_get_uid (default_source);
 
2655
        } else {
 
2656
                uid = E_SOURCE_BUILTIN_CALENDAR_UID;
 
2657
        }
 
2658
 
 
2659
        key = E_SETTINGS_DEFAULT_CALENDAR_KEY;
 
2660
        g_settings_set_string (registry->priv->settings, key, uid);
 
2661
 
 
2662
        /* The GSettings::changed signal will trigger a "notify" signal
 
2663
         * from the registry, so no need to call g_object_notify() here. */
 
2664
}
 
2665
 
 
2666
/**
 
2667
 * e_source_registry_ref_builtin_mail_account:
 
2668
 * @registry: an #ESourceRegistry
 
2669
 *
 
2670
 * Returns the built-in mail account #ESource.
 
2671
 *
 
2672
 * This #ESource is always present and makes for a safe fallback.
 
2673
 *
 
2674
 * The returned #ESource is referenced for thread-safety and must be
 
2675
 * unreferenced with g_object_unref() when finished with it.
 
2676
 *
 
2677
 * Returns: (transfer full): the built-in mail account #ESource
 
2678
 *
 
2679
 * Since: 3.6
 
2680
 **/
 
2681
ESource *
 
2682
e_source_registry_ref_builtin_mail_account (ESourceRegistry *registry)
 
2683
{
 
2684
        ESource *source;
 
2685
        const gchar *uid;
 
2686
 
 
2687
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2688
 
 
2689
        uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
 
2690
        source = e_source_registry_ref_source (registry, uid);
 
2691
        g_return_val_if_fail (source != NULL, NULL);
 
2692
 
 
2693
        return source;
 
2694
}
 
2695
 
 
2696
/**
 
2697
 * e_source_registry_ref_default_mail_account:
 
2698
 * @registry: an #ESourceRegistry
 
2699
 *
 
2700
 * Returns the #ESource most recently passed to
 
2701
 * e_source_registry_set_default_mail_account() either in this session
 
2702
 * or a previous session, or else falls back to the built-in mail account.
 
2703
 *
 
2704
 * The returned #ESource is referenced for thread-safety and must be
 
2705
 * unreferenced with g_object_unref() when finished with it.
 
2706
 *
 
2707
 * Returns: (transfer full): the default mail account #ESource
 
2708
 *
 
2709
 * Since: 3.6
 
2710
 **/
 
2711
ESource *
 
2712
e_source_registry_ref_default_mail_account (ESourceRegistry *registry)
 
2713
{
 
2714
        const gchar *key;
 
2715
        ESource *source;
 
2716
        gchar *uid;
 
2717
 
 
2718
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2719
 
 
2720
        key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
 
2721
        uid = g_settings_get_string (registry->priv->settings, key);
 
2722
        source = e_source_registry_ref_source (registry, uid);
 
2723
        g_free (uid);
 
2724
 
 
2725
        /* The built-in source is always present. */
 
2726
        if (source == NULL)
 
2727
                source = e_source_registry_ref_builtin_mail_account (registry);
 
2728
 
 
2729
        g_return_val_if_fail (E_IS_SOURCE (source), NULL);
 
2730
 
 
2731
        return source;
 
2732
}
 
2733
 
 
2734
/**
 
2735
 * e_source_registry_set_default_mail_account:
 
2736
 * @registry: an #ESourceRegistry
 
2737
 * @default_source: (allow-none): a mail account #ESource, or %NULL
 
2738
 *
 
2739
 * Sets @default_source as the default mail account.  If @default_source
 
2740
 * is %NULL, the default mail account is reset to the built-in mail account.
 
2741
 * This setting will persist across sessions until changed.
 
2742
 *
 
2743
 * Since: 3.6
 
2744
 **/
 
2745
void
 
2746
e_source_registry_set_default_mail_account (ESourceRegistry *registry,
 
2747
                                            ESource *default_source)
 
2748
{
 
2749
        const gchar *key;
 
2750
        const gchar *uid;
 
2751
 
 
2752
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
2753
 
 
2754
        if (default_source != NULL) {
 
2755
                g_return_if_fail (E_IS_SOURCE (default_source));
 
2756
                uid = e_source_get_uid (default_source);
 
2757
        } else {
 
2758
                uid = E_SOURCE_BUILTIN_MAIL_ACCOUNT_UID;
 
2759
        }
 
2760
 
 
2761
        key = E_SETTINGS_DEFAULT_MAIL_ACCOUNT_KEY;
 
2762
        g_settings_set_string (registry->priv->settings, key, uid);
 
2763
 
 
2764
        /* The GSettings::changed signal will trigger a "notify" signal
 
2765
         * from the registry, so no need to call g_object_notify() here. */
 
2766
}
 
2767
 
 
2768
/* Helper for e_source_registry_ref_default_mail_identity() */
 
2769
static ESource *
 
2770
source_registry_ref_any_mail_identity (ESourceRegistry *registry)
 
2771
{
 
2772
        ESource *source;
 
2773
        GList *list, *link;
 
2774
        const gchar *extension_name;
 
2775
        gchar *uid = NULL;
 
2776
 
 
2777
        /* First fallback: Return the mail identity named
 
2778
         *                 by the default mail account. */
 
2779
 
 
2780
        source = e_source_registry_ref_default_mail_account (registry);
 
2781
 
 
2782
        /* This should never be NULL, but just to be safe. */
 
2783
        if (source != NULL) {
 
2784
                ESourceMailAccount *extension;
 
2785
 
 
2786
                extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
 
2787
                extension = e_source_get_extension (source, extension_name);
 
2788
                uid = e_source_mail_account_dup_identity_uid (extension);
 
2789
 
 
2790
                g_object_unref (source);
 
2791
                source = NULL;
 
2792
        }
 
2793
 
 
2794
        if (uid != NULL) {
 
2795
                source = e_source_registry_ref_source (registry, uid);
 
2796
                g_free (uid);
 
2797
        }
 
2798
 
 
2799
        if (source != NULL)
 
2800
                return source;
 
2801
 
 
2802
        /* Second fallback: Pick any available mail identity,
 
2803
         *                  preferring enabled identities. */
 
2804
 
 
2805
        extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
 
2806
        list = e_source_registry_list_sources (registry, extension_name);
 
2807
 
 
2808
        for (link = list; link != NULL; link = g_list_next (link)) {
 
2809
                ESource *candidate = E_SOURCE (link->data);
 
2810
 
 
2811
                if (e_source_get_enabled (candidate)) {
 
2812
                        source = g_object_ref (candidate);
 
2813
                        break;
 
2814
                }
 
2815
        }
 
2816
 
 
2817
        if (source == NULL && list != NULL)
 
2818
                source = g_object_ref (link->data);
 
2819
 
 
2820
        g_list_free_full (list, (GDestroyNotify) g_object_unref);
 
2821
 
 
2822
        return source;
 
2823
}
 
2824
 
 
2825
/**
 
2826
 * e_source_registry_ref_default_mail_identity:
 
2827
 * @registry: an #ESourceRegistry
 
2828
 *
 
2829
 * Returns the #ESource most recently passed to
 
2830
 * e_source_registry_set_default_mail_identity() either in this session
 
2831
 * or a previous session, or else falls back to the mail identity named
 
2832
 * by the default mail account.  If even that fails it returns any mail
 
2833
 * identity from @registry, or %NULL if there are none.
 
2834
 *
 
2835
 * The returned #ESource is referenced for thread-safety and must be
 
2836
 * unreferenced with g_object_unref() when finished with it.
 
2837
 *
 
2838
 * Returns: (transfer full): the default mail identity #ESource, or %NULL
 
2839
 *
 
2840
 * Since: 3.6
 
2841
 **/
 
2842
ESource *
 
2843
e_source_registry_ref_default_mail_identity (ESourceRegistry *registry)
 
2844
{
 
2845
        const gchar *key;
 
2846
        ESource *source;
 
2847
        gchar *uid;
 
2848
 
 
2849
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2850
 
 
2851
        key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
 
2852
        uid = g_settings_get_string (registry->priv->settings, key);
 
2853
        source = e_source_registry_ref_source (registry, uid);
 
2854
        g_free (uid);
 
2855
 
 
2856
        if (source == NULL)
 
2857
                source = source_registry_ref_any_mail_identity (registry);
 
2858
 
 
2859
        return source;
 
2860
}
 
2861
 
 
2862
/**
 
2863
 * e_source_registry_set_default_mail_identity:
 
2864
 * @registry: an #ESourceRegistry
 
2865
 * @default_source: (allow-none): a mail identity #ESource, or %NULL
 
2866
 *
 
2867
 * Sets @default_source as the default mail identity.  If @default_source
 
2868
 * is %NULL, the next request for the default mail identity will use the
 
2869
 * fallbacks described in e_source_registry_get_default_mail_identity().
 
2870
 *
 
2871
 * Since: 3.6
 
2872
 **/
 
2873
void
 
2874
e_source_registry_set_default_mail_identity (ESourceRegistry *registry,
 
2875
                                             ESource *default_source)
 
2876
{
 
2877
        const gchar *key;
 
2878
        const gchar *uid;
 
2879
 
 
2880
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
2881
 
 
2882
        if (default_source != NULL) {
 
2883
                g_return_if_fail (E_IS_SOURCE (default_source));
 
2884
                uid = e_source_get_uid (default_source);
 
2885
        } else {
 
2886
                uid = "";  /* no built-in mail identity */
 
2887
        }
 
2888
 
 
2889
        key = E_SETTINGS_DEFAULT_MAIL_IDENTITY_KEY;
 
2890
        g_settings_set_string (registry->priv->settings, key, uid);
 
2891
 
 
2892
        /* The GSettings::changed signal will trigger a "notify" signal
 
2893
         * from the registry, so no need to call g_object_notify() here. */
 
2894
}
 
2895
 
 
2896
/**
 
2897
 * e_source_registry_ref_builtin_memo_list:
 
2898
 * @registry: an #ESourceRegistry
 
2899
 *
 
2900
 * Returns the built-in memo list #ESource.
 
2901
 *
 
2902
 * This #ESource is always present and makes for a safe fallback.
 
2903
 *
 
2904
 * The returned #ESource is referenced for thread-safety and must be
 
2905
 * unreferenced with g_object_unref() when finished with it.
 
2906
 *
 
2907
 * Returns: (transfer full): the built-in memo list #ESource
 
2908
 *
 
2909
 * Since: 3.6
 
2910
 **/
 
2911
ESource *
 
2912
e_source_registry_ref_builtin_memo_list (ESourceRegistry *registry)
 
2913
{
 
2914
        ESource *source;
 
2915
        const gchar *uid;
 
2916
 
 
2917
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2918
 
 
2919
        uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
 
2920
        source = e_source_registry_ref_source (registry, uid);
 
2921
        g_return_val_if_fail (source != NULL, NULL);
 
2922
 
 
2923
        return source;
 
2924
}
 
2925
 
 
2926
/**
 
2927
 * e_source_registry_ref_default_memo_list:
 
2928
 * @registry: an #ESourceRegistry
 
2929
 *
 
2930
 * Returns the #ESource most recently passed to
 
2931
 * e_source_registry_set_default_memo_list() either in this session
 
2932
 * or a previous session, or else falls back to the built-in memo list.
 
2933
 *
 
2934
 * The returned #ESource is referenced for thread-safety and must be
 
2935
 * unreferenced with g_object_unref() when finished with it.
 
2936
 *
 
2937
 * Returns: (transfer full): the default memo list #ESource
 
2938
 *
 
2939
 * Since: 3.6
 
2940
 **/
 
2941
ESource *
 
2942
e_source_registry_ref_default_memo_list (ESourceRegistry *registry)
 
2943
{
 
2944
        const gchar *key;
 
2945
        ESource *source;
 
2946
        gchar *uid;
 
2947
 
 
2948
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
2949
 
 
2950
        key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
 
2951
        uid = g_settings_get_string (registry->priv->settings, key);
 
2952
        source = e_source_registry_ref_source (registry, uid);
 
2953
        g_free (uid);
 
2954
 
 
2955
        /* The built-in source is always present. */
 
2956
        if (source == NULL)
 
2957
                source = e_source_registry_ref_builtin_memo_list (registry);
 
2958
 
 
2959
        g_return_val_if_fail (E_IS_SOURCE (source), NULL);
 
2960
 
 
2961
        return source;
 
2962
}
 
2963
 
 
2964
/**
 
2965
 * e_source_registry_set_default_memo_list:
 
2966
 * @registry: an #ESourceRegistry
 
2967
 * @default_source: (allow-none): a memo list #ESource, or %NULL
 
2968
 *
 
2969
 * Sets @default_source as the default memo list.  If @default_source
 
2970
 * is %NULL, the default memo list is reset to the built-in memo list.
 
2971
 * This setting will persist across sessions until changed.
 
2972
 *
 
2973
 * Since: 3.6
 
2974
 **/
 
2975
void
 
2976
e_source_registry_set_default_memo_list (ESourceRegistry *registry,
 
2977
                                         ESource *default_source)
 
2978
{
 
2979
        const gchar *key;
 
2980
        const gchar *uid;
 
2981
 
 
2982
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
2983
 
 
2984
        if (default_source != NULL) {
 
2985
                g_return_if_fail (E_IS_SOURCE (default_source));
 
2986
                uid = e_source_get_uid (default_source);
 
2987
        } else {
 
2988
                uid = E_SOURCE_BUILTIN_MEMO_LIST_UID;
 
2989
        }
 
2990
 
 
2991
        key = E_SETTINGS_DEFAULT_MEMO_LIST_KEY;
 
2992
        g_settings_set_string (registry->priv->settings, key, uid);
 
2993
 
 
2994
        /* The GSettings::changed signal will trigger a "notify" signal
 
2995
         * from the registry, so no need to call g_object_notify() here. */
 
2996
}
 
2997
 
 
2998
/**
 
2999
 * e_source_registry_ref_builtin_task_list:
 
3000
 * @registry: an #ESourceRegistry
 
3001
 *
 
3002
 * Returns the built-in task list #ESource.
 
3003
 *
 
3004
 * This #ESource is always present and makes for a safe fallback.
 
3005
 *
 
3006
 * The returned #ESource is referenced for thread-safety and must be
 
3007
 * unreferenced with g_object_unref() when finished with it.
 
3008
 *
 
3009
 * Returns: (transfer full): the built-in task list #ESource
 
3010
 *
 
3011
 * Since: 3.6
 
3012
 **/
 
3013
ESource *
 
3014
e_source_registry_ref_builtin_task_list (ESourceRegistry *registry)
 
3015
{
 
3016
        ESource *source;
 
3017
        const gchar *uid;
 
3018
 
 
3019
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
3020
 
 
3021
        uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
 
3022
        source = e_source_registry_ref_source (registry, uid);
 
3023
        g_return_val_if_fail (source != NULL, NULL);
 
3024
 
 
3025
        return source;
 
3026
}
 
3027
 
 
3028
/**
 
3029
 * e_source_registry_ref_default_task_list:
 
3030
 * @registry: an #ESourceRegistry
 
3031
 *
 
3032
 * Returns the #ESource most recently passed to
 
3033
 * e_source_registry_set_default_task_list() either in this session
 
3034
 * or a previous session, or else falls back to the built-in task list.
 
3035
 *
 
3036
 * The returned #ESource is referenced for thread-safety and must be
 
3037
 * unreferenced with g_object_unref() when finished with it.
 
3038
 *
 
3039
 * Returns: (transfer full): the default task list #ESource
 
3040
 *
 
3041
 * Since: 3.6
 
3042
 **/
 
3043
ESource *
 
3044
e_source_registry_ref_default_task_list (ESourceRegistry *registry)
 
3045
{
 
3046
        const gchar *key;
 
3047
        ESource *source;
 
3048
        gchar *uid;
 
3049
 
 
3050
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
3051
 
 
3052
        key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
 
3053
        uid = g_settings_get_string (registry->priv->settings, key);
 
3054
        source = e_source_registry_ref_source (registry, uid);
 
3055
        g_free (uid);
 
3056
 
 
3057
        /* The built-in source is always present. */
 
3058
        if (source == NULL)
 
3059
                source = e_source_registry_ref_builtin_task_list (registry);
 
3060
 
 
3061
        g_return_val_if_fail (E_IS_SOURCE (source), NULL);
 
3062
 
 
3063
        return source;
 
3064
}
 
3065
 
 
3066
/**
 
3067
 * e_source_registry_set_default_task_list:
 
3068
 * @registry: an #ESourceRegistry
 
3069
 * @default_source: (allow-none): a task list #ESource, or %NULL
 
3070
 *
 
3071
 * Sets @default_source as the default task list.  If @default_source
 
3072
 * is %NULL, the default task list is reset to the built-in task list.
 
3073
 * This setting will persist across sessions until changed.
 
3074
 *
 
3075
 * Since: 3.6
 
3076
 **/
 
3077
void
 
3078
e_source_registry_set_default_task_list (ESourceRegistry *registry,
 
3079
                                         ESource *default_source)
 
3080
{
 
3081
        const gchar *key;
 
3082
        const gchar *uid;
 
3083
 
 
3084
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
3085
 
 
3086
        if (default_source != NULL) {
 
3087
                g_return_if_fail (E_IS_SOURCE (default_source));
 
3088
                uid = e_source_get_uid (default_source);
 
3089
        } else {
 
3090
                uid = E_SOURCE_BUILTIN_TASK_LIST_UID;
 
3091
        }
 
3092
 
 
3093
        key = E_SETTINGS_DEFAULT_TASK_LIST_KEY;
 
3094
        g_settings_set_string (registry->priv->settings, key, uid);
 
3095
 
 
3096
        /* The GSettings::changed signal will trigger a "notify" signal
 
3097
         * from the registry, so no need to call g_object_notify() here. */
 
3098
}
 
3099
 
 
3100
/**
 
3101
 * e_source_registry_ref_default_for_extension_name:
 
3102
 * @registry: an #ESourceRegistry
 
3103
 * @extension_name: an extension_name
 
3104
 *
 
3105
 * This is a convenience function to return a default #ESource based on
 
3106
 * @extension_name.  This only works with a subset of extension names.
 
3107
 *
 
3108
 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
 
3109
 * returns the current default address book, or else falls back to the
 
3110
 * built-in address book.
 
3111
 *
 
3112
 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function returns
 
3113
 * the current default calendar, or else falls back to the built-in calendar.
 
3114
 *
 
3115
 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
 
3116
 * returns the current default mail account, or else falls back to the
 
3117
 * built-in mail account.
 
3118
 *
 
3119
 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
 
3120
 * returns the current default mail identity, or else falls back to the
 
3121
 * mail identity named by the current default mail account.
 
3122
 *
 
3123
 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function returns
 
3124
 * the current default memo list, or else falls back to the built-in memo list.
 
3125
 *
 
3126
 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function returns
 
3127
 * the current default task list, or else falls back to the built-in task list.
 
3128
 *
 
3129
 * For all other values of @extension_name, the function returns %NULL.
 
3130
 *
 
3131
 * The returned #ESource is referenced for thread-safety and must be
 
3132
 * unreferenced with g_object_unref() when finished with it.
 
3133
 *
 
3134
 * Returns: (transfer full): the default #ESource based on @extension_name
 
3135
 *
 
3136
 * Since: 3.6
 
3137
 **/
 
3138
ESource *
 
3139
e_source_registry_ref_default_for_extension_name (ESourceRegistry *registry,
 
3140
                                                  const gchar *extension_name)
 
3141
{
 
3142
        g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
 
3143
        g_return_val_if_fail (extension_name != NULL, NULL);
 
3144
 
 
3145
        if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
 
3146
                return e_source_registry_ref_default_address_book (registry);
 
3147
 
 
3148
        if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
 
3149
                return e_source_registry_ref_default_calendar (registry);
 
3150
 
 
3151
        if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
 
3152
                return e_source_registry_ref_default_mail_account (registry);
 
3153
 
 
3154
        if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
 
3155
                return e_source_registry_ref_default_mail_identity (registry);
 
3156
 
 
3157
        if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
 
3158
                return e_source_registry_ref_default_memo_list (registry);
 
3159
 
 
3160
        if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
 
3161
                return e_source_registry_ref_default_task_list (registry);
 
3162
 
 
3163
        return NULL;
 
3164
}
 
3165
 
 
3166
/**
 
3167
 * e_source_registry_set_default_for_extension_name:
 
3168
 * @registry: an #ESourceRegistry
 
3169
 * @extension_name: an extension name
 
3170
 * @default_source: (allow-none): an #ESource, or %NULL
 
3171
 *
 
3172
 * This is a convenience function to set a default #ESource based on
 
3173
 * @extension_name.  This only works with a subset of extension names.
 
3174
 *
 
3175
 * If @extension_name is #E_SOURCE_EXTENSION_ADDRESS_BOOK, the function
 
3176
 * sets @default_source as the default address book.  If @default_source
 
3177
 * is %NULL, the default address book is reset to the built-in address book.
 
3178
 *
 
3179
 * If @extension_name is #E_SOURCE_EXTENSION_CALENDAR, the function sets
 
3180
 * @default_source as the default calendar.  If @default_source is %NULL,
 
3181
 * the default calendar is reset to the built-in calendar.
 
3182
 *
 
3183
 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_ACCOUNT, the function
 
3184
 * sets @default_source as the default mail account.  If @default_source
 
3185
 * is %NULL, the default mail account is reset to the built-in mail account.
 
3186
 *
 
3187
 * If @extension_name is #E_SOURCE_EXTENSION_MAIL_IDENTITY, the function
 
3188
 * sets @default_source as the default mail identity.  If @default_source
 
3189
 * is %NULL, the next request for the default mail identity will return
 
3190
 * the mail identity named by the default mail account.
 
3191
 *
 
3192
 * If @extension_name is #E_SOURCE_EXTENSION_MEMO_LIST, the function sets
 
3193
 * @default_source as the default memo list.  If @default_source is %NULL,
 
3194
 * the default memo list is reset to the built-in memo list.
 
3195
 *
 
3196
 * If @extension_name is #E_SOURCE_EXTENSION_TASK_LIST, the function sets
 
3197
 * @default_source as the default task list.  If @default_source is %NULL,
 
3198
 * the default task list is reset to the built-in task list.
 
3199
 *
 
3200
 * For all other values of @extension_name, the function does nothing.
 
3201
 *
 
3202
 * Since: 3.6
 
3203
 **/
 
3204
void
 
3205
e_source_registry_set_default_for_extension_name (ESourceRegistry *registry,
 
3206
                                                  const gchar *extension_name,
 
3207
                                                  ESource *default_source)
 
3208
{
 
3209
        g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 
3210
        g_return_if_fail (extension_name != NULL);
 
3211
 
 
3212
        if (strcmp (extension_name, E_SOURCE_EXTENSION_ADDRESS_BOOK) == 0)
 
3213
                e_source_registry_set_default_address_book (
 
3214
                        registry, default_source);
 
3215
 
 
3216
        if (strcmp (extension_name, E_SOURCE_EXTENSION_CALENDAR) == 0)
 
3217
                e_source_registry_set_default_calendar (
 
3218
                        registry, default_source);
 
3219
 
 
3220
        if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_ACCOUNT) == 0)
 
3221
                e_source_registry_set_default_mail_account (
 
3222
                        registry, default_source);
 
3223
 
 
3224
        if (strcmp (extension_name, E_SOURCE_EXTENSION_MAIL_IDENTITY) == 0)
 
3225
                e_source_registry_set_default_mail_identity (
 
3226
                        registry, default_source);
 
3227
 
 
3228
        if (strcmp (extension_name, E_SOURCE_EXTENSION_MEMO_LIST) == 0)
 
3229
                e_source_registry_set_default_memo_list (
 
3230
                        registry, default_source);
 
3231
 
 
3232
        if (strcmp (extension_name, E_SOURCE_EXTENSION_TASK_LIST) == 0)
 
3233
                e_source_registry_set_default_task_list (
 
3234
                        registry, default_source);
 
3235
}
 
3236