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-contacts"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <gio/gio.h>
9 : : #include <libpeas.h>
10 : : #include <libvalent-core.h>
11 : :
12 : : #include "valent-contacts.h"
13 : : #include "valent-contacts-adapter.h"
14 : :
15 : :
16 : : /**
17 : : * ValentContacts:
18 : : *
19 : : * A class for managing address books.
20 : : *
21 : : * `ValentContacts` is an address book manager, intended for use by
22 : : * [class@Valent.DevicePlugin] implementations.
23 : : *
24 : : * Plugins can implement [class@Valent.ContactsAdapter] to provide an interface
25 : : * to manage address books, or lists of contacts.
26 : : *
27 : : * Since: 1.0
28 : : */
29 : :
30 : : struct _ValentContacts
31 : : {
32 : : ValentComponent parent_instance;
33 : :
34 : : /* list model */
35 : : GPtrArray *items;
36 : : };
37 : :
38 : : static void valent_contacts_unbind_extension (ValentComponent *component,
39 : : GObject *extension);
40 : : static void g_list_model_iface_init (GListModelInterface *iface);
41 : :
42 [ + + + - ]: 193 : G_DEFINE_FINAL_TYPE_WITH_CODE (ValentContacts, valent_contacts, VALENT_TYPE_COMPONENT,
43 : : G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, g_list_model_iface_init))
44 : :
45 : : static ValentContacts *default_contacts = NULL;
46 : :
47 : :
48 : : /*
49 : : * GListModel
50 : : */
51 : : static gpointer
52 : 8 : valent_contacts_get_item (GListModel *list,
53 : : unsigned int position)
54 : : {
55 : 8 : ValentContacts *self = VALENT_CONTACTS (list);
56 : :
57 [ + - ]: 8 : g_assert (VALENT_IS_CONTACTS (self));
58 : :
59 [ + - ]: 8 : if G_UNLIKELY (position >= self->items->len)
60 : : return NULL;
61 : :
62 : 8 : return g_object_ref (g_ptr_array_index (self->items, position));
63 : : }
64 : :
65 : : static GType
66 : 1 : valent_contacts_get_item_type (GListModel *list)
67 : : {
68 : 1 : return VALENT_TYPE_CONTACTS_ADAPTER;
69 : : }
70 : :
71 : : static unsigned int
72 : 7 : valent_contacts_get_n_items (GListModel *list)
73 : : {
74 : 7 : ValentContacts *self = VALENT_CONTACTS (list);
75 : :
76 [ + - ]: 7 : g_assert (VALENT_IS_CONTACTS (self));
77 : :
78 : 7 : return self->items->len;
79 : : }
80 : :
81 : : static void
82 : 5 : g_list_model_iface_init (GListModelInterface *iface)
83 : : {
84 : 5 : iface->get_item = valent_contacts_get_item;
85 : 5 : iface->get_item_type = valent_contacts_get_item_type;
86 : 5 : iface->get_n_items = valent_contacts_get_n_items;
87 : 5 : }
88 : :
89 : : /*
90 : : * ValentComponent
91 : : */
92 : : static void
93 : 12 : valent_contacts_bind_extension (ValentComponent *component,
94 : : GObject *extension)
95 : : {
96 : 12 : ValentContacts *self = VALENT_CONTACTS (component);
97 : 12 : unsigned int position = 0;
98 : :
99 : 12 : VALENT_ENTRY;
100 : :
101 [ + - ]: 12 : g_assert (VALENT_IS_CONTACTS (self));
102 [ - + ]: 12 : g_assert (VALENT_IS_CONTACTS_ADAPTER (extension));
103 : :
104 [ - + ]: 12 : if (g_ptr_array_find (self->items, extension, &position))
105 : : {
106 : 0 : g_warning ("Adapter \"%s\" already exported in \"%s\"",
107 : : G_OBJECT_TYPE_NAME (extension),
108 : : G_OBJECT_TYPE_NAME (component));
109 : 0 : return;
110 : : }
111 : :
112 : 12 : g_signal_connect_object (extension,
113 : : "destroy",
114 : : G_CALLBACK (valent_contacts_unbind_extension),
115 : : self,
116 : : G_CONNECT_SWAPPED);
117 : :
118 : 12 : position = self->items->len;
119 : 12 : g_ptr_array_add (self->items, g_object_ref (extension));
120 : 12 : g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
121 : :
122 : 12 : VALENT_EXIT;
123 : : }
124 : :
125 : : static void
126 : 10 : valent_contacts_unbind_extension (ValentComponent *component,
127 : : GObject *extension)
128 : : {
129 : 10 : ValentContacts *self = VALENT_CONTACTS (component);
130 : 20 : g_autoptr (ValentExtension) item = NULL;
131 : 10 : unsigned int position = 0;
132 : :
133 : 10 : VALENT_ENTRY;
134 : :
135 [ + - ]: 10 : g_assert (VALENT_IS_CONTACTS (self));
136 [ - + ]: 10 : g_assert (VALENT_IS_CONTACTS_ADAPTER (extension));
137 : :
138 [ - + ]: 10 : if (!g_ptr_array_find (self->items, extension, &position))
139 : : {
140 : 0 : g_warning ("Adapter \"%s\" not found in \"%s\"",
141 : : G_OBJECT_TYPE_NAME (extension),
142 : : G_OBJECT_TYPE_NAME (component));
143 : 0 : return;
144 : : }
145 : :
146 : 10 : g_signal_handlers_disconnect_by_func (extension, valent_contacts_unbind_extension, self);
147 : 10 : item = g_ptr_array_steal_index (self->items, position);
148 : 10 : g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
149 : :
150 [ + - ]: 10 : VALENT_EXIT;
151 : : }
152 : :
153 : : /*
154 : : * GObject
155 : : */
156 : : static void
157 : 5 : valent_contacts_finalize (GObject *object)
158 : : {
159 : 5 : ValentContacts *self = VALENT_CONTACTS (object);
160 : :
161 [ + - ]: 5 : g_clear_pointer (&self->items, g_ptr_array_unref);
162 : :
163 : 5 : G_OBJECT_CLASS (valent_contacts_parent_class)->finalize (object);
164 : 5 : }
165 : :
166 : : static void
167 : 5 : valent_contacts_class_init (ValentContactsClass *klass)
168 : : {
169 : 5 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
170 : 5 : ValentComponentClass *component_class = VALENT_COMPONENT_CLASS (klass);
171 : :
172 : 5 : object_class->finalize = valent_contacts_finalize;
173 : :
174 : 5 : component_class->bind_extension = valent_contacts_bind_extension;
175 : 5 : component_class->unbind_extension = valent_contacts_unbind_extension;
176 : : }
177 : :
178 : : static void
179 : 7 : valent_contacts_init (ValentContacts *self)
180 : : {
181 : 7 : self->items = g_ptr_array_new_with_free_func (g_object_unref);
182 : 7 : }
183 : :
184 : : /**
185 : : * valent_contacts_get_default:
186 : : *
187 : : * Get the default [class@Valent.Contacts].
188 : : *
189 : : * Returns: (transfer none) (not nullable): a `ValentContacts`
190 : : *
191 : : * Since: 1.0
192 : : */
193 : : ValentContacts *
194 : 27 : valent_contacts_get_default (void)
195 : : {
196 [ + + ]: 27 : if (default_contacts == NULL)
197 : : {
198 : 7 : default_contacts = g_object_new (VALENT_TYPE_CONTACTS,
199 : : "plugin-domain", "contacts",
200 : : "plugin-type", VALENT_TYPE_CONTACTS_ADAPTER,
201 : : NULL);
202 : :
203 : 7 : g_object_add_weak_pointer (G_OBJECT (default_contacts),
204 : : (gpointer)&default_contacts);
205 : : }
206 : :
207 : 27 : return default_contacts;
208 : : }
209 : :
210 : : /**
211 : : * valent_contacts_export_adapter:
212 : : * @contacts: a `ValentContacts`
213 : : * @object: a `ValentContactsAdapter`
214 : : *
215 : : * Export @object on all adapters that support it.
216 : : *
217 : : * Since: 1.0
218 : : */
219 : : void
220 : 5 : valent_contacts_export_adapter (ValentContacts *contacts,
221 : : ValentContactsAdapter *object)
222 : : {
223 : 5 : VALENT_ENTRY;
224 : :
225 [ + - ]: 5 : g_return_if_fail (VALENT_IS_CONTACTS (contacts));
226 [ - + ]: 5 : g_return_if_fail (VALENT_IS_CONTACTS_ADAPTER (object));
227 : :
228 : 5 : valent_contacts_bind_extension (VALENT_COMPONENT (contacts),
229 : : G_OBJECT (object));
230 : :
231 : 5 : VALENT_EXIT;
232 : : }
233 : :
234 : : /**
235 : : * valent_contacts_unexport_adapter:
236 : : * @contacts: a `ValentContacts`
237 : : * @object: a `ValentContactsAdapter`
238 : : *
239 : : * Unexport @object from all adapters that support it.
240 : : *
241 : : * Since: 1.0
242 : : */
243 : : void
244 : 5 : valent_contacts_unexport_adapter (ValentContacts *contacts,
245 : : ValentContactsAdapter *object)
246 : : {
247 : 5 : VALENT_ENTRY;
248 : :
249 [ + - ]: 5 : g_return_if_fail (VALENT_IS_CONTACTS (contacts));
250 [ - + ]: 5 : g_return_if_fail (VALENT_IS_CONTACTS_ADAPTER (object));
251 : :
252 : 5 : valent_contacts_unbind_extension (VALENT_COMPONENT (contacts),
253 : : G_OBJECT (object));
254 : :
255 : 5 : VALENT_EXIT;
256 : : }
257 : :
|