1 /*
2 * e-source-extension.c
3 *
4 * This library is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18 /**
19 * SECTION: e-source-extension
20 * @include: libedataserver/libedataserver.h
21 * @short_description: Base class for #ESource extensions
22 *
23 * #ESourceExtension is an abstract base class for #ESource extension
24 * objects. An #ESourceExtension object basically just maps the keys in
25 * a key file group to a set of #GObject properties. The name of the key
26 * file group doubles as the name of the #ESourceExtension object.
27 *
28 * #ESourceExtension objects are accessed through e_source_get_extension().
29 **/
30
31 #include "e-source-extension.h"
32
33 struct _ESourceExtensionPrivate {
34 GWeakRef source;
35 GRecMutex property_lock;
36 };
37
38 enum {
39 PROP_0,
40 PROP_SOURCE
41 };
42
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(ESourceExtension,e_source_extension,G_TYPE_OBJECT)43 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (
44 ESourceExtension,
45 e_source_extension,
46 G_TYPE_OBJECT)
47
48 static void
49 source_extension_set_source (ESourceExtension *extension,
50 ESource *source)
51 {
52 g_return_if_fail (E_IS_SOURCE (source));
53
54 g_weak_ref_set (&extension->priv->source, source);
55 }
56
57 static void
source_extension_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)58 source_extension_set_property (GObject *object,
59 guint property_id,
60 const GValue *value,
61 GParamSpec *pspec)
62 {
63 switch (property_id) {
64 case PROP_SOURCE:
65 source_extension_set_source (
66 E_SOURCE_EXTENSION (object),
67 g_value_get_object (value));
68 return;
69 }
70
71 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
72 }
73
74 static void
source_extension_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)75 source_extension_get_property (GObject *object,
76 guint property_id,
77 GValue *value,
78 GParamSpec *pspec)
79 {
80 switch (property_id) {
81 case PROP_SOURCE:
82 g_value_take_object (
83 value, e_source_extension_ref_source (
84 E_SOURCE_EXTENSION (object)));
85 return;
86 }
87
88 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
89 }
90
91 static void
source_extension_dispose(GObject * object)92 source_extension_dispose (GObject *object)
93 {
94 ESourceExtensionPrivate *priv;
95
96 priv = E_SOURCE_EXTENSION (object)->priv;
97
98 g_weak_ref_set (&priv->source, NULL);
99
100 /* Chain up to parent's dispose() method. */
101 G_OBJECT_CLASS (e_source_extension_parent_class)->dispose (object);
102 }
103
104 static void
source_extension_finalize(GObject * object)105 source_extension_finalize (GObject *object)
106 {
107 ESourceExtensionPrivate *priv;
108
109 priv = E_SOURCE_EXTENSION (object)->priv;
110
111 g_weak_ref_clear (&priv->source);
112 g_rec_mutex_clear (&priv->property_lock);
113
114 /* Chain up to parent's finalize() method. */
115 G_OBJECT_CLASS (e_source_extension_parent_class)->finalize (object);
116 }
117
118 static void
source_extension_notify(GObject * object,GParamSpec * pspec)119 source_extension_notify (GObject *object,
120 GParamSpec *pspec)
121 {
122 ESource *source;
123 ESourceExtension *extension;
124
125 extension = E_SOURCE_EXTENSION (object);
126 source = e_source_extension_ref_source (extension);
127 g_return_if_fail (source != NULL);
128
129 if ((pspec->flags & E_SOURCE_PARAM_SETTING) != 0)
130 e_source_changed (source);
131
132 g_object_unref (source);
133 }
134
135 static void
e_source_extension_class_init(ESourceExtensionClass * class)136 e_source_extension_class_init (ESourceExtensionClass *class)
137 {
138 GObjectClass *object_class;
139
140 object_class = G_OBJECT_CLASS (class);
141 object_class->set_property = source_extension_set_property;
142 object_class->get_property = source_extension_get_property;
143 object_class->dispose = source_extension_dispose;
144 object_class->finalize = source_extension_finalize;
145 object_class->notify = source_extension_notify;
146
147 g_object_class_install_property (
148 object_class,
149 PROP_SOURCE,
150 g_param_spec_object (
151 "source",
152 "Source",
153 "The ESource being extended",
154 E_TYPE_SOURCE,
155 G_PARAM_READWRITE |
156 G_PARAM_CONSTRUCT_ONLY |
157 G_PARAM_STATIC_STRINGS));
158 }
159
160 static void
e_source_extension_init(ESourceExtension * extension)161 e_source_extension_init (ESourceExtension *extension)
162 {
163 extension->priv = e_source_extension_get_instance_private (extension);
164 g_weak_ref_init (&extension->priv->source, NULL);
165 g_rec_mutex_init (&extension->priv->property_lock);
166 }
167
168 /**
169 * e_source_extension_ref_source:
170 * @extension: an #ESourceExtension
171 *
172 * Returns the #ESource instance to which the @extension belongs.
173 *
174 * The returned #ESource is referenced for thread-safety. Unreference
175 * the #ESource with g_object_unref() when finished with it.
176 *
177 * Returns: (transfer full): the #ESource instance
178 *
179 * Since: 3.8
180 **/
181 ESource *
e_source_extension_ref_source(ESourceExtension * extension)182 e_source_extension_ref_source (ESourceExtension *extension)
183 {
184 g_return_val_if_fail (E_IS_SOURCE_EXTENSION (extension), NULL);
185
186 return g_weak_ref_get (&extension->priv->source);
187 }
188
189 /**
190 * e_source_extension_get_source:
191 * @extension: an #ESourceExtension
192 *
193 * Returns the #ESource instance to which @extension belongs.
194 *
195 * Note this function is not thread-safe. The returned #ESource could
196 * be finalized by another thread while the caller is still using it.
197 *
198 * Returns: (transfer none): the #ESource instance
199 *
200 * Since: 3.6
201 *
202 * Deprecated: 3.8: Use e_source_extension_ref_source() instead.
203 **/
204 ESource *
e_source_extension_get_source(ESourceExtension * extension)205 e_source_extension_get_source (ESourceExtension *extension)
206 {
207 ESource *source;
208
209 g_return_val_if_fail (E_IS_SOURCE_EXTENSION (extension), NULL);
210
211 source = e_source_extension_ref_source (extension);
212
213 /* XXX Drop the ESource reference for backward-compatibility.
214 * This is risky. Without a reference, the ESource could
215 * be finalized while the caller is still using it. */
216 if (source != NULL)
217 g_object_unref (source);
218
219 return source;
220 }
221
222 /**
223 * e_source_extension_property_lock:
224 * @extension: an #ESourceExtension
225 *
226 * Acquires a property lock, thus no other thread can change properties
227 * of the @extension until the lock is released.
228 *
229 * Since: 3.18
230 **/
231 void
e_source_extension_property_lock(ESourceExtension * extension)232 e_source_extension_property_lock (ESourceExtension *extension)
233 {
234 g_return_if_fail (E_IS_SOURCE_EXTENSION (extension));
235
236 g_rec_mutex_lock (&extension->priv->property_lock);
237 }
238
239 /**
240 * e_source_extension_property_unlock:
241 * @extension: an #ESourceExtension
242 *
243 * Releases a property lock, previously acquired with e_source_extension_property_lock(),
244 * thus other threads can change properties of the @extension.
245 *
246 * Since: 3.18
247 **/
248 void
e_source_extension_property_unlock(ESourceExtension * extension)249 e_source_extension_property_unlock (ESourceExtension *extension)
250 {
251 g_return_if_fail (E_IS_SOURCE_EXTENSION (extension));
252
253 g_rec_mutex_unlock (&extension->priv->property_lock);
254 }
255