changes: Bump to 3.8.1
[platform/upstream/evolution-data-server.git] / libedataserver / e-source-alarms.c
1 /*
2  * e-source-alarms.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 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-alarms
20  * @include: libedataserver/libedataserver.h
21  * @short_description: #ESource extension for alarm state
22  *
23  * The #ESourceAlarms extension tracks alarm state for a calendar.
24  *
25  * Access the extension as follows:
26  *
27  * |[
28  *   #include <libedataserver/libedataserver.h>
29  *
30  *   ESourceAlarms *extension;
31  *
32  *   extension = e_source_get_extension (source, E_SOURCE_EXTENSION_ALARMS);
33  * ]|
34  **/
35
36 #include "e-source-alarms.h"
37
38 #define E_SOURCE_ALARMS_GET_PRIVATE(obj) \
39         (G_TYPE_INSTANCE_GET_PRIVATE \
40         ((obj), E_TYPE_SOURCE_ALARMS, ESourceAlarmsPrivate))
41
42 struct _ESourceAlarmsPrivate {
43         GMutex property_lock;
44         gboolean include_me;
45         gchar *last_notified;
46 };
47
48 enum {
49         PROP_0,
50         PROP_INCLUDE_ME,
51         PROP_LAST_NOTIFIED
52 };
53
54 G_DEFINE_TYPE (
55         ESourceAlarms,
56         e_source_alarms,
57         E_TYPE_SOURCE_EXTENSION)
58
59 static void
60 source_alarms_set_property (GObject *object,
61                             guint property_id,
62                             const GValue *value,
63                             GParamSpec *pspec)
64 {
65         switch (property_id) {
66                 case PROP_INCLUDE_ME:
67                         e_source_alarms_set_include_me (
68                                 E_SOURCE_ALARMS (object),
69                                 g_value_get_boolean (value));
70                         return;
71
72                 case PROP_LAST_NOTIFIED:
73                         e_source_alarms_set_last_notified (
74                                 E_SOURCE_ALARMS (object),
75                                 g_value_get_string (value));
76                         return;
77         }
78
79         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
80 }
81
82 static void
83 source_alarms_get_property (GObject *object,
84                             guint property_id,
85                             GValue *value,
86                             GParamSpec *pspec)
87 {
88         switch (property_id) {
89                 case PROP_INCLUDE_ME:
90                         g_value_set_boolean (
91                                 value,
92                                 e_source_alarms_get_include_me (
93                                 E_SOURCE_ALARMS (object)));
94                         return;
95
96                 case PROP_LAST_NOTIFIED:
97                         g_value_take_string (
98                                 value,
99                                 e_source_alarms_dup_last_notified (
100                                 E_SOURCE_ALARMS (object)));
101                         return;
102         }
103
104         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
105 }
106
107 static void
108 source_alarms_finalize (GObject *object)
109 {
110         ESourceAlarmsPrivate *priv;
111
112         priv = E_SOURCE_ALARMS_GET_PRIVATE (object);
113
114         g_mutex_clear (&priv->property_lock);
115
116         g_free (priv->last_notified);
117
118         /* Chain up to parent's finalize() method. */
119         G_OBJECT_CLASS (e_source_alarms_parent_class)->finalize (object);
120 }
121
122 static void
123 e_source_alarms_class_init (ESourceAlarmsClass *class)
124 {
125         GObjectClass *object_class;
126         ESourceExtensionClass *extension_class;
127
128         g_type_class_add_private (class, sizeof (ESourceAlarmsPrivate));
129
130         object_class = G_OBJECT_CLASS (class);
131         object_class->set_property = source_alarms_set_property;
132         object_class->get_property = source_alarms_get_property;
133         object_class->finalize = source_alarms_finalize;
134
135         extension_class = E_SOURCE_EXTENSION_CLASS (class);
136         extension_class->name = E_SOURCE_EXTENSION_ALARMS;
137
138         g_object_class_install_property (
139                 object_class,
140                 PROP_INCLUDE_ME,
141                 g_param_spec_boolean (
142                         "include-me",
143                         "IncludeMe",
144                         "Include this source in alarm notifications",
145                         TRUE,
146                         G_PARAM_READWRITE |
147                         G_PARAM_CONSTRUCT |
148                         G_PARAM_STATIC_STRINGS |
149                         E_SOURCE_PARAM_SETTING));
150
151         g_object_class_install_property (
152                 object_class,
153                 PROP_LAST_NOTIFIED,
154                 g_param_spec_string (
155                         "last-notified",
156                         "LastNotified",
157                         "Last alarm notification (in ISO 8601 format)",
158                         NULL,
159                         G_PARAM_READWRITE |
160                         G_PARAM_CONSTRUCT |
161                         G_PARAM_STATIC_STRINGS |
162                         E_SOURCE_PARAM_SETTING));
163 }
164
165 static void
166 e_source_alarms_init (ESourceAlarms *extension)
167 {
168         extension->priv = E_SOURCE_ALARMS_GET_PRIVATE (extension);
169         g_mutex_init (&extension->priv->property_lock);
170 }
171
172 /**
173  * e_source_alarms_get_include_me:
174  * @extension: an #ESourceAlarms
175  *
176  * Returns whether the user should be alerted about upcoming appointments
177  * in the calendar described by the #ESource to which @extension belongs.
178  *
179  * Alarm daemons such as evolution-alarm-notify can use this property to
180  * decide which calendars to query for upcoming appointments.
181  *
182  * Returns: whether to show alarms for upcoming appointments
183  *
184  * Since: 3.6
185  **/
186 gboolean
187 e_source_alarms_get_include_me (ESourceAlarms *extension)
188 {
189         g_return_val_if_fail (E_IS_SOURCE_ALARMS (extension), FALSE);
190
191         return extension->priv->include_me;
192 }
193
194 /**
195  * e_source_alarms_set_include_me:
196  * @extension: an #ESourceAlarms
197  * @include_me: whether to show alarms for upcoming appointments
198  *
199  * Sets whether the user should be alerted about upcoming appointments in
200  * the calendar described by the #ESource to which @extension belongs.
201  *
202  * Alarm daemons such as evolution-alarm-notify can use this property to
203  * decide which calendars to query for upcoming appointments.
204  *
205  * Since: 3.6
206  **/
207 void
208 e_source_alarms_set_include_me (ESourceAlarms *extension,
209                                 gboolean include_me)
210 {
211         g_return_if_fail (E_IS_SOURCE_ALARMS (extension));
212
213         if (extension->priv->include_me == include_me)
214                 return;
215
216         extension->priv->include_me = include_me;
217
218         g_object_notify (G_OBJECT (extension), "include-me");
219 }
220
221 /**
222  * e_source_alarms_get_last_notified:
223  * @extension: an #ESourceAlarms
224  *
225  * Returns an ISO 8601 formatted timestamp of when the user was last
226  * alerted about an upcoming appointment in the calendar described by
227  * the #ESource to which @extension belongs.  If no valid timestamp
228  * has been set, the function will return %NULL.
229  *
230  * Returns: an ISO 8601 timestamp, or %NULL
231  *
232  * Since: 3.6
233  **/
234 const gchar *
235 e_source_alarms_get_last_notified (ESourceAlarms *extension)
236 {
237         g_return_val_if_fail (E_IS_SOURCE_ALARMS (extension), NULL);
238
239         return extension->priv->last_notified;
240 }
241
242 /**
243  * e_source_alarms_dup_last_notified:
244  * @extension: an #ESourceAlarms
245  *
246  * Thread-safe variation of e_source_alarms_get_last_notified().
247  * Use this function when accessing @extension from multiple threads.
248  *
249  * The returned string should be freed with g_free() when no longer needed.
250  *
251  * Returns: a newly-allocated copy of #ESourceAlarms:last-notified
252  *
253  * Since: 3.6
254  **/
255 gchar *
256 e_source_alarms_dup_last_notified (ESourceAlarms *extension)
257 {
258         const gchar *protected;
259         gchar *duplicate;
260
261         g_return_val_if_fail (E_IS_SOURCE_ALARMS (extension), NULL);
262
263         g_mutex_lock (&extension->priv->property_lock);
264
265         protected = e_source_alarms_get_last_notified (extension);
266         duplicate = g_strdup (protected);
267
268         g_mutex_unlock (&extension->priv->property_lock);
269
270         return duplicate;
271 }
272
273 /**
274  * e_source_alarms_set_last_notified:
275  * @extension: an #ESourceAlarms
276  * @last_notified: (allow-none): an ISO 8601 timestamp, or %NULL
277  *
278  * Sets an ISO 8601 formatted timestamp of when the user was last
279  * alerted about an upcoming appointment in the calendar described
280  * by the #ESource to which @extension belongs.
281  *
282  * If @last_notified is non-%NULL, the function will validate the
283  * timestamp before setting the #ESourceAlarms:last-notified property.
284  * Invalid timestamps are discarded with a runtime warning.
285  *
286  * Generally, this function should only be called by an alarm daemon
287  * such as evolution-alarm-notify.
288  *
289  * Since: 3.6
290  **/
291 void
292 e_source_alarms_set_last_notified (ESourceAlarms *extension,
293                                    const gchar *last_notified)
294 {
295         g_return_if_fail (E_IS_SOURCE_ALARMS (extension));
296
297         if (last_notified && !*last_notified)
298                 last_notified = NULL;
299
300         if (last_notified != NULL) {
301                 GTimeVal time_val;
302
303                 if (!g_time_val_from_iso8601 (last_notified, &time_val)) {
304                         g_warning (
305                                 "%s: Invalid timestamp: '%s'",
306                                 G_STRFUNC, last_notified);
307                         return;
308                 }
309         }
310
311         g_mutex_lock (&extension->priv->property_lock);
312
313         if (g_strcmp0 (extension->priv->last_notified, last_notified) == 0) {
314                 g_mutex_unlock (&extension->priv->property_lock);
315                 return;
316         }
317
318         g_free (extension->priv->last_notified);
319         extension->priv->last_notified = g_strdup (last_notified);
320
321         g_mutex_unlock (&extension->priv->property_lock);
322
323         g_object_notify (G_OBJECT (extension), "last-notified");
324 }