Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-ebook-adapter"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <gio/gio.h>
9 : : #include <valent.h>
10 : :
11 : : #include "valent-ebook-adapter.h"
12 : : #include "valent-ebook-store.h"
13 : :
14 : :
15 : : struct _ValentEBookAdapter
16 : : {
17 : : ValentContactsAdapter parent_instance;
18 : :
19 : : ESourceRegistry *registry;
20 : : GHashTable *stores;
21 : : };
22 : :
23 : : static void g_async_initable_iface_init (GAsyncInitableIface *iface);
24 : :
25 : 0 : G_DEFINE_FINAL_TYPE_WITH_CODE (ValentEBookAdapter, valent_ebook_adapter, VALENT_TYPE_CONTACTS_ADAPTER,
26 : : G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, g_async_initable_iface_init))
27 : :
28 : :
29 : : /*
30 : : * ESourceRegistry Callbacks
31 : : */
32 : : static void
33 : 0 : g_async_initable_new_async_cb (GAsyncInitable *initable,
34 : : GAsyncResult *result,
35 : : ValentEBookAdapter *self)
36 : : {
37 : 0 : ESource *source = NULL;
38 : 0 : g_autoptr (GObject) object = NULL;
39 : 0 : g_autoptr (GError) error = NULL;
40 : :
41 : 0 : if ((object = g_async_initable_new_finish (initable, result, &error)) == NULL)
42 : : {
43 : 0 : if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
44 : 0 : g_warning ("Failed loading address book: %s", error->message);
45 : :
46 : 0 : return;
47 : : }
48 : :
49 : 0 : source = valent_contact_store_get_source (VALENT_CONTACT_STORE (object));
50 : 0 : g_hash_table_replace (self->stores,
51 : : g_object_ref (source),
52 : : g_object_ref (object));
53 : 0 : valent_contacts_adapter_store_added (VALENT_CONTACTS_ADAPTER (self),
54 : : VALENT_CONTACT_STORE (object));
55 : : }
56 : :
57 : : static void
58 : 0 : on_source_added (ESourceRegistry *registry,
59 : : ESource *source,
60 : : ValentEBookAdapter *self)
61 : : {
62 : 0 : g_autoptr (GCancellable) destroy = NULL;
63 : :
64 : 0 : g_assert (E_IS_SOURCE_REGISTRY (registry));
65 : 0 : g_assert (E_IS_SOURCE (source));
66 : 0 : g_assert (VALENT_IS_EBOOK_ADAPTER (self));
67 : :
68 : 0 : if (!e_source_has_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK))
69 : : return;
70 : :
71 : 0 : destroy = valent_object_ref_cancellable (VALENT_OBJECT (self));
72 : 0 : g_async_initable_new_async (VALENT_TYPE_EBOOK_STORE,
73 : : G_PRIORITY_DEFAULT,
74 : : destroy,
75 : : (GAsyncReadyCallback)g_async_initable_new_async_cb,
76 : : self,
77 : : "source", source,
78 : : NULL);
79 : : }
80 : :
81 : : static void
82 : 0 : on_source_removed (ESourceRegistry *registry,
83 : : ESource *source,
84 : : ValentEBookAdapter *self)
85 : : {
86 : 0 : ValentContactsAdapter *adapter = VALENT_CONTACTS_ADAPTER (self);
87 : 0 : gpointer esource, store;
88 : :
89 : 0 : g_assert (E_IS_SOURCE_REGISTRY (registry));
90 : 0 : g_assert (E_IS_SOURCE (source));
91 : 0 : g_assert (VALENT_IS_EBOOK_ADAPTER (self));
92 : :
93 : 0 : if (!e_source_has_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK))
94 : 0 : return;
95 : :
96 : 0 : if (g_hash_table_steal_extended (self->stores, source, &esource, &store))
97 : : {
98 : 0 : valent_contacts_adapter_store_removed (adapter, store);
99 : 0 : g_object_unref (esource);
100 : 0 : g_object_unref (store);
101 : : }
102 : : }
103 : :
104 : : /*
105 : : * GAsyncInitable
106 : : */
107 : : static void
108 : 0 : e_source_registry_new_cb (GObject *object,
109 : : GAsyncResult *result,
110 : : gpointer user_data)
111 : : {
112 : 0 : g_autoptr (GTask) task = G_TASK (user_data);
113 : 0 : g_autolist (ESource) sources = NULL;
114 : 0 : ValentEBookAdapter *self = g_task_get_source_object (task);
115 : 0 : g_autoptr (GError) error = NULL;
116 : :
117 : 0 : g_assert (VALENT_IS_EBOOK_ADAPTER (self));
118 : :
119 : 0 : if ((self->registry = e_source_registry_new_finish (result, &error)) == NULL)
120 : : {
121 : 0 : valent_extension_plugin_state_changed (VALENT_EXTENSION (self),
122 : : VALENT_PLUGIN_STATE_ERROR,
123 : : error);
124 : 0 : return g_task_return_error (task, g_steal_pointer (&error));
125 : : }
126 : :
127 : : /* Load existing address books */
128 : 0 : sources = e_source_registry_list_sources (self->registry,
129 : : E_SOURCE_EXTENSION_ADDRESS_BOOK);
130 : :
131 : 0 : for (const GList *iter = sources; iter; iter = iter->next)
132 : 0 : on_source_added (self->registry, E_SOURCE (iter->data), self);
133 : :
134 : 0 : g_signal_connect_object (self->registry,
135 : : "source-added",
136 : : G_CALLBACK (on_source_added),
137 : : self, 0);
138 : 0 : g_signal_connect_object (self->registry,
139 : : "source-removed",
140 : : G_CALLBACK (on_source_removed),
141 : : self, 0);
142 : :
143 : : /* Report the adapter as active */
144 : 0 : valent_extension_plugin_state_changed (VALENT_EXTENSION (self),
145 : : VALENT_PLUGIN_STATE_ACTIVE,
146 : : NULL);
147 : 0 : g_task_return_boolean (task, TRUE);
148 : : }
149 : :
150 : : static void
151 : 0 : valent_ebook_adapter_init_async (GAsyncInitable *initable,
152 : : int io_priority,
153 : : GCancellable *cancellable,
154 : : GAsyncReadyCallback callback,
155 : : gpointer user_data)
156 : : {
157 : 0 : g_autoptr (GTask) task = NULL;
158 : 0 : g_autoptr (GCancellable) destroy = NULL;
159 : :
160 : 0 : g_assert (VALENT_IS_EBOOK_ADAPTER (initable));
161 : 0 : g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
162 : :
163 : : /* Cede the primary position until complete */
164 : 0 : valent_extension_plugin_state_changed (VALENT_EXTENSION (initable),
165 : : VALENT_PLUGIN_STATE_INACTIVE,
166 : : NULL);
167 : :
168 : : /* Cancel initialization if the object is destroyed */
169 : 0 : destroy = valent_object_chain_cancellable (VALENT_OBJECT (initable),
170 : : cancellable);
171 : :
172 : 0 : task = g_task_new (initable, destroy, callback, user_data);
173 : 0 : g_task_set_priority (task, io_priority);
174 : 0 : g_task_set_source_tag (task, valent_ebook_adapter_init_async);
175 : :
176 : 0 : e_source_registry_new (destroy,
177 : : e_source_registry_new_cb,
178 : : g_steal_pointer (&task));
179 : 0 : }
180 : :
181 : : static void
182 : 0 : g_async_initable_iface_init (GAsyncInitableIface *iface)
183 : : {
184 : 0 : iface->init_async = valent_ebook_adapter_init_async;
185 : 0 : }
186 : :
187 : : /*
188 : : * ValentObject
189 : : */
190 : : static void
191 : 0 : valent_ebook_adapter_destroy (ValentObject *object)
192 : : {
193 : 0 : ValentEBookAdapter *self = VALENT_EBOOK_ADAPTER (object);
194 : :
195 : 0 : g_clear_object (&self->registry);
196 : 0 : g_hash_table_remove_all (self->stores);
197 : :
198 : 0 : VALENT_OBJECT_CLASS (valent_ebook_adapter_parent_class)->destroy (object);
199 : 0 : }
200 : :
201 : : /*
202 : : * GObject
203 : : */
204 : : static void
205 : 0 : valent_ebook_adapter_finalize (GObject *object)
206 : : {
207 : 0 : ValentEBookAdapter *self = VALENT_EBOOK_ADAPTER (object);
208 : :
209 : 0 : g_clear_pointer (&self->stores, g_hash_table_unref);
210 : :
211 : 0 : G_OBJECT_CLASS (valent_ebook_adapter_parent_class)->finalize (object);
212 : 0 : }
213 : :
214 : : static void
215 : 0 : valent_ebook_adapter_class_init (ValentEBookAdapterClass *klass)
216 : : {
217 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
218 : 0 : ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
219 : :
220 : 0 : object_class->finalize = valent_ebook_adapter_finalize;
221 : :
222 : 0 : vobject_class->destroy = valent_ebook_adapter_destroy;
223 : : }
224 : :
225 : : static void
226 : 0 : valent_ebook_adapter_init (ValentEBookAdapter *self)
227 : : {
228 : 0 : self->stores = g_hash_table_new_full ((GHashFunc)e_source_hash,
229 : : (GEqualFunc)e_source_equal,
230 : : g_object_unref,
231 : : g_object_unref);
232 : 0 : }
233 : :
|