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