goa: Add missing linker flag (for real).
[platform/upstream/evolution-data-server.git] / libedataserver / e-source-selectable.c
1 /*
2  * e-source-selectable.c
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) version 3.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
16  *
17  */
18
19 /**
20  * SECTION: e-source-selectable
21  * @include: libedataserver/libedataserver.h
22  * @short_description: Base class for selectable data sources
23  * @see_also: #ESourceCalendar, #ESourceMemoList, #ESourceTaskList
24  *
25  * #ESourceSelectable is an abstract base class for data sources
26  * that can be selected in an #ESourceSelector or similar widget.
27  **/
28
29 #include "e-source-selectable.h"
30
31 #include <libedataserver/e-data-server-util.h>
32
33 #define E_SOURCE_SELECTABLE_GET_PRIVATE(obj) \
34         (G_TYPE_INSTANCE_GET_PRIVATE \
35         ((obj), E_TYPE_SOURCE_SELECTABLE, ESourceSelectablePrivate))
36
37 struct _ESourceSelectablePrivate {
38         GMutex property_lock;
39         gchar *color;
40         gboolean selected;
41 };
42
43 enum {
44         PROP_0,
45         PROP_COLOR,
46         PROP_SELECTED
47 };
48
49 G_DEFINE_ABSTRACT_TYPE (
50         ESourceSelectable,
51         e_source_selectable,
52         E_TYPE_SOURCE_BACKEND)
53
54 static void
55 source_selectable_set_property (GObject *object,
56                                 guint property_id,
57                                 const GValue *value,
58                                 GParamSpec *pspec)
59 {
60         switch (property_id) {
61                 case PROP_COLOR:
62                         e_source_selectable_set_color (
63                                 E_SOURCE_SELECTABLE (object),
64                                 g_value_get_string (value));
65                         return;
66
67                 case PROP_SELECTED:
68                         e_source_selectable_set_selected (
69                                 E_SOURCE_SELECTABLE (object),
70                                 g_value_get_boolean (value));
71                         return;
72         }
73
74         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
75 }
76
77 static void
78 source_selectable_get_property (GObject *object,
79                                 guint property_id,
80                                 GValue *value,
81                                 GParamSpec *pspec)
82 {
83         switch (property_id) {
84                 case PROP_COLOR:
85                         g_value_take_string (
86                                 value,
87                                 e_source_selectable_dup_color (
88                                 E_SOURCE_SELECTABLE (object)));
89                         return;
90
91                 case PROP_SELECTED:
92                         g_value_set_boolean (
93                                 value,
94                                 e_source_selectable_get_selected (
95                                 E_SOURCE_SELECTABLE (object)));
96                         return;
97         }
98
99         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
100 }
101
102 static void
103 source_selectable_finalize (GObject *object)
104 {
105         ESourceSelectablePrivate *priv;
106
107         priv = E_SOURCE_SELECTABLE_GET_PRIVATE (object);
108
109         g_mutex_clear (&priv->property_lock);
110
111         g_free (priv->color);
112
113         /* Chain up to parent's finalize() method. */
114         G_OBJECT_CLASS (e_source_selectable_parent_class)->finalize (object);
115 }
116
117 static void
118 e_source_selectable_class_init (ESourceSelectableClass *class)
119 {
120         GObjectClass *object_class;
121
122         g_type_class_add_private (class, sizeof (ESourceSelectablePrivate));
123
124         object_class = G_OBJECT_CLASS (class);
125         object_class->set_property = source_selectable_set_property;
126         object_class->get_property = source_selectable_get_property;
127         object_class->finalize = source_selectable_finalize;
128
129         /* We do not provide an extension name,
130          * which is why the class is abstract. */
131
132         g_object_class_install_property (
133                 object_class,
134                 PROP_COLOR,
135                 g_param_spec_string (
136                         "color",
137                         "Color",
138                         "Textual specification of a color",
139                         "#becedd",
140                         G_PARAM_READWRITE |
141                         G_PARAM_CONSTRUCT |
142                         G_PARAM_STATIC_STRINGS |
143                         E_SOURCE_PARAM_SETTING));
144
145         g_object_class_install_property (
146                 object_class,
147                 PROP_SELECTED,
148                 g_param_spec_boolean (
149                         "selected",
150                         "Selected",
151                         "Whether the data source is selected",
152                         TRUE,
153                         G_PARAM_READWRITE |
154                         G_PARAM_CONSTRUCT |
155                         G_PARAM_STATIC_STRINGS |
156                         E_SOURCE_PARAM_SETTING));
157 }
158
159 static void
160 e_source_selectable_init (ESourceSelectable *extension)
161 {
162         extension->priv = E_SOURCE_SELECTABLE_GET_PRIVATE (extension);
163         g_mutex_init (&extension->priv->property_lock);
164 }
165
166 /**
167  * e_source_selectable_get_color:
168  * @extension: an #ESourceSelectable
169  *
170  * Returns the color specification for the #ESource to which @extension
171  * belongs.  A colored block is often displayed next to the data source's
172  * display name in user interfaces.
173  *
174  * Returns: the color specification for the #ESource
175  *
176  * Since: 3.6
177  **/
178 const gchar *
179 e_source_selectable_get_color (ESourceSelectable *extension)
180 {
181         g_return_val_if_fail (E_IS_SOURCE_SELECTABLE (extension), NULL);
182
183         return extension->priv->color;
184 }
185
186 /**
187  * e_source_selectable_dup_color:
188  * @extension: an #ESourceSelectable
189  *
190  * Thread-safe variation of e_source_selectable_get_color().
191  * Use this function when accessing @extension from multiple threads.
192  *
193  * The returned string should be freed with g_free() when no longer needed.
194  *
195  * Returns: a newly-allocated copy of #ESourceSelectable:color
196  *
197  * Since: 3.6
198  **/
199 gchar *
200 e_source_selectable_dup_color (ESourceSelectable *extension)
201 {
202         const gchar *protected;
203         gchar *duplicate;
204
205         g_return_val_if_fail (E_IS_SOURCE_SELECTABLE (extension), NULL);
206
207         g_mutex_lock (&extension->priv->property_lock);
208
209         protected = e_source_selectable_get_color (extension);
210         duplicate = g_strdup (protected);
211
212         g_mutex_unlock (&extension->priv->property_lock);
213
214         return duplicate;
215 }
216
217 /**
218  * e_source_selectable_set_color:
219  * @extension: an #ESourceSelectable
220  * @color: (allow-none): a color specification, or %NULL
221  *
222  * Sets the color specification for the #ESource to which @extension
223  * belongs.  A colored block is often displayed next to the data source's
224  * display name in user interfaces.
225  *
226  * The internal copy of @color is automatically stripped of leading and
227  * trailing whitespace.  If the resulting string is empty, %NULL is set
228  * instead.
229  *
230  * Since: 3.6
231  **/
232 void
233 e_source_selectable_set_color (ESourceSelectable *extension,
234                                const gchar *color)
235 {
236         g_return_if_fail (E_IS_SOURCE_SELECTABLE (extension));
237
238         g_mutex_lock (&extension->priv->property_lock);
239
240         if (g_strcmp0 (extension->priv->color, color) == 0) {
241                 g_mutex_unlock (&extension->priv->property_lock);
242                 return;
243         }
244
245         g_free (extension->priv->color);
246         extension->priv->color = e_util_strdup_strip (color);
247
248         g_mutex_unlock (&extension->priv->property_lock);
249
250         g_object_notify (G_OBJECT (extension), "color");
251 }
252
253 /**
254  * e_source_selectable_get_selected:
255  * @extension: an #ESourceSelectable
256  *
257  * Returns the selected state of the #ESource to which @extension belongs.
258  * The selected state is often represented as a checkbox next to the data
259  * source's display name in user interfaces.
260  *
261  * Returns: the selected state for the #ESource
262  *
263  * Since: 3.6
264  **/
265 gboolean
266 e_source_selectable_get_selected (ESourceSelectable *extension)
267 {
268         g_return_val_if_fail (E_IS_SOURCE_SELECTABLE (extension), FALSE);
269
270         return extension->priv->selected;
271 }
272
273 /**
274  * e_source_selectable_set_selected:
275  * @extension: an #ESourceSelectable
276  * @selected: selected state
277  *
278  * Sets the selected state for the #ESource to which @extension belongs.
279  * The selected state is often represented as a checkbox next to the data
280  * source's display name in user interfaces.
281  *
282  * Since: 3.6
283  **/
284 void
285 e_source_selectable_set_selected (ESourceSelectable *extension,
286                                   gboolean selected)
287 {
288         g_return_if_fail (E_IS_SOURCE_SELECTABLE (extension));
289
290         if (extension->priv->selected == selected)
291                 return;
292
293         extension->priv->selected = selected;
294
295         g_object_notify (G_OBJECT (extension), "selected");
296 }
297