1 /*
2  * e-source-autoconfig.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-autoconfig
20  * @include: libedataserver/libedataserver.h
21  * @short_description: #ESource extension for autoconfig settings
22  *
23  * The #ESourceAutoconfig extension keeps a mapping between user-specific
24  * sources and system-wide ones.
25  *
26  * Access the extension as follows:
27  *
28  * |[
29  *   #include <libedataserver/libedataserver.h>
30  *
31  *   ESourceAutoconfig *extension;
32  *
33  *   extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTOCONFIG);
34  * ]|
35  **/
36 
37 #include "e-source-autoconfig.h"
38 
39 struct _ESourceAutoconfigPrivate {
40 	gchar *revision;
41 };
42 
43 enum {
44 	PROP_0,
45 	PROP_REVISION
46 };
47 
G_DEFINE_TYPE_WITH_PRIVATE(ESourceAutoconfig,e_source_autoconfig,E_TYPE_SOURCE_EXTENSION)48 G_DEFINE_TYPE_WITH_PRIVATE (
49 	ESourceAutoconfig,
50 	e_source_autoconfig,
51 	E_TYPE_SOURCE_EXTENSION)
52 
53 static void
54 source_autoconfig_get_property (GObject *object,
55                                 guint property_id,
56                                 GValue *value,
57                                 GParamSpec *pspec)
58 {
59 	switch (property_id) {
60 		case PROP_REVISION:
61 			g_value_take_string (
62 				value,
63 				e_source_autoconfig_dup_revision (
64 				E_SOURCE_AUTOCONFIG (object)));
65 			return;
66 	}
67 
68 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
69 }
70 
71 static void
source_autoconfig_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)72 source_autoconfig_set_property (GObject *object,
73                                 guint property_id,
74                                 const GValue *value,
75                                 GParamSpec *pspec)
76 {
77 	switch (property_id) {
78 		case PROP_REVISION:
79 			e_source_autoconfig_set_revision (
80 				E_SOURCE_AUTOCONFIG (object),
81 				g_value_get_string (value));
82 			return;
83 	}
84 
85 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
86 }
87 
88 static void
source_autoconfig_finalize(GObject * object)89 source_autoconfig_finalize (GObject *object)
90 {
91 	ESourceAutoconfigPrivate *priv;
92 
93 	priv = E_SOURCE_AUTOCONFIG (object)->priv;
94 
95 	g_free (priv->revision);
96 
97 	/* Chain up to parent's finalize() method. */
98 	G_OBJECT_CLASS (e_source_autoconfig_parent_class)->finalize (object);
99 }
100 
101 static void
e_source_autoconfig_class_init(ESourceAutoconfigClass * class)102 e_source_autoconfig_class_init (ESourceAutoconfigClass *class)
103 {
104 	GObjectClass *object_class;
105 	ESourceExtensionClass *extension_class;
106 
107 	object_class = G_OBJECT_CLASS (class);
108 	object_class->set_property = source_autoconfig_set_property;
109 	object_class->get_property = source_autoconfig_get_property;
110 	object_class->finalize = source_autoconfig_finalize;
111 
112 	extension_class = E_SOURCE_EXTENSION_CLASS (class);
113 	extension_class->name = E_SOURCE_EXTENSION_AUTOCONFIG;
114 
115 	g_object_class_install_property (
116 		object_class,
117 		PROP_REVISION,
118 		g_param_spec_string (
119 			"revision",
120 			"Revision",
121 			"Identifier to map a particular version of a system-wide source to a user-specific source",
122 			"",
123 			G_PARAM_READWRITE |
124 			G_PARAM_CONSTRUCT |
125 			G_PARAM_EXPLICIT_NOTIFY |
126 			G_PARAM_STATIC_STRINGS |
127 			E_SOURCE_PARAM_SETTING));
128 }
129 
130 static void
e_source_autoconfig_init(ESourceAutoconfig * extension)131 e_source_autoconfig_init (ESourceAutoconfig *extension)
132 {
133 	extension->priv = e_source_autoconfig_get_instance_private (extension);
134 }
135 
136 /**
137  * e_source_autoconfig_get_revision:
138  * @extension: an #ESourceAutoconfig
139  *
140  * Returns the revision of a data source. This maps a particular version of a
141  * system-wide source to a user-specific source.
142  *
143  * If doesn't match, the system-wide source will be copied to the user-specific
144  * evolution config directory, preserving the already present fields that are
145  * not defined by the system-wide source.
146  *
147  * If it matches, no copying is done.
148  *
149  * Returns: revision of the data source
150  *
151  * Since: 3.24
152  **/
153 const gchar *
e_source_autoconfig_get_revision(ESourceAutoconfig * extension)154 e_source_autoconfig_get_revision (ESourceAutoconfig *extension)
155 {
156 	g_return_val_if_fail (E_IS_SOURCE_AUTOCONFIG (extension), NULL);
157 
158 	return extension->priv->revision;
159 }
160 
161 /**
162  * e_source_autoconfig_dup_revision:
163  * @extension: an #ESourceAutoconfig
164  *
165  * Thread-safe variation of e_source_autoconfig_get_revision().
166  * Use this function when accessing @extension from multiple threads.
167  *
168  * The returned string should be freed with g_free() when no longer needed.
169  *
170  * Returns: (transfer full): a newly-allocated copy of #ESourceAutoconfig:revision
171  *
172  * Since: 3.24
173  **/
174 gchar *
e_source_autoconfig_dup_revision(ESourceAutoconfig * extension)175 e_source_autoconfig_dup_revision (ESourceAutoconfig *extension)
176 {
177 	const gchar *protected;
178 	gchar *duplicate;
179 
180 	g_return_val_if_fail (E_IS_SOURCE_AUTOCONFIG (extension), NULL);
181 
182 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
183 
184 	protected = e_source_autoconfig_get_revision (extension);
185 	duplicate = g_strdup (protected);
186 
187 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
188 
189 	return duplicate;
190 }
191 
192 /**
193  * e_source_autoconfig_set_revision:
194  * @extension: an #ESourceAutoconfig
195  * @revision: a revision
196  *
197  * Sets the revision used to map a particular version of a system-wide source
198  * to a user-specific source.
199  *
200  * If doesn't match, the system-wide source will be copied to the user-specific
201  * evolution config directory, preserving the already present fields that are
202  * not defined by the system-wide source.
203  *
204  * If it matches, no copying is done.
205  *
206  * The internal copy of @revision is automatically stripped of leading and
207  * trailing whitespace.
208  *
209  * Since: 3.24
210  **/
211 void
e_source_autoconfig_set_revision(ESourceAutoconfig * extension,const gchar * revision)212 e_source_autoconfig_set_revision (ESourceAutoconfig *extension,
213                                   const gchar *revision)
214 {
215 	g_return_if_fail (E_IS_SOURCE_AUTOCONFIG (extension));
216 
217 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
218 
219 	if (e_util_strcmp0 (extension->priv->revision, revision) == 0) {
220 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
221 		return;
222 	}
223 
224 	g_free (extension->priv->revision);
225 	extension->priv->revision = e_util_strdup_strip (revision);
226 
227 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
228 
229 	g_object_notify (G_OBJECT (extension), "revision");
230 }
231