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 : : /* Cancel initialization if the object is destroyed */
166 : 0 : destroy = valent_object_chain_cancellable (VALENT_OBJECT (initable),
167 : : cancellable);
168 : :
169 : 0 : task = g_task_new (initable, destroy, callback, user_data);
170 : 0 : g_task_set_priority (task, io_priority);
171 : 0 : g_task_set_source_tag (task, valent_ebook_adapter_init_async);
172 : :
173 : 0 : e_source_registry_new (destroy,
174 : : e_source_registry_new_cb,
175 : : g_steal_pointer (&task));
176 : 0 : }
177 : :
178 : : static void
179 : 0 : g_async_initable_iface_init (GAsyncInitableIface *iface)
180 : : {
181 : 0 : iface->init_async = valent_ebook_adapter_init_async;
182 : 0 : }
183 : :
184 : : /*
185 : : * ValentObject
186 : : */
187 : : static void
188 : 0 : valent_ebook_adapter_destroy (ValentObject *object)
189 : : {
190 : 0 : ValentEBookAdapter *self = VALENT_EBOOK_ADAPTER (object);
191 : :
192 : 0 : g_clear_object (&self->registry);
193 : 0 : g_hash_table_remove_all (self->stores);
194 : :
195 : 0 : VALENT_OBJECT_CLASS (valent_ebook_adapter_parent_class)->destroy (object);
196 : 0 : }
197 : :
198 : : /*
199 : : * GObject
200 : : */
201 : : static void
202 : 0 : valent_ebook_adapter_finalize (GObject *object)
203 : : {
204 : 0 : ValentEBookAdapter *self = VALENT_EBOOK_ADAPTER (object);
205 : :
206 : 0 : g_clear_pointer (&self->stores, g_hash_table_unref);
207 : :
208 : 0 : G_OBJECT_CLASS (valent_ebook_adapter_parent_class)->finalize (object);
209 : 0 : }
210 : :
211 : : static void
212 : 0 : valent_ebook_adapter_class_init (ValentEBookAdapterClass *klass)
213 : : {
214 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
215 : 0 : ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
216 : :
217 : 0 : object_class->finalize = valent_ebook_adapter_finalize;
218 : :
219 : 0 : vobject_class->destroy = valent_ebook_adapter_destroy;
220 : : }
221 : :
222 : : static void
223 : 0 : valent_ebook_adapter_init (ValentEBookAdapter *self)
224 : : {
225 : 0 : self->stores = g_hash_table_new_full ((GHashFunc)e_source_hash,
226 : : (GEqualFunc)e_source_equal,
227 : : g_object_unref,
228 : : g_object_unref);
229 : 0 : }
230 : :
|