1 /*
2  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
3  * Copyright (C) 2019 Red Hat, Inc. (www.redhat.com)
4  *
5  * This library is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library. If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18 
19 #include "evolution-data-server-config.h"
20 
21 /**
22  * SECTION:e-cal-component-alarm
23  * @short_description: An ECalComponentAlarm structure
24  * @include: libecal/libecal.h
25  *
26  * Contains functions to work with the #ECalComponentAlarm structure.
27  **/
28 
29 #include <libedataserver/libedataserver.h>
30 
31 #include "e-cal-component-alarm-repeat.h"
32 #include "e-cal-component-alarm-trigger.h"
33 #include "e-cal-component-attendee.h"
34 #include "e-cal-component-property-bag.h"
35 #include "e-cal-component-text.h"
36 #include "e-cal-enums.h"
37 
38 #include "e-cal-component-alarm.h"
39 
40 G_DEFINE_BOXED_TYPE (ECalComponentAlarm, e_cal_component_alarm, e_cal_component_alarm_copy, e_cal_component_alarm_free)
41 
42 struct _ECalComponentAlarm {
43 	gchar *uid;
44 	ECalComponentAlarmAction action;
45 	ECalComponentText *summary;
46 	ECalComponentText *description;
47 	ECalComponentAlarmRepeat *repeat;
48 	ECalComponentAlarmTrigger *trigger;
49 	GSList *attendees; /* ECalComponentAttendee * */
50 	GSList *attachments; /* ICalAttach * */
51 	ECalComponentPropertyBag *property_bag;
52 	ICalTime *acknowledged;
53 };
54 
55 /**
56  * e_cal_component_alarm_new:
57  *
58  * Creates a new empty #ECalComponentAlarm structure. Free it
59  * with e_cal_component_alarm_free(), when no longer needed.
60  *
61  * Returns: (transfer full): a newly allocated #ECalComponentAlarm
62  *
63  * Since: 3.34
64  **/
65 ECalComponentAlarm *
e_cal_component_alarm_new(void)66 e_cal_component_alarm_new (void)
67 {
68 	ECalComponentAlarm *alarm;
69 
70 	alarm = g_slice_new0 (ECalComponentAlarm);
71 	alarm->uid = e_util_generate_uid ();
72 	alarm->action = E_CAL_COMPONENT_ALARM_UNKNOWN;
73 	alarm->property_bag = e_cal_component_property_bag_new ();
74 
75 	return alarm;
76 }
77 
78 /**
79  * e_cal_component_alarm_new_from_component:
80  * @component: an #ICalComponent of kind %I_CAL_VALARM_COMPONENT
81  *
82  * Creates a new #ECalComponentAlarm, filled with values from @component,
83  * which should be of kind %I_CAL_VALARM_COMPONENT. The function returns
84  * %NULL when it is not of the expected kind. Free the structure
85  * with e_cal_component_alarm_free(), when no longer needed.
86  *
87  * Returns: (transfer full) (nullable): a newly allocated #ECalComponentAlarm
88  *
89  * Since: 3.34
90  **/
91 ECalComponentAlarm *
e_cal_component_alarm_new_from_component(const ICalComponent * component)92 e_cal_component_alarm_new_from_component (const ICalComponent *component)
93 {
94 	ECalComponentAlarm *alarm;
95 
96 	g_return_val_if_fail (I_CAL_IS_COMPONENT ((ICalComponent *) component), NULL);
97 
98 	if (i_cal_component_isa ((ICalComponent *) component) != I_CAL_VALARM_COMPONENT)
99 		return NULL;
100 
101 	alarm = e_cal_component_alarm_new ();
102 
103 	e_cal_component_alarm_set_from_component (alarm, component);
104 
105 	return alarm;
106 }
107 
108 /**
109  * e_cal_component_alarm_copy:
110  * @alarm: (not nullable): an #ECalComponentAlarm
111  *
112  * Returns a newly allocated copy of @alarm, which should be freed with
113  * e_cal_component_alarm_free(), when no longer needed.
114  *
115  * Returns: (transfer full): a newly allocated copy of @alarm
116  *
117  * Since: 3.34
118  **/
119 ECalComponentAlarm *
e_cal_component_alarm_copy(const ECalComponentAlarm * alarm)120 e_cal_component_alarm_copy (const ECalComponentAlarm *alarm)
121 {
122 	ECalComponentAlarm *alrm;
123 
124 	g_return_val_if_fail (alarm != NULL, NULL);
125 
126 	alrm = e_cal_component_alarm_new ();
127 
128 	g_free (alrm->uid);
129 	alrm->uid = g_strdup (alarm->uid);
130 	alrm->action = alarm->action;
131 
132 	if (alarm->summary)
133 		alrm->summary = e_cal_component_text_copy (alarm->summary);
134 
135 	if (alarm->description)
136 		alrm->description = e_cal_component_text_copy (alarm->description);
137 
138 	if (alarm->repeat)
139 		alrm->repeat = e_cal_component_alarm_repeat_copy (alarm->repeat);
140 
141 	if (alarm->trigger)
142 		alrm->trigger = e_cal_component_alarm_trigger_copy (alarm->trigger);
143 
144 	if (alarm->attendees) {
145 		GSList *link;
146 
147 		for (link = alarm->attendees; link; link = g_slist_next (link)) {
148 			ECalComponentAttendee *attendee = link->data;
149 
150 			if (!attendee)
151 				continue;
152 
153 			alrm->attendees = g_slist_prepend (alrm->attendees, e_cal_component_attendee_copy (attendee));
154 		}
155 
156 		alrm->attendees = g_slist_reverse (alrm->attendees);
157 	}
158 
159 	if (alarm->attachments) {
160 		GSList *link;
161 
162 		for (link = alarm->attachments; link; link = g_slist_next (link)) {
163 			ICalAttach *src_attach = link->data, *attach = NULL;
164 
165 			if (!src_attach)
166 				continue;
167 
168 			if (i_cal_attach_get_is_url (src_attach)) {
169 				const gchar *url;
170 
171 				url = i_cal_attach_get_url (src_attach);
172 				if (url)
173 					attach = i_cal_attach_new_from_url (url);
174 			} else {
175 				const gchar *data;
176 
177 				data = i_cal_attach_get_data (src_attach);
178 				if (data)
179 					attach = i_cal_attach_new_from_data (data, NULL, NULL);
180 			}
181 
182 			if (attach)
183 				alrm->attachments = g_slist_prepend (alrm->attachments, attach);
184 		}
185 
186 		alrm->attachments = g_slist_reverse (alrm->attachments);
187 	}
188 
189 	if (alarm->acknowledged)
190 		e_cal_component_alarm_set_acknowledged (alrm, alarm->acknowledged);
191 
192 	e_cal_component_property_bag_assign (alrm->property_bag, alarm->property_bag);
193 
194 	return alrm;
195 }
196 
197 /**
198  * e_cal_component_alarm_free: (skip)
199  * @alarm: (type ECalComponentAlarm) (nullable): an #ECalComponentAlarm to free
200  *
201  * Free @alarm, previously created by e_cal_component_alarm_new(),
202  * e_cal_component_alarm_new_from_component()
203  * or e_cal_component_alarm_copy(). The function does nothing, if @alarm
204  * is %NULL.
205  *
206  * Since: 3.34
207  **/
208 void
e_cal_component_alarm_free(gpointer alarm)209 e_cal_component_alarm_free (gpointer alarm)
210 {
211 	ECalComponentAlarm *alrm = alarm;
212 
213 	if (alrm) {
214 		g_free (alrm->uid);
215 		e_cal_component_text_free (alrm->summary);
216 		e_cal_component_text_free (alrm->description);
217 		e_cal_component_alarm_repeat_free (alrm->repeat);
218 		e_cal_component_alarm_trigger_free (alrm->trigger);
219 		e_cal_component_property_bag_free (alrm->property_bag);
220 		g_slist_free_full (alrm->attendees, e_cal_component_attendee_free);
221 		g_slist_free_full (alrm->attachments, g_object_unref);
222 		g_clear_object (&alrm->acknowledged);
223 		g_slice_free (ECalComponentAlarm, alrm);
224 	}
225 }
226 
227 /**
228  * e_cal_component_alarm_set_from_component:
229  * @alarm: an #ECalComponentAlarm
230  * @component: an #ICalComponent
231  *
232  * Fill the @alarm structure with the information from
233  * the @component, which should be of %I_CAL_VALARM_COMPONENT kind.
234  *
235  * Since: 3.34
236  **/
237 void
e_cal_component_alarm_set_from_component(ECalComponentAlarm * alarm,const ICalComponent * component)238 e_cal_component_alarm_set_from_component (ECalComponentAlarm *alarm,
239 					  const ICalComponent *component)
240 {
241 	ICalComponent *comp = (ICalComponent *) component;
242 	ICalDuration *duration = NULL;
243 	ICalProperty *prop, *repeat = NULL;
244 
245 	g_return_if_fail (alarm != NULL);
246 	g_return_if_fail (I_CAL_IS_COMPONENT ((ICalComponent *) component));
247 	g_return_if_fail (i_cal_component_isa ((ICalComponent *) component) == I_CAL_VALARM_COMPONENT);
248 
249 	g_free (alarm->uid);
250 	e_cal_component_text_free (alarm->summary);
251 	e_cal_component_text_free (alarm->description);
252 	e_cal_component_alarm_repeat_free (alarm->repeat);
253 	e_cal_component_alarm_trigger_free (alarm->trigger);
254 	g_slist_free_full (alarm->attendees, e_cal_component_attendee_free);
255 	g_slist_free_full (alarm->attachments, g_object_unref);
256 	g_clear_object (&alarm->acknowledged);
257 
258 	alarm->uid = NULL;
259 	alarm->action = E_CAL_COMPONENT_ALARM_NONE;
260 	alarm->summary = NULL;
261 	alarm->description = NULL;
262 	alarm->repeat = NULL;
263 	alarm->trigger = NULL;
264 	alarm->attendees = NULL;
265 	alarm->attachments = NULL;
266 
267 	e_cal_component_property_bag_clear (alarm->property_bag);
268 
269 	for (prop = i_cal_component_get_first_property (comp, I_CAL_ANY_PROPERTY);
270 	     prop;
271 	     g_object_unref (prop), prop = i_cal_component_get_next_property (comp, I_CAL_ANY_PROPERTY)) {
272 		ECalComponentAttendee *attendee;
273 		ICalAttach *attach;
274 		const gchar *xname;
275 
276 		switch (i_cal_property_isa (prop)) {
277 		case I_CAL_ACTION_PROPERTY:
278 			switch (i_cal_property_get_action (prop)) {
279 			case I_CAL_ACTION_AUDIO:
280 				alarm->action = E_CAL_COMPONENT_ALARM_AUDIO;
281 				break;
282 
283 			case I_CAL_ACTION_DISPLAY:
284 				alarm->action = E_CAL_COMPONENT_ALARM_DISPLAY;
285 				break;
286 
287 			case I_CAL_ACTION_EMAIL:
288 				alarm->action = E_CAL_COMPONENT_ALARM_EMAIL;
289 				break;
290 
291 			case I_CAL_ACTION_PROCEDURE:
292 				alarm->action = E_CAL_COMPONENT_ALARM_PROCEDURE;
293 				break;
294 
295 			case I_CAL_ACTION_NONE:
296 				alarm->action = E_CAL_COMPONENT_ALARM_NONE;
297 				break;
298 
299 			default:
300 				alarm->action = E_CAL_COMPONENT_ALARM_UNKNOWN;
301 				break;
302 			}
303 			break;
304 
305 		case I_CAL_ATTACH_PROPERTY:
306 			attach = i_cal_property_get_attach (prop);
307 			if (attach)
308 				alarm->attachments = g_slist_prepend (alarm->attachments, attach);
309 			break;
310 
311 		case I_CAL_SUMMARY_PROPERTY:
312 			if (i_cal_property_get_summary (prop)) {
313 				ICalParameter *param;
314 
315 				param = i_cal_property_get_first_parameter (prop, I_CAL_ALTREP_PARAMETER);
316 				e_cal_component_alarm_take_summary (alarm,
317 					e_cal_component_text_new (i_cal_property_get_summary (prop),
318 					param ? i_cal_parameter_get_altrep (param) : NULL));
319 				g_clear_object (&param);
320 			}
321 			break;
322 
323 		case I_CAL_DESCRIPTION_PROPERTY:
324 			if (i_cal_property_get_description (prop)) {
325 				ICalParameter *param;
326 
327 				param = i_cal_property_get_first_parameter (prop, I_CAL_ALTREP_PARAMETER);
328 				e_cal_component_alarm_take_description (alarm,
329 					e_cal_component_text_new (i_cal_property_get_description (prop),
330 					param ? i_cal_parameter_get_altrep (param) : NULL));
331 				g_clear_object (&param);
332 			}
333 			break;
334 
335 		case I_CAL_DURATION_PROPERTY:
336 			g_clear_object (&duration);
337 			duration = i_cal_property_get_duration (prop);
338 			break;
339 
340 		case I_CAL_REPEAT_PROPERTY:
341 			g_clear_object (&repeat);
342 			repeat = g_object_ref (prop);
343 			break;
344 
345 		case I_CAL_TRIGGER_PROPERTY:
346 			alarm->trigger = e_cal_component_alarm_trigger_new_from_property (prop);
347 			break;
348 
349 		case I_CAL_ATTENDEE_PROPERTY:
350 			attendee = e_cal_component_attendee_new_from_property (prop);
351 			if (attendee)
352 				alarm->attendees = g_slist_prepend (alarm->attendees, attendee);
353 			break;
354 
355 		case I_CAL_ACKNOWLEDGED_PROPERTY:
356 			g_clear_object (&alarm->acknowledged);
357 			alarm->acknowledged = i_cal_property_get_acknowledged (prop);
358 			break;
359 
360 		case I_CAL_X_PROPERTY:
361 			xname = i_cal_property_get_x_name (prop);
362 			if (g_strcmp0 (xname, E_CAL_EVOLUTION_ALARM_UID_PROPERTY) == 0) {
363 				g_free (alarm->uid);
364 				alarm->uid = g_strdup (i_cal_property_get_x (prop));
365 			} else {
366 				e_cal_component_property_bag_add (alarm->property_bag, prop);
367 			}
368 			break;
369 
370 		default:
371 			e_cal_component_property_bag_add (alarm->property_bag, prop);
372 			break;
373 		}
374 	}
375 
376 	alarm->attendees = g_slist_reverse (alarm->attendees);
377 	alarm->attachments = g_slist_reverse (alarm->attachments);
378 
379 	if (duration && repeat) {
380 		alarm->repeat = e_cal_component_alarm_repeat_new (
381 			i_cal_property_get_repeat (repeat),
382 			duration);
383 	}
384 
385 	g_clear_object (&duration);
386 	g_clear_object (&repeat);
387 
388 	/* Ensure mandatory property */
389 	if (!alarm->uid)
390 		alarm->uid = e_util_generate_uid ();
391 }
392 
393 /**
394  * e_cal_component_alarm_get_as_component:
395  * @alarm: an #ECalComponentAlarm
396  *
397  * Creates a VALARM #ICalComponent filled with data from the @alarm.
398  * In case the @alarm doesn't have set 'uid', a new is assigned.
399  * Free the returned component with g_object_unref(), when no longer
400  * needed.
401  *
402  * Returns: (transfer full): a newly created #ICalComponent
403  *    of %I_CAL_VALARM_COMPONENT kind
404  *
405  * Since: 3.34
406  **/
407 ICalComponent *
e_cal_component_alarm_get_as_component(ECalComponentAlarm * alarm)408 e_cal_component_alarm_get_as_component (ECalComponentAlarm *alarm)
409 {
410 	ICalComponent *valarm;
411 
412 	g_return_val_if_fail (alarm != NULL, NULL);
413 
414 	valarm = i_cal_component_new_valarm ();
415 
416 	e_cal_component_alarm_fill_component (alarm, valarm);
417 
418 	return valarm;
419 }
420 
421 /**
422  * e_cal_component_alarm_fill_component:
423  * @alarm: an #ECalComponentAlarm
424  * @component: an #ICalComponent of %I_CAL_VALARM_COMPONENT kind
425  *
426  * Fills @component with data from @alarm. The @component should
427  * be of %I_CAL_VALARM_COMPONENT kind - the function does nothing,
428  * if it's not. In case the @alarm doesn't have set 'uid', a new
429  * is assigned.
430  *
431  * Since: 3.34
432  **/
433 void
e_cal_component_alarm_fill_component(ECalComponentAlarm * alarm,ICalComponent * component)434 e_cal_component_alarm_fill_component (ECalComponentAlarm *alarm,
435 				      ICalComponent *component)
436 {
437 	ICalPropertyKind remove_props[] = {
438 		I_CAL_ACTION_PROPERTY,
439 		I_CAL_ATTACH_PROPERTY,
440 		I_CAL_SUMMARY_PROPERTY,
441 		I_CAL_DESCRIPTION_PROPERTY,
442 		I_CAL_DURATION_PROPERTY,
443 		I_CAL_REPEAT_PROPERTY,
444 		I_CAL_TRIGGER_PROPERTY,
445 		I_CAL_ATTENDEE_PROPERTY };
446 	ICalProperty *prop;
447 	GSList *link;
448 	gint ii;
449 
450 	g_return_if_fail (alarm != NULL);
451 	g_return_if_fail (I_CAL_IS_COMPONENT (component));
452 
453 	if (i_cal_component_isa (component) != I_CAL_VALARM_COMPONENT)
454 		return;
455 
456 	/* Remove used properties first */
457 
458 	for (ii = 0; ii < G_N_ELEMENTS (remove_props); ii++) {
459 		if (remove_props[ii] == I_CAL_ACTION_PROPERTY &&
460 		    alarm->action == E_CAL_COMPONENT_ALARM_UNKNOWN)
461 			continue;
462 
463 		while (prop = i_cal_component_get_first_property (component, remove_props[ii]), prop) {
464 			i_cal_component_remove_property (component, prop);
465 			g_object_unref (prop);
466 		}
467 	}
468 
469 	if (!alarm->uid)
470 		alarm->uid = e_util_generate_uid ();
471 
472 	for (prop = i_cal_component_get_first_property (component, I_CAL_X_PROPERTY);
473 	     prop;
474 	     g_object_unref (prop), i_cal_component_get_first_property (component, I_CAL_X_PROPERTY)) {
475 		const gchar *xname;
476 
477 		xname = i_cal_property_get_x_name (prop);
478 		if (g_strcmp0 (xname, E_CAL_EVOLUTION_ALARM_UID_PROPERTY) == 0) {
479 			i_cal_property_set_x (prop, alarm->uid);
480 			/* Do not set to NULL, it's used below as a sentinel */
481 			g_object_unref (prop);
482 			break;
483 		}
484 	}
485 
486 	/* Tried all existing and none was the E_CAL_EVOLUTION_ALARM_UID_PROPERTY, thus add it */
487 	if (!prop) {
488 		prop = i_cal_property_new_x (alarm->uid);
489 		i_cal_property_set_x_name (prop, E_CAL_EVOLUTION_ALARM_UID_PROPERTY);
490 		i_cal_component_take_property (component, prop);
491 	}
492 
493 	prop = NULL;
494 
495 	switch (alarm->action) {
496 	case E_CAL_COMPONENT_ALARM_AUDIO:
497 		prop = i_cal_property_new_action (I_CAL_ACTION_AUDIO);
498 		break;
499 
500 	case E_CAL_COMPONENT_ALARM_DISPLAY:
501 		prop = i_cal_property_new_action (I_CAL_ACTION_DISPLAY);
502 		break;
503 
504 	case E_CAL_COMPONENT_ALARM_EMAIL:
505 		prop = i_cal_property_new_action (I_CAL_ACTION_EMAIL);
506 		break;
507 
508 	case E_CAL_COMPONENT_ALARM_PROCEDURE:
509 		prop = i_cal_property_new_action (I_CAL_ACTION_PROCEDURE);
510 		break;
511 
512 	case E_CAL_COMPONENT_ALARM_NONE:
513 		prop = i_cal_property_new_action (I_CAL_ACTION_NONE);
514 		break;
515 
516 	case E_CAL_COMPONENT_ALARM_UNKNOWN:
517 		break;
518 	}
519 
520 	if (prop)
521 		i_cal_component_take_property (component, prop);
522 
523 	if (alarm->summary && e_cal_component_text_get_value (alarm->summary)) {
524 		prop = i_cal_property_new_summary (e_cal_component_text_get_value (alarm->summary));
525 
526 		if (prop) {
527 			const gchar *altrep = e_cal_component_text_get_altrep (alarm->summary);
528 
529 			if (altrep && *altrep) {
530 				ICalParameter *param;
531 
532 				param = i_cal_parameter_new_altrep (altrep);
533 				if (param)
534 					i_cal_property_take_parameter (prop, param);
535 			}
536 
537 			i_cal_component_take_property (component, prop);
538 		}
539 	}
540 
541 	if (alarm->description && e_cal_component_text_get_value (alarm->description)) {
542 		prop = i_cal_property_new_description (e_cal_component_text_get_value (alarm->description));
543 
544 		if (prop) {
545 			const gchar *altrep = e_cal_component_text_get_altrep (alarm->description);
546 
547 			if (altrep && *altrep) {
548 				ICalParameter *param;
549 
550 				param = i_cal_parameter_new_altrep (altrep);
551 				if (param)
552 					i_cal_property_take_parameter (prop, param);
553 			}
554 
555 			i_cal_component_take_property (component, prop);
556 		}
557 	}
558 
559 	if (alarm->trigger) {
560 		prop = e_cal_component_alarm_trigger_get_as_property (alarm->trigger);
561 		if (prop)
562 			i_cal_component_take_property (component, prop);
563 	}
564 
565 	if (alarm->repeat) {
566 		ICalDuration *interval;
567 
568 		interval = e_cal_component_alarm_repeat_get_interval (alarm->repeat);
569 		if (interval) {
570 			prop = i_cal_property_new_repeat (e_cal_component_alarm_repeat_get_repetitions (alarm->repeat));
571 			i_cal_component_take_property (component, prop);
572 
573 			prop = i_cal_property_new_duration (interval);
574 			i_cal_component_take_property (component, prop);
575 		}
576 	}
577 
578 	for (link = alarm->attendees; link; link = g_slist_next (link)) {
579 		ECalComponentAttendee *attendee = link->data;
580 
581 		if (!attendee)
582 			continue;
583 
584 		prop = e_cal_component_attendee_get_as_property (attendee);
585 		if (prop)
586 			i_cal_component_take_property (component, prop);
587 	}
588 
589 	for (link = alarm->attachments; link; link = g_slist_next (link)) {
590 		ICalAttach *attach = link->data;
591 
592 		if (!attach)
593 			continue;
594 
595 		prop = i_cal_property_new_attach (attach);
596 		if (prop)
597 			i_cal_component_take_property (component, prop);
598 	}
599 
600 	if (alarm->acknowledged) {
601 		prop = i_cal_property_new_acknowledged (alarm->acknowledged);
602 		i_cal_component_take_property (component, prop);
603 	}
604 
605 	e_cal_component_property_bag_fill_component (alarm->property_bag, component);
606 }
607 
608 /**
609  * e_cal_component_alarm_get_uid:
610  * @alarm: an #ECalComponentAlarm
611  *
612  * Get the @alarm UID.
613  *
614  * Returns: (nullable): the @alarm UID, or %NULL, when none is set
615  *
616  * Since: 3.34
617  **/
618 const gchar *
e_cal_component_alarm_get_uid(const ECalComponentAlarm * alarm)619 e_cal_component_alarm_get_uid (const ECalComponentAlarm *alarm)
620 {
621 	g_return_val_if_fail (alarm != NULL, NULL);
622 
623 	return alarm->uid;
624 }
625 
626 /**
627  * e_cal_component_alarm_set_uid:
628  * @alarm: an #ECalComponentAlarm
629  * @uid: (nullable): a UID to set, or %NULL or emptry string to generate new
630  *
631  * Set the @alarm UID, or generates a new UID, if @uid is %NULL or an empty string.
632  *
633  * Since: 3.34
634  **/
635 void
e_cal_component_alarm_set_uid(ECalComponentAlarm * alarm,const gchar * uid)636 e_cal_component_alarm_set_uid (ECalComponentAlarm *alarm,
637 			       const gchar *uid)
638 {
639 	g_return_if_fail (alarm != NULL);
640 
641 	if (!uid || !*uid) {
642 		g_free (alarm->uid);
643 		alarm->uid = e_util_generate_uid ();
644 	} else if (g_strcmp0 (alarm->uid, uid) != 0) {
645 		g_free (alarm->uid);
646 		alarm->uid = g_strdup (uid);
647 	}
648 }
649 
650 /**
651  * e_cal_component_alarm_get_action:
652  * @alarm: an #ECalComponentAlarm
653  *
654  * Get the @alarm action, as an #ECalComponentAlarmAction.
655  *
656  * Returns: the @alarm action, or %E_CAL_COMPONENT_ALARM_NONE, when none is set
657  *
658  * Since: 3.34
659  **/
660 ECalComponentAlarmAction
e_cal_component_alarm_get_action(const ECalComponentAlarm * alarm)661 e_cal_component_alarm_get_action (const ECalComponentAlarm *alarm)
662 {
663 	g_return_val_if_fail (alarm != NULL, E_CAL_COMPONENT_ALARM_NONE);
664 
665 	return alarm->action;
666 }
667 
668 /**
669  * e_cal_component_alarm_set_action:
670  * @alarm: an #ECalComponentAlarm
671  * @action: an #ECalComponentAlarmAction
672  *
673  * Set the @alarm action, as an #ECalComponentAlarmAction.
674  *
675  * Since: 3.34
676  **/
677 void
e_cal_component_alarm_set_action(ECalComponentAlarm * alarm,ECalComponentAlarmAction action)678 e_cal_component_alarm_set_action (ECalComponentAlarm *alarm,
679 				  ECalComponentAlarmAction action)
680 {
681 	g_return_if_fail (alarm != NULL);
682 
683 	alarm->action = action;
684 }
685 
686 /**
687  * e_cal_component_alarm_get_summary:
688  * @alarm: an #ECalComponentAlarm
689  *
690  * Get the @alarm summary, as an #ECalComponentText.
691  *
692  * Returns: (transfer none) (nullable): the @alarm summary, or %NULL, when none is set
693  *
694  * Since: 3.34
695  **/
696 ECalComponentText *
e_cal_component_alarm_get_summary(const ECalComponentAlarm * alarm)697 e_cal_component_alarm_get_summary (const ECalComponentAlarm *alarm)
698 {
699 	g_return_val_if_fail (alarm != NULL, NULL);
700 
701 	return alarm->summary;
702 }
703 
704 /**
705  * e_cal_component_alarm_set_summary:
706  * @alarm: an #ECalComponentAlarm
707  * @summary: (transfer none) (nullable): a summary to set, or %NULL to unset
708  *
709  * Set the @alarm summary, as an #ECalComponentText.
710  *
711  * Since: 3.34
712  **/
713 void
e_cal_component_alarm_set_summary(ECalComponentAlarm * alarm,const ECalComponentText * summary)714 e_cal_component_alarm_set_summary (ECalComponentAlarm *alarm,
715 				   const ECalComponentText *summary)
716 {
717 	g_return_if_fail (alarm != NULL);
718 
719 	if (summary != alarm->summary) {
720 		e_cal_component_text_free (alarm->summary);
721 
722 		alarm->summary = summary ? e_cal_component_text_copy (summary) : NULL;
723 	}
724 }
725 
726 /**
727  * e_cal_component_alarm_take_summary: (skip)
728  * @alarm: an #ECalComponentAlarm
729  * @summary: (transfer full) (nullable): a summary to set, or %NULL to unset
730  *
731  * Set the @alarm summary, as an #ECalComponentText, and assumes
732  * ownership of the @summary.
733  *
734  * Since: 3.34
735  **/
736 void
e_cal_component_alarm_take_summary(ECalComponentAlarm * alarm,ECalComponentText * summary)737 e_cal_component_alarm_take_summary (ECalComponentAlarm *alarm,
738 				    ECalComponentText *summary)
739 {
740 	g_return_if_fail (alarm != NULL);
741 
742 	if (summary != alarm->summary) {
743 		e_cal_component_text_free (alarm->summary);
744 		alarm->summary = summary;
745 	}
746 }
747 
748 /**
749  * e_cal_component_alarm_get_description:
750  * @alarm: an #ECalComponentAlarm
751  *
752  * Get the @alarm description, as an #ECalComponentText.
753  *
754  * Returns: (transfer none) (nullable): the @alarm description, or %NULL, when none is set
755  *
756  * Since: 3.34
757  **/
758 ECalComponentText *
e_cal_component_alarm_get_description(const ECalComponentAlarm * alarm)759 e_cal_component_alarm_get_description (const ECalComponentAlarm *alarm)
760 {
761 	g_return_val_if_fail (alarm != NULL, NULL);
762 
763 	return alarm->description;
764 }
765 
766 /**
767  * e_cal_component_alarm_set_description:
768  * @alarm: an #ECalComponentAlarm
769  * @description: (transfer none) (nullable): a description to set, or %NULL to unset
770  *
771  * Set the @alarm description, as an #ECalComponentText.
772  *
773  * Since: 3.34
774  **/
775 void
e_cal_component_alarm_set_description(ECalComponentAlarm * alarm,const ECalComponentText * description)776 e_cal_component_alarm_set_description (ECalComponentAlarm *alarm,
777 				       const ECalComponentText *description)
778 {
779 	g_return_if_fail (alarm != NULL);
780 
781 	if (description != alarm->description) {
782 		e_cal_component_text_free (alarm->description);
783 
784 		alarm->description = description ? e_cal_component_text_copy (description) : NULL;
785 	}
786 }
787 
788 /**
789  * e_cal_component_alarm_take_description: (skip)
790  * @alarm: an #ECalComponentAlarm
791  * @description: (transfer full) (nullable): a description to set, or %NULL to unset
792  *
793  * Set the @alarm description, as an #ECalComponentText, and assumes
794  * ownership of the @description.
795  *
796  * Since: 3.34
797  **/
798 void
e_cal_component_alarm_take_description(ECalComponentAlarm * alarm,ECalComponentText * description)799 e_cal_component_alarm_take_description (ECalComponentAlarm *alarm,
800 					ECalComponentText *description)
801 {
802 	g_return_if_fail (alarm != NULL);
803 
804 	if (description != alarm->description) {
805 		e_cal_component_text_free (alarm->description);
806 		alarm->description = description;
807 	}
808 }
809 
810 /**
811  * e_cal_component_alarm_get_repeat:
812  * @alarm: an #ECalComponentAlarm
813  *
814  * Get the @alarm repeat information, as an ECalComponentAlarmRepeat.
815  *
816  * Returns: (transfer none) (nullable): the @alarm repeat information,
817  *    or %NULL, when none is set
818  *
819  * Since: 3.34
820  **/
821 ECalComponentAlarmRepeat *
e_cal_component_alarm_get_repeat(const ECalComponentAlarm * alarm)822 e_cal_component_alarm_get_repeat (const ECalComponentAlarm *alarm)
823 {
824 	g_return_val_if_fail (alarm != NULL, NULL);
825 
826 	return alarm->repeat;
827 }
828 
829 /**
830  * e_cal_component_alarm_set_repeat:
831  * @alarm: an #ECalComponentAlarm
832  * @repeat: (transfer none) (nullable): a repeat information to set, or %NULL to unset
833  *
834  * Set the @alarm repeat information, as an #ECalComponentAlarmRepeat.
835  *
836  * Since: 3.34
837  **/
838 void
e_cal_component_alarm_set_repeat(ECalComponentAlarm * alarm,const ECalComponentAlarmRepeat * repeat)839 e_cal_component_alarm_set_repeat (ECalComponentAlarm *alarm,
840 				  const ECalComponentAlarmRepeat *repeat)
841 {
842 	g_return_if_fail (alarm != NULL);
843 
844 	if (repeat != alarm->repeat) {
845 		e_cal_component_alarm_repeat_free (alarm->repeat);
846 
847 		alarm->repeat = repeat ? e_cal_component_alarm_repeat_copy (repeat) : NULL;
848 	}
849 }
850 
851 /**
852  * e_cal_component_alarm_take_repeat: (skip)
853  * @alarm: an #ECalComponentAlarm
854  * @repeat: (transfer none) (nullable): a repeat information to set, or %NULL to unset
855  *
856  * Set the @alarm repeat information, as an #ECalComponentAlarmRepeat and assumes
857  * ownership of the @trigger.
858  *
859  * Since: 3.34
860  **/
861 void
e_cal_component_alarm_take_repeat(ECalComponentAlarm * alarm,ECalComponentAlarmRepeat * repeat)862 e_cal_component_alarm_take_repeat (ECalComponentAlarm *alarm,
863 				   ECalComponentAlarmRepeat *repeat)
864 {
865 	g_return_if_fail (alarm != NULL);
866 
867 	if (repeat != alarm->repeat) {
868 		e_cal_component_alarm_repeat_free (alarm->repeat);
869 		alarm->repeat = repeat;
870 	}
871 }
872 
873 /**
874  * e_cal_component_alarm_get_trigger:
875  * @alarm: an #ECalComponentAlarm
876  *
877  * Get the @alarm trigger, as an #ECalComponentAlarmTrigger.
878  *
879  * Returns: (transfer none) (nullable): the @alarm trigger, or %NULL when, none is set
880  *
881  * Since: 3.34
882  **/
883 ECalComponentAlarmTrigger *
e_cal_component_alarm_get_trigger(const ECalComponentAlarm * alarm)884 e_cal_component_alarm_get_trigger (const ECalComponentAlarm *alarm)
885 {
886 	g_return_val_if_fail (alarm != NULL, NULL);
887 
888 	return alarm->trigger;
889 }
890 
891 /**
892  * e_cal_component_alarm_set_trigger:
893  * @alarm: an #ECalComponentAlarm
894  * @trigger: (transfer none) (nullable): a trigger to set, or %NULL to unset
895  *
896  * Set the @alarm trigger, as an #ECalComponentAlarmTrigger.
897  *
898  * Since: 3.34
899  **/
900 void
e_cal_component_alarm_set_trigger(ECalComponentAlarm * alarm,const ECalComponentAlarmTrigger * trigger)901 e_cal_component_alarm_set_trigger (ECalComponentAlarm *alarm,
902 				   const ECalComponentAlarmTrigger *trigger)
903 {
904 	g_return_if_fail (alarm != NULL);
905 
906 	if (trigger != alarm->trigger) {
907 		e_cal_component_alarm_trigger_free (alarm->trigger);
908 
909 		alarm->trigger = trigger ? e_cal_component_alarm_trigger_copy (trigger) : NULL;
910 	}
911 }
912 
913 /**
914  * e_cal_component_alarm_take_trigger: (skip)
915  * @alarm: an #ECalComponentAlarm
916  * @trigger: (transfer full) (nullable): a trigger to set, or %NULL to unset
917  *
918  * Set the @alarm trigger, as an #ECalComponentAlarmTrigger and assumes
919  * ownership of the @trigger.
920  *
921  * Since: 3.34
922  **/
923 void
e_cal_component_alarm_take_trigger(ECalComponentAlarm * alarm,ECalComponentAlarmTrigger * trigger)924 e_cal_component_alarm_take_trigger (ECalComponentAlarm *alarm,
925 				    ECalComponentAlarmTrigger *trigger)
926 {
927 	g_return_if_fail (alarm != NULL);
928 
929 	if (trigger != alarm->trigger) {
930 		e_cal_component_alarm_trigger_free (alarm->trigger);
931 		alarm->trigger = trigger;
932 	}
933 }
934 
935 /**
936  * e_cal_component_alarm_has_attendees:
937  * @alarm: an #ECalComponentAlarm
938  *
939  * Returns: whether the @alarm has any attendees
940  *
941  * Since: 3.34
942  **/
943 gboolean
e_cal_component_alarm_has_attendees(const ECalComponentAlarm * alarm)944 e_cal_component_alarm_has_attendees (const ECalComponentAlarm *alarm)
945 {
946 	g_return_val_if_fail (alarm != NULL, FALSE);
947 
948 	return alarm->attendees != NULL;
949 }
950 
951 /**
952  * e_cal_component_alarm_get_attendees:
953  * @alarm: an #ECalComponentAlarm
954  *
955  * Get the list of attendees, as #ECalComponentAttendee.
956  * The returned #GSList is owned by @alarm and should not be modified,
957  * neither its content.
958  *
959  * Returns: (transfer none) (nullable) (element-type ECalComponentAttendee): the @alarm attendees,
960  *    as a #GSList of an #ECalComponentAttendee, or %NULL when, none are set
961  *
962  * Since: 3.34
963  **/
964 GSList *
e_cal_component_alarm_get_attendees(const ECalComponentAlarm * alarm)965 e_cal_component_alarm_get_attendees (const ECalComponentAlarm *alarm)
966 {
967 	g_return_val_if_fail (alarm != NULL, NULL);
968 
969 	return alarm->attendees;
970 }
971 
972 /**
973  * e_cal_component_alarm_set_attendees:
974  * @alarm: an #ECalComponentAlarm
975  * @attendees: (transfer none) (nullable) (element-type ECalComponentAttendee): a #GSList
976  *    of an #ECalComponentAttendee objects to set as attendees, or %NULL to unset
977  *
978  * Set the list of attendees, as a #GSList of an #ECalComponentAttendee.
979  *
980  * Since: 3.34
981  **/
982 void
e_cal_component_alarm_set_attendees(ECalComponentAlarm * alarm,const GSList * attendees)983 e_cal_component_alarm_set_attendees (ECalComponentAlarm *alarm,
984 				     const GSList *attendees)
985 {
986 	GSList *to_take = NULL, *link;
987 
988 	g_return_if_fail (alarm != NULL);
989 
990 	if (alarm->attendees == attendees)
991 		return;
992 
993 	for (link = (GSList *) attendees; link; link = g_slist_next (link)) {
994 		ECalComponentAttendee *attendee = link->data;
995 
996 		if (attendee)
997 			to_take = g_slist_prepend (to_take, e_cal_component_attendee_copy (attendee));
998 	}
999 
1000 	to_take = g_slist_reverse (to_take);
1001 
1002 	e_cal_component_alarm_take_attendees (alarm, to_take);
1003 }
1004 
1005 /**
1006  * e_cal_component_alarm_take_attendees: (skip)
1007  * @alarm: an #ECalComponentAlarm
1008  * @attendees: (transfer full) (nullable) (element-type ECalComponentAttendee): a #GSList
1009  *    of an #ECalComponentAttendee objects to set as attendees, or %NULL to unset
1010  *
1011  * Sets the list of attendees, as a #GSList of an #ECalComponentAttendee and assumes
1012  * ownership of the @attendees and its content.
1013  *
1014  * Since: 3.34
1015  **/
1016 void
e_cal_component_alarm_take_attendees(ECalComponentAlarm * alarm,GSList * attendees)1017 e_cal_component_alarm_take_attendees (ECalComponentAlarm *alarm,
1018 				      GSList *attendees)
1019 {
1020 	g_return_if_fail (alarm != NULL);
1021 
1022 	if (alarm->attendees != attendees) {
1023 		g_slist_free_full (alarm->attendees, e_cal_component_attendee_free);
1024 		alarm->attendees = attendees;
1025 	}
1026 }
1027 
1028 /**
1029  * e_cal_component_alarm_has_attachments:
1030  * @alarm: an #ECalComponentAlarm
1031  *
1032  * Returns: whether the @alarm has any attachments
1033  *
1034  * Since: 3.34
1035  **/
1036 gboolean
e_cal_component_alarm_has_attachments(const ECalComponentAlarm * alarm)1037 e_cal_component_alarm_has_attachments (const ECalComponentAlarm *alarm)
1038 {
1039 	g_return_val_if_fail (alarm != NULL, FALSE);
1040 
1041 	return alarm->attachments != NULL;
1042 }
1043 
1044 /**
1045  * e_cal_component_alarm_get_attachments:
1046  * @alarm: an #ECalComponentAlarm
1047  *
1048  * Get the list of attachments, as #ICalAttach.
1049  * The returned #GSList is owned by @alarm and should not be modified,
1050  * neither its content.
1051  *
1052  * Returns: (transfer none) (nullable) (element-type ICalAttach): the @alarm attachments,
1053  *    as a #GSList of an #ICalAttach, or %NULL, when none is set
1054  *
1055  * Since: 3.34
1056  **/
1057 GSList *
e_cal_component_alarm_get_attachments(const ECalComponentAlarm * alarm)1058 e_cal_component_alarm_get_attachments (const ECalComponentAlarm *alarm)
1059 {
1060 	g_return_val_if_fail (alarm != NULL, NULL);
1061 
1062 	return alarm->attachments;
1063 }
1064 
1065 /**
1066  * e_cal_component_alarm_set_attachments:
1067  * @alarm: an #ECalComponentAlarm
1068  * @attachments: (transfer none) (nullable) (element-type ICalAttach): a #GSList
1069  *    of an #ICalAttach objects to set as attachments, or %NULL to unset
1070  *
1071  * Set the list of attachments, as a #GSList of an #ICalAttach.
1072  *
1073  * Since: 3.34
1074  **/
1075 void
e_cal_component_alarm_set_attachments(ECalComponentAlarm * alarm,const GSList * attachments)1076 e_cal_component_alarm_set_attachments (ECalComponentAlarm *alarm,
1077 				       const GSList *attachments)
1078 {
1079 	GSList *to_take = NULL, *link;
1080 
1081 	g_return_if_fail (alarm != NULL);
1082 
1083 	if (alarm->attachments == attachments)
1084 		return;
1085 
1086 	for (link = (GSList *) attachments; link; link = g_slist_next (link)) {
1087 		ICalAttach *attach = link->data;
1088 
1089 		if (attach)
1090 			to_take = g_slist_prepend (to_take, g_object_ref (attach));
1091 	}
1092 
1093 	to_take = g_slist_reverse (to_take);
1094 
1095 	e_cal_component_alarm_take_attachments (alarm, to_take);
1096 }
1097 
1098 /**
1099  * e_cal_component_alarm_take_attachments: (skip)
1100  * @alarm: an #ECalComponentAlarm
1101  * @attachments: (transfer full) (nullable) (element-type ICalAttach): a #GSList
1102  *    of an #ICalAttach objects to set as attachments, or %NULL to unset
1103  *
1104  * Sets the list of attachments, as a #GSList of an #ICalAttach and assumes
1105  * ownership of the @attachments and its content.
1106  *
1107  * Since: 3.34
1108  **/
1109 void
e_cal_component_alarm_take_attachments(ECalComponentAlarm * alarm,GSList * attachments)1110 e_cal_component_alarm_take_attachments (ECalComponentAlarm *alarm,
1111 					GSList *attachments)
1112 {
1113 	g_return_if_fail (alarm != NULL);
1114 
1115 	if (alarm->attachments != attachments) {
1116 		g_slist_free_full (alarm->attachments, g_object_unref);
1117 		alarm->attachments = attachments;
1118 	}
1119 }
1120 
1121 /**
1122  * e_cal_component_alarm_get_property_bag:
1123  * @alarm: an #ECalComponentAlarm
1124  *
1125  * Returns: (transfer none): an #ECalComponentPropertyBag with additional
1126  *    properties stored with an alarm component, other than those accessible
1127  *    with the other functions of the @alarm.
1128  *
1129  * Since: 3.34
1130  **/
1131 ECalComponentPropertyBag *
e_cal_component_alarm_get_property_bag(const ECalComponentAlarm * alarm)1132 e_cal_component_alarm_get_property_bag (const ECalComponentAlarm *alarm)
1133 {
1134 	g_return_val_if_fail (alarm != NULL, NULL);
1135 
1136 	return alarm->property_bag;
1137 }
1138 
1139 /**
1140  * e_cal_component_alarm_get_acknowledged:
1141  * @alarm: an #ECalComponentAlarm
1142  *
1143  * Get the last time the alarm had been acknowledged, that is, when its
1144  * reminder had been triggered.
1145  * The returned #ICalTime is owned by @alarm and should not be modified,
1146  * neither its content.
1147  *
1148  * Returns: (transfer none) (nullable): the @alarm acknowledged time,
1149  *    or %NULL, when none is set
1150  *
1151  * Since: 3.40
1152  **/
1153 ICalTime *
e_cal_component_alarm_get_acknowledged(const ECalComponentAlarm * alarm)1154 e_cal_component_alarm_get_acknowledged (const ECalComponentAlarm *alarm)
1155 {
1156 	g_return_val_if_fail (alarm != NULL, NULL);
1157 
1158 	return alarm->acknowledged;
1159 }
1160 
1161 /**
1162  * e_cal_component_alarm_set_acknowledged:
1163  * @alarm: an #ECalComponentAlarm
1164  * @when: (transfer none) (nullable): an #ICalTime when the @alarm
1165  *    had been acknowledged, or %NULL to unset
1166  *
1167  * Set the acknowledged time of the @alarm. Use %NULL to unset it.
1168  *
1169  * Since: 3.40
1170  **/
1171 void
e_cal_component_alarm_set_acknowledged(ECalComponentAlarm * alarm,const ICalTime * when)1172 e_cal_component_alarm_set_acknowledged (ECalComponentAlarm *alarm,
1173 					const ICalTime *when)
1174 {
1175 	g_return_if_fail (alarm != NULL);
1176 
1177 	if (when != alarm->acknowledged)
1178 		e_cal_component_alarm_take_acknowledged (alarm, when ? i_cal_time_clone (when) : NULL);
1179 }
1180 
1181 /**
1182  * e_cal_component_alarm_take_acknowledged:
1183  * @alarm: an #ECalComponentAlarm
1184  * @when: (transfer full) (nullable): an #ICalTime when the @alarm
1185  *    had been acknowledged, or %NULL to unset
1186  *
1187  * Set the acknowledged time of the @alarm. Use %NULL to unset it.
1188  * The function assumes ownership of the @when.
1189  *
1190  * Since: 3.40
1191  **/
1192 void
e_cal_component_alarm_take_acknowledged(ECalComponentAlarm * alarm,ICalTime * when)1193 e_cal_component_alarm_take_acknowledged (ECalComponentAlarm *alarm,
1194 					 ICalTime *when)
1195 {
1196 	g_return_if_fail (alarm != NULL);
1197 
1198 	if (when != alarm->acknowledged) {
1199 		g_clear_object (&alarm->acknowledged);
1200 		alarm->acknowledged = when;
1201 	} else {
1202 		g_clear_object (&when);
1203 	}
1204 }
1205