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