1 /*
2 * Evolution calendar - Data model for ETable
3 *
4 * This program 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 program 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 program; if not, see <http://www.gnu.org/licenses/>.
15 *
16 *
17 * Authors:
18 * Rodrigo Moya <rodrigo@ximian.com>
19 *
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21 *
22 */
23
24 #include "evolution-config.h"
25
26 #include <string.h>
27 #include <glib/gi18n.h>
28
29 #include <libebackend/libebackend.h>
30
31 #include <e-util/e-util.h>
32 #include <e-util/e-util-enumtypes.h>
33
34 #include "comp-util.h"
35 #include "e-cal-data-model-subscriber.h"
36 #include "e-cal-dialogs.h"
37 #include "e-cal-ops.h"
38 #include "itip-utils.h"
39 #include "misc.h"
40
41 #include "e-cal-model.h"
42
43 struct _ECalModelComponentPrivate {
44 GString *categories_str;
45 gint icon_index;
46 };
47
48 #define E_CAL_MODEL_GET_PRIVATE(obj) \
49 (G_TYPE_INSTANCE_GET_PRIVATE \
50 ((obj), E_TYPE_CAL_MODEL, ECalModelPrivate))
51
52 #define E_CAL_MODEL_COMPONENT_GET_PRIVATE(obj) \
53 (G_TYPE_INSTANCE_GET_PRIVATE \
54 ((obj), E_TYPE_CAL_MODEL_COMPONENT, ECalModelComponentPrivate))
55
56 struct _ECalModelPrivate {
57 ECalDataModel *data_model;
58 ESourceRegistry *registry;
59 EShell *shell;
60 EClientCache *client_cache;
61
62 /* The default source uid of an ECalClient */
63 gchar *default_source_uid;
64
65 /* Array for storing the objects. Each element is of type ECalModelComponent */
66 GPtrArray *objects;
67
68 ICalComponentKind kind;
69 ICalTimezone *zone;
70
71 /* The time range to display */
72 time_t start;
73 time_t end;
74
75 /* The search regular expression */
76 gchar *search_sexp;
77
78 /* The default category */
79 gchar *default_category;
80
81 /* Whether we display dates in 24-hour format. */
82 gboolean use_24_hour_format;
83
84 /* Whether to compress weekends into one cell. */
85 gboolean compress_weekend;
86
87 /* First day of the week */
88 GDateWeekday week_start_day;
89
90 /* Work days. Indices are based on GDateWeekday.
91 * The first element (G_DATE_BAD_WEEKDAY) is unused. */
92 gboolean work_days[G_DATE_SUNDAY + 1];
93
94 /* Work day timespan */
95 gint work_day_start_hour;
96 gint work_day_start_minute;
97 gint work_day_end_hour;
98 gint work_day_end_minute;
99 gint work_day_start_mon;
100 gint work_day_end_mon;
101 gint work_day_start_tue;
102 gint work_day_end_tue;
103 gint work_day_start_wed;
104 gint work_day_end_wed;
105 gint work_day_start_thu;
106 gint work_day_end_thu;
107 gint work_day_start_fri;
108 gint work_day_end_fri;
109 gint work_day_start_sat;
110 gint work_day_end_sat;
111 gint work_day_start_sun;
112 gint work_day_end_sun;
113
114 /* callback, to retrieve start time for newly added rows by click-to-add */
115 ECalModelDefaultTimeFunc get_default_time;
116 gpointer get_default_time_user_data;
117
118 /* Default reminder for events */
119 gboolean use_default_reminder;
120 gint default_reminder_interval;
121 EDurationType default_reminder_units;
122
123 /* Ask user to confirm before deleting components. */
124 gboolean confirm_delete;
125 };
126
127 typedef struct {
128 const gchar *color;
129 GList *uids;
130 } AssignedColorData;
131
132 static const gchar *cal_model_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data);
133
134 enum {
135 PROP_0,
136 PROP_CLIENT_CACHE,
137 PROP_COMPRESS_WEEKEND,
138 PROP_CONFIRM_DELETE,
139 PROP_DATA_MODEL,
140 PROP_DEFAULT_REMINDER_INTERVAL,
141 PROP_DEFAULT_REMINDER_UNITS,
142 PROP_DEFAULT_SOURCE_UID,
143 PROP_REGISTRY,
144 PROP_SHELL,
145 PROP_TIMEZONE,
146 PROP_USE_24_HOUR_FORMAT,
147 PROP_USE_DEFAULT_REMINDER,
148 PROP_WEEK_START_DAY,
149 PROP_WORK_DAY_MONDAY,
150 PROP_WORK_DAY_TUESDAY,
151 PROP_WORK_DAY_WEDNESDAY,
152 PROP_WORK_DAY_THURSDAY,
153 PROP_WORK_DAY_FRIDAY,
154 PROP_WORK_DAY_SATURDAY,
155 PROP_WORK_DAY_SUNDAY,
156 PROP_WORK_DAY_END_HOUR,
157 PROP_WORK_DAY_END_MINUTE,
158 PROP_WORK_DAY_START_HOUR,
159 PROP_WORK_DAY_START_MINUTE,
160 PROP_WORK_DAY_START_MON,
161 PROP_WORK_DAY_END_MON,
162 PROP_WORK_DAY_START_TUE,
163 PROP_WORK_DAY_END_TUE,
164 PROP_WORK_DAY_START_WED,
165 PROP_WORK_DAY_END_WED,
166 PROP_WORK_DAY_START_THU,
167 PROP_WORK_DAY_END_THU,
168 PROP_WORK_DAY_START_FRI,
169 PROP_WORK_DAY_END_FRI,
170 PROP_WORK_DAY_START_SAT,
171 PROP_WORK_DAY_END_SAT,
172 PROP_WORK_DAY_START_SUN,
173 PROP_WORK_DAY_END_SUN
174 };
175
176 enum {
177 TIME_RANGE_CHANGED,
178 ROW_APPENDED,
179 COMPS_DELETED,
180 TIMEZONE_CHANGED,
181 OBJECT_CREATED,
182 LAST_SIGNAL
183 };
184
185 /* Forward Declarations */
186 static void e_cal_model_table_model_init (ETableModelInterface *iface);
187 static void e_cal_model_cal_data_model_subscriber_init (ECalDataModelSubscriberInterface *iface);
188
189 static guint signals[LAST_SIGNAL];
190
G_DEFINE_ABSTRACT_TYPE_WITH_CODE(ECalModel,e_cal_model,G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE,NULL)G_IMPLEMENT_INTERFACE (E_TYPE_TABLE_MODEL,e_cal_model_table_model_init)G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER,e_cal_model_cal_data_model_subscriber_init))191 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ECalModel, e_cal_model, G_TYPE_OBJECT,
192 G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)
193 G_IMPLEMENT_INTERFACE (E_TYPE_TABLE_MODEL, e_cal_model_table_model_init)
194 G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER, e_cal_model_cal_data_model_subscriber_init))
195
196 G_DEFINE_TYPE (ECalModelComponent, e_cal_model_component, G_TYPE_OBJECT)
197
198 static void
199 e_cal_model_component_set_icalcomponent (ECalModelComponent *comp_data,
200 ECalModel *model,
201 ICalComponent *icomp)
202 {
203 if (model != NULL)
204 g_return_if_fail (E_IS_CAL_MODEL (model));
205 g_return_if_fail (comp_data != NULL);
206
207 g_clear_object (&comp_data->icalcomp);
208 comp_data->icalcomp = icomp;
209
210 if (comp_data->priv->categories_str)
211 g_string_free (comp_data->priv->categories_str, TRUE);
212 comp_data->priv->categories_str = NULL;
213 comp_data->priv->icon_index = -1;
214
215 g_clear_pointer (&comp_data->dtstart, e_cell_date_edit_value_free);
216 g_clear_pointer (&comp_data->dtend, e_cell_date_edit_value_free);
217 g_clear_pointer (&comp_data->due, e_cell_date_edit_value_free);
218 g_clear_pointer (&comp_data->completed, e_cell_date_edit_value_free);
219 g_clear_pointer (&comp_data->created, e_cell_date_edit_value_free);
220 g_clear_pointer (&comp_data->lastmodified, e_cell_date_edit_value_free);
221 g_clear_pointer (&comp_data->color, g_free);
222
223 if (comp_data->icalcomp && model)
224 e_cal_model_set_instance_times (comp_data, model->priv->zone);
225 }
226
227 static void
e_cal_model_component_finalize(GObject * object)228 e_cal_model_component_finalize (GObject *object)
229 {
230 ECalModelComponent *comp_data = E_CAL_MODEL_COMPONENT (object);
231
232 g_clear_object (&comp_data->client);
233
234 e_cal_model_component_set_icalcomponent (comp_data, NULL, NULL);
235
236 /* Chain up to parent's finalize() method. */
237 G_OBJECT_CLASS (e_cal_model_component_parent_class)->finalize (object);
238 }
239
240 /* Class initialization function for the calendar component object */
241 static void
e_cal_model_component_class_init(ECalModelComponentClass * class)242 e_cal_model_component_class_init (ECalModelComponentClass *class)
243 {
244 GObjectClass *object_class;
245
246 object_class = (GObjectClass *) class;
247 g_type_class_add_private (class, sizeof (ECalModelComponentPrivate));
248
249 object_class->finalize = e_cal_model_component_finalize;
250 }
251
252 static void
e_cal_model_component_init(ECalModelComponent * comp)253 e_cal_model_component_init (ECalModelComponent *comp)
254 {
255 comp->priv = E_CAL_MODEL_COMPONENT_GET_PRIVATE (comp);
256 comp->priv->icon_index = -1;
257 comp->is_new_component = FALSE;
258 }
259
260 static gpointer
get_categories(ECalModelComponent * comp_data)261 get_categories (ECalModelComponent *comp_data)
262 {
263 if (!comp_data->priv->categories_str) {
264 ICalProperty *prop;
265
266 comp_data->priv->categories_str = g_string_new ("");
267
268 for (prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_CATEGORIES_PROPERTY);
269 prop;
270 g_object_unref (prop), prop = i_cal_component_get_next_property (comp_data->icalcomp, I_CAL_CATEGORIES_PROPERTY)) {
271 const gchar *categories = i_cal_property_get_categories (prop);
272 if (!categories)
273 continue;
274
275 if (comp_data->priv->categories_str->len)
276 g_string_append_c (comp_data->priv->categories_str, ',');
277 g_string_append (comp_data->priv->categories_str, categories);
278 }
279 }
280
281 return g_strdup (comp_data->priv->categories_str->str);
282 }
283
284 static gchar *
get_classification(ECalModelComponent * comp_data)285 get_classification (ECalModelComponent *comp_data)
286 {
287 ICalProperty *prop;
288 ICalProperty_Class class_prop;
289
290 prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_CLASS_PROPERTY);
291
292 if (!prop)
293 return _("Public");
294
295 class_prop = i_cal_property_get_class (prop);
296
297 g_clear_object (&prop);
298
299 switch (class_prop) {
300 case I_CAL_CLASS_PUBLIC:
301 return _("Public");
302 case I_CAL_CLASS_PRIVATE:
303 return _("Private");
304 case I_CAL_CLASS_CONFIDENTIAL:
305 return _("Confidential");
306 default:
307 return _("Unknown");
308 }
309 }
310
311 static const gchar *
get_color(ECalModel * model,ECalModelComponent * comp_data)312 get_color (ECalModel *model,
313 ECalModelComponent *comp_data)
314 {
315 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
316
317 return e_cal_model_get_color_for_component (model, comp_data);
318 }
319
320 static gpointer
get_description(ECalModelComponent * comp_data)321 get_description (ECalModelComponent *comp_data)
322 {
323 ICalProperty *prop;
324 GString *str = NULL;
325
326 for (prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_DESCRIPTION_PROPERTY);
327 prop;
328 g_object_unref (prop), prop = i_cal_component_get_next_property (comp_data->icalcomp, I_CAL_DESCRIPTION_PROPERTY)) {
329 if (!str)
330 str = g_string_new (NULL);
331 g_string_append (str, i_cal_property_get_description (prop));
332 }
333
334 return str ? g_string_free (str, FALSE) : g_strdup ("");
335 }
336
337 static ECellDateEditValue *
get_dtstart(ECalModel * model,ECalModelComponent * comp_data)338 get_dtstart (ECalModel *model,
339 ECalModelComponent *comp_data)
340 {
341 if (!comp_data->dtstart) {
342 comp_data->dtstart = e_cal_model_util_get_datetime_value (model, comp_data,
343 I_CAL_DTSTART_PROPERTY, i_cal_property_get_dtstart);
344 }
345
346 return e_cell_date_edit_value_copy (comp_data->dtstart);
347 }
348
349 static ECellDateEditValue *
get_datetime_from_utc(ECalModel * model,ECalModelComponent * comp_data,ICalPropertyKind propkind,ICalTime * (* get_value)(ICalProperty * prop),ECellDateEditValue ** buffer)350 get_datetime_from_utc (ECalModel *model,
351 ECalModelComponent *comp_data,
352 ICalPropertyKind propkind,
353 ICalTime * (*get_value) (ICalProperty *prop),
354 ECellDateEditValue **buffer)
355 {
356 g_return_val_if_fail (buffer != NULL, NULL);
357
358 if (!*buffer) {
359 ECalModelPrivate *priv;
360 ICalTime *tt_value;
361 ICalProperty *prop;
362
363 priv = model->priv;
364
365 prop = i_cal_component_get_first_property (comp_data->icalcomp, propkind);
366 if (!prop)
367 return NULL;
368
369 tt_value = get_value (prop);
370
371 /* these are always in UTC, thus convert to default zone, if any and done */
372 if (priv->zone)
373 i_cal_time_convert_timezone (tt_value, i_cal_timezone_get_utc_timezone (), priv->zone);
374
375 g_object_unref (prop);
376
377 if (!i_cal_time_is_valid_time (tt_value) || i_cal_time_is_null_time (tt_value)) {
378 g_clear_object (&tt_value);
379 return NULL;
380 }
381
382 *buffer = e_cell_date_edit_value_new_take (tt_value, NULL);
383 }
384
385 return e_cell_date_edit_value_copy (*buffer);
386 }
387
388 static gpointer
get_summary(ECalModelComponent * comp_data)389 get_summary (ECalModelComponent *comp_data)
390 {
391 ICalProperty *prop;
392 gchar *res = NULL;
393
394 prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_SUMMARY_PROPERTY);
395 if (prop)
396 res = g_strdup (i_cal_property_get_summary (prop));
397
398 g_clear_object (&prop);
399
400 if (!res)
401 res = g_strdup ("");
402
403 e_cal_model_until_sanitize_text_value (res, -1);
404
405 return res;
406 }
407
408 static gchar *
get_uid(ECalModelComponent * comp_data)409 get_uid (ECalModelComponent *comp_data)
410 {
411 return (gchar *) i_cal_component_get_uid (comp_data->icalcomp);
412 }
413
414 static gchar *
get_source_description(ESourceRegistry * registry,ECalModelComponent * comp_data)415 get_source_description (ESourceRegistry *registry,
416 ECalModelComponent *comp_data)
417 {
418 if (!registry || !comp_data || !comp_data->client)
419 return NULL;
420
421 return e_util_get_source_full_name (registry, e_client_get_source (E_CLIENT (comp_data->client)));
422 }
423
424 static void
set_categories(ECalModelComponent * comp_data,const gchar * value)425 set_categories (ECalModelComponent *comp_data,
426 const gchar *value)
427 {
428 ICalProperty *prop;
429
430 /* remove all categories first */
431 e_cal_util_component_remove_property_by_kind (comp_data->icalcomp, I_CAL_CATEGORIES_PROPERTY, TRUE);
432
433 if (comp_data->priv->categories_str)
434 g_string_free (comp_data->priv->categories_str, TRUE);
435 comp_data->priv->categories_str = NULL;
436
437 /* then set a new value; no need to populate categories_str,
438 * it'll be populated on demand (in the get_categories() function)
439 */
440 if (value && *value) {
441 prop = i_cal_property_new_categories (value);
442 i_cal_component_take_property (comp_data->icalcomp, prop);
443 }
444 }
445
446 static void
set_classification(ECalModelComponent * comp_data,const gchar * value)447 set_classification (ECalModelComponent *comp_data,
448 const gchar *value)
449 {
450 ICalProperty *prop;
451
452 prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_CLASS_PROPERTY);
453 if (!value || !(*value)) {
454 if (prop) {
455 i_cal_component_remove_property (comp_data->icalcomp, prop);
456 g_clear_object (&prop);
457 }
458 } else {
459 ICalProperty_Class ical_class;
460
461 if (!g_ascii_strcasecmp (value, "PUBLIC"))
462 ical_class = I_CAL_CLASS_PUBLIC;
463 else if (!g_ascii_strcasecmp (value, "PRIVATE"))
464 ical_class = I_CAL_CLASS_PRIVATE;
465 else if (!g_ascii_strcasecmp (value, "CONFIDENTIAL"))
466 ical_class = I_CAL_CLASS_CONFIDENTIAL;
467 else
468 ical_class = I_CAL_CLASS_NONE;
469
470 if (!prop) {
471 prop = i_cal_property_new_class (ical_class);
472 i_cal_component_take_property (comp_data->icalcomp, prop);
473 } else {
474 i_cal_property_set_class (prop, ical_class);
475 g_clear_object (&prop);
476 }
477 }
478 }
479
480 static void
set_description(ECalModelComponent * comp_data,const gchar * value)481 set_description (ECalModelComponent *comp_data,
482 const gchar *value)
483 {
484 ICalProperty *prop;
485
486 /* remove old description(s) */
487 e_cal_util_component_remove_property_by_kind (comp_data->icalcomp, I_CAL_DESCRIPTION_PROPERTY, TRUE);
488
489 /* now add the new description */
490 if (!value || !(*value))
491 return;
492
493 prop = i_cal_property_new_description (value);
494 i_cal_component_take_property (comp_data->icalcomp, prop);
495 }
496
497 static void
set_dtstart(ECalModel * model,ECalModelComponent * comp_data,gconstpointer value)498 set_dtstart (ECalModel *model,
499 ECalModelComponent *comp_data,
500 gconstpointer value)
501 {
502 e_cal_model_update_comp_time (
503 model, comp_data, value,
504 I_CAL_DTSTART_PROPERTY,
505 i_cal_property_set_dtstart,
506 i_cal_property_new_dtstart);
507 }
508
509 static void
set_summary(ECalModelComponent * comp_data,const gchar * value)510 set_summary (ECalModelComponent *comp_data,
511 const gchar *value)
512 {
513 ICalProperty *prop;
514
515 prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_SUMMARY_PROPERTY);
516
517 if (string_is_empty (value)) {
518 if (prop) {
519 i_cal_component_remove_property (comp_data->icalcomp, prop);
520 g_clear_object (&prop);
521 }
522 } else {
523 if (prop) {
524 i_cal_property_set_summary (prop, value);
525 g_clear_object (&prop);
526 } else {
527 prop = i_cal_property_new_summary (value);
528 i_cal_component_take_property (comp_data->icalcomp, prop);
529 }
530 }
531 }
532
533 static void
datetime_to_zone(ECalClient * client,ICalTime * tt,ICalTimezone * tt_zone,const gchar * tzid)534 datetime_to_zone (ECalClient *client,
535 ICalTime *tt,
536 ICalTimezone *tt_zone,
537 const gchar *tzid)
538 {
539 ICalTimezone *from, *to;
540 const gchar *tt_tzid = NULL;
541
542 g_return_if_fail (tt != NULL);
543
544 if (tt_zone)
545 tt_tzid = i_cal_timezone_get_tzid (tt_zone);
546
547 if (tt_tzid == NULL || tzid == NULL ||
548 tt_tzid == tzid || g_str_equal (tt_tzid, tzid))
549 return;
550
551 from = tt_zone;
552 to = i_cal_timezone_get_builtin_timezone_from_tzid (tzid);
553 if (!to) {
554 /* do not abort on failure here, maybe the zone is not available there */
555 if (!e_cal_client_get_timezone_sync (client, tzid, &to, NULL, NULL))
556 to = NULL;
557 }
558
559 i_cal_time_convert_timezone (tt, from, to);
560 }
561
562 static void
cal_model_set_data_model(ECalModel * model,ECalDataModel * data_model)563 cal_model_set_data_model (ECalModel *model,
564 ECalDataModel *data_model)
565 {
566 g_return_if_fail (E_IS_CAL_DATA_MODEL (data_model));
567 g_return_if_fail (model->priv->data_model == NULL);
568
569 /* Be aware of a circular dependency, once this @model is subscribed to
570 the @data_model, then the @data_model increases reference count
571 of the @model.
572 */
573 model->priv->data_model = g_object_ref (data_model);
574 }
575
576 static void
cal_model_set_registry(ECalModel * model,ESourceRegistry * registry)577 cal_model_set_registry (ECalModel *model,
578 ESourceRegistry *registry)
579 {
580 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
581 g_return_if_fail (model->priv->registry == NULL);
582
583 model->priv->registry = g_object_ref (registry);
584 }
585
586 static void
cal_model_set_shell(ECalModel * model,EShell * shell)587 cal_model_set_shell (ECalModel *model,
588 EShell *shell)
589 {
590 EClientCache *client_cache;
591
592 g_return_if_fail (E_IS_SHELL (shell));
593 g_return_if_fail (model->priv->shell == NULL);
594
595 model->priv->shell = g_object_ref (shell);
596
597 client_cache = e_shell_get_client_cache (shell);
598
599 g_return_if_fail (E_IS_CLIENT_CACHE (client_cache));
600 g_return_if_fail (model->priv->client_cache == NULL);
601
602 model->priv->client_cache = g_object_ref (client_cache);
603 }
604
605 static void
cal_model_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)606 cal_model_set_property (GObject *object,
607 guint property_id,
608 const GValue *value,
609 GParamSpec *pspec)
610 {
611 switch (property_id) {
612 case PROP_COMPRESS_WEEKEND:
613 e_cal_model_set_compress_weekend (
614 E_CAL_MODEL (object),
615 g_value_get_boolean (value));
616 return;
617
618 case PROP_CONFIRM_DELETE:
619 e_cal_model_set_confirm_delete (
620 E_CAL_MODEL (object),
621 g_value_get_boolean (value));
622 return;
623
624 case PROP_DATA_MODEL:
625 cal_model_set_data_model (
626 E_CAL_MODEL (object),
627 g_value_get_object (value));
628 return;
629
630 case PROP_DEFAULT_SOURCE_UID:
631 e_cal_model_set_default_source_uid (
632 E_CAL_MODEL (object),
633 g_value_get_string (value));
634 return;
635
636 case PROP_DEFAULT_REMINDER_INTERVAL:
637 e_cal_model_set_default_reminder_interval (
638 E_CAL_MODEL (object),
639 g_value_get_int (value));
640 return;
641
642 case PROP_DEFAULT_REMINDER_UNITS:
643 e_cal_model_set_default_reminder_units (
644 E_CAL_MODEL (object),
645 g_value_get_enum (value));
646 return;
647
648 case PROP_REGISTRY:
649 cal_model_set_registry (
650 E_CAL_MODEL (object),
651 g_value_get_object (value));
652 return;
653
654 case PROP_SHELL:
655 cal_model_set_shell (
656 E_CAL_MODEL (object),
657 g_value_get_object (value));
658 return;
659
660 case PROP_TIMEZONE:
661 e_cal_model_set_timezone (
662 E_CAL_MODEL (object),
663 g_value_get_object (value));
664 return;
665
666 case PROP_USE_24_HOUR_FORMAT:
667 e_cal_model_set_use_24_hour_format (
668 E_CAL_MODEL (object),
669 g_value_get_boolean (value));
670 return;
671
672 case PROP_USE_DEFAULT_REMINDER:
673 e_cal_model_set_use_default_reminder (
674 E_CAL_MODEL (object),
675 g_value_get_boolean (value));
676 return;
677
678 case PROP_WEEK_START_DAY:
679 e_cal_model_set_week_start_day (
680 E_CAL_MODEL (object),
681 g_value_get_enum (value));
682 return;
683
684 case PROP_WORK_DAY_MONDAY:
685 e_cal_model_set_work_day (
686 E_CAL_MODEL (object),
687 G_DATE_MONDAY,
688 g_value_get_boolean (value));
689 return;
690
691 case PROP_WORK_DAY_TUESDAY:
692 e_cal_model_set_work_day (
693 E_CAL_MODEL (object),
694 G_DATE_TUESDAY,
695 g_value_get_boolean (value));
696 return;
697
698 case PROP_WORK_DAY_WEDNESDAY:
699 e_cal_model_set_work_day (
700 E_CAL_MODEL (object),
701 G_DATE_WEDNESDAY,
702 g_value_get_boolean (value));
703 return;
704
705 case PROP_WORK_DAY_THURSDAY:
706 e_cal_model_set_work_day (
707 E_CAL_MODEL (object),
708 G_DATE_THURSDAY,
709 g_value_get_boolean (value));
710 return;
711
712 case PROP_WORK_DAY_FRIDAY:
713 e_cal_model_set_work_day (
714 E_CAL_MODEL (object),
715 G_DATE_FRIDAY,
716 g_value_get_boolean (value));
717 return;
718
719 case PROP_WORK_DAY_SATURDAY:
720 e_cal_model_set_work_day (
721 E_CAL_MODEL (object),
722 G_DATE_SATURDAY,
723 g_value_get_boolean (value));
724 return;
725
726 case PROP_WORK_DAY_SUNDAY:
727 e_cal_model_set_work_day (
728 E_CAL_MODEL (object),
729 G_DATE_SUNDAY,
730 g_value_get_boolean (value));
731 return;
732
733 case PROP_WORK_DAY_END_HOUR:
734 e_cal_model_set_work_day_end_hour (
735 E_CAL_MODEL (object),
736 g_value_get_int (value));
737 return;
738
739 case PROP_WORK_DAY_END_MINUTE:
740 e_cal_model_set_work_day_end_minute (
741 E_CAL_MODEL (object),
742 g_value_get_int (value));
743 return;
744
745 case PROP_WORK_DAY_START_HOUR:
746 e_cal_model_set_work_day_start_hour (
747 E_CAL_MODEL (object),
748 g_value_get_int (value));
749 return;
750
751 case PROP_WORK_DAY_START_MINUTE:
752 e_cal_model_set_work_day_start_minute (
753 E_CAL_MODEL (object),
754 g_value_get_int (value));
755 return;
756
757 case PROP_WORK_DAY_START_MON:
758 e_cal_model_set_work_day_start_mon (
759 E_CAL_MODEL (object),
760 g_value_get_int (value));
761 return;
762
763 case PROP_WORK_DAY_END_MON:
764 e_cal_model_set_work_day_end_mon (
765 E_CAL_MODEL (object),
766 g_value_get_int (value));
767 return;
768
769 case PROP_WORK_DAY_START_TUE:
770 e_cal_model_set_work_day_start_tue (
771 E_CAL_MODEL (object),
772 g_value_get_int (value));
773 return;
774
775 case PROP_WORK_DAY_END_TUE:
776 e_cal_model_set_work_day_end_tue (
777 E_CAL_MODEL (object),
778 g_value_get_int (value));
779 return;
780
781 case PROP_WORK_DAY_START_WED:
782 e_cal_model_set_work_day_start_wed (
783 E_CAL_MODEL (object),
784 g_value_get_int (value));
785 return;
786
787 case PROP_WORK_DAY_END_WED:
788 e_cal_model_set_work_day_end_wed (
789 E_CAL_MODEL (object),
790 g_value_get_int (value));
791 return;
792
793 case PROP_WORK_DAY_START_THU:
794 e_cal_model_set_work_day_start_thu (
795 E_CAL_MODEL (object),
796 g_value_get_int (value));
797 return;
798
799 case PROP_WORK_DAY_END_THU:
800 e_cal_model_set_work_day_end_thu (
801 E_CAL_MODEL (object),
802 g_value_get_int (value));
803 return;
804
805 case PROP_WORK_DAY_START_FRI:
806 e_cal_model_set_work_day_start_fri (
807 E_CAL_MODEL (object),
808 g_value_get_int (value));
809 return;
810
811 case PROP_WORK_DAY_END_FRI:
812 e_cal_model_set_work_day_end_fri (
813 E_CAL_MODEL (object),
814 g_value_get_int (value));
815 return;
816
817 case PROP_WORK_DAY_START_SAT:
818 e_cal_model_set_work_day_start_sat (
819 E_CAL_MODEL (object),
820 g_value_get_int (value));
821 return;
822
823 case PROP_WORK_DAY_END_SAT:
824 e_cal_model_set_work_day_end_sat (
825 E_CAL_MODEL (object),
826 g_value_get_int (value));
827 return;
828
829 case PROP_WORK_DAY_START_SUN:
830 e_cal_model_set_work_day_start_sun (
831 E_CAL_MODEL (object),
832 g_value_get_int (value));
833 return;
834
835 case PROP_WORK_DAY_END_SUN:
836 e_cal_model_set_work_day_end_sun (
837 E_CAL_MODEL (object),
838 g_value_get_int (value));
839 return;
840 }
841
842 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
843 }
844
845 static void
cal_model_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)846 cal_model_get_property (GObject *object,
847 guint property_id,
848 GValue *value,
849 GParamSpec *pspec)
850 {
851 switch (property_id) {
852 case PROP_CLIENT_CACHE:
853 g_value_set_object (
854 value,
855 e_cal_model_get_client_cache (
856 E_CAL_MODEL (object)));
857 return;
858
859 case PROP_COMPRESS_WEEKEND:
860 g_value_set_boolean (
861 value,
862 e_cal_model_get_compress_weekend (
863 E_CAL_MODEL (object)));
864 return;
865
866 case PROP_CONFIRM_DELETE:
867 g_value_set_boolean (
868 value,
869 e_cal_model_get_confirm_delete (
870 E_CAL_MODEL (object)));
871 return;
872
873 case PROP_DATA_MODEL:
874 g_value_set_object (
875 value,
876 e_cal_model_get_data_model (
877 E_CAL_MODEL (object)));
878 return;
879
880 case PROP_DEFAULT_SOURCE_UID:
881 g_value_set_string (
882 value,
883 e_cal_model_get_default_source_uid (
884 E_CAL_MODEL (object)));
885 return;
886
887 case PROP_DEFAULT_REMINDER_INTERVAL:
888 g_value_set_int (
889 value,
890 e_cal_model_get_default_reminder_interval (
891 E_CAL_MODEL (object)));
892 return;
893
894 case PROP_DEFAULT_REMINDER_UNITS:
895 g_value_set_enum (
896 value,
897 e_cal_model_get_default_reminder_units (
898 E_CAL_MODEL (object)));
899 return;
900
901 case PROP_REGISTRY:
902 g_value_set_object (
903 value,
904 e_cal_model_get_registry (
905 E_CAL_MODEL (object)));
906 return;
907
908 case PROP_SHELL:
909 g_value_set_object (
910 value,
911 e_cal_model_get_shell (
912 E_CAL_MODEL (object)));
913 return;
914
915 case PROP_TIMEZONE:
916 g_value_set_object (
917 value,
918 e_cal_model_get_timezone (
919 E_CAL_MODEL (object)));
920 return;
921
922 case PROP_USE_24_HOUR_FORMAT:
923 g_value_set_boolean (
924 value,
925 e_cal_model_get_use_24_hour_format (
926 E_CAL_MODEL (object)));
927 return;
928
929 case PROP_USE_DEFAULT_REMINDER:
930 g_value_set_boolean (
931 value,
932 e_cal_model_get_use_default_reminder (
933 E_CAL_MODEL (object)));
934 return;
935
936 case PROP_WEEK_START_DAY:
937 g_value_set_enum (
938 value,
939 e_cal_model_get_week_start_day (
940 E_CAL_MODEL (object)));
941 return;
942
943 case PROP_WORK_DAY_MONDAY:
944 g_value_set_boolean (
945 value,
946 e_cal_model_get_work_day (
947 E_CAL_MODEL (object), G_DATE_MONDAY));
948 return;
949
950 case PROP_WORK_DAY_TUESDAY:
951 g_value_set_boolean (
952 value,
953 e_cal_model_get_work_day (
954 E_CAL_MODEL (object), G_DATE_TUESDAY));
955 return;
956
957 case PROP_WORK_DAY_WEDNESDAY:
958 g_value_set_boolean (
959 value,
960 e_cal_model_get_work_day (
961 E_CAL_MODEL (object), G_DATE_WEDNESDAY));
962 return;
963
964 case PROP_WORK_DAY_THURSDAY:
965 g_value_set_boolean (
966 value,
967 e_cal_model_get_work_day (
968 E_CAL_MODEL (object), G_DATE_THURSDAY));
969 return;
970
971 case PROP_WORK_DAY_FRIDAY:
972 g_value_set_boolean (
973 value,
974 e_cal_model_get_work_day (
975 E_CAL_MODEL (object), G_DATE_FRIDAY));
976 return;
977
978 case PROP_WORK_DAY_SATURDAY:
979 g_value_set_boolean (
980 value,
981 e_cal_model_get_work_day (
982 E_CAL_MODEL (object), G_DATE_SATURDAY));
983 return;
984
985 case PROP_WORK_DAY_SUNDAY:
986 g_value_set_boolean (
987 value,
988 e_cal_model_get_work_day (
989 E_CAL_MODEL (object), G_DATE_SUNDAY));
990 return;
991
992 case PROP_WORK_DAY_END_HOUR:
993 g_value_set_int (
994 value,
995 e_cal_model_get_work_day_end_hour (
996 E_CAL_MODEL (object)));
997 return;
998
999 case PROP_WORK_DAY_END_MINUTE:
1000 g_value_set_int (
1001 value,
1002 e_cal_model_get_work_day_end_minute (
1003 E_CAL_MODEL (object)));
1004 return;
1005
1006 case PROP_WORK_DAY_START_HOUR:
1007 g_value_set_int (
1008 value,
1009 e_cal_model_get_work_day_start_hour (
1010 E_CAL_MODEL (object)));
1011 return;
1012
1013 case PROP_WORK_DAY_START_MINUTE:
1014 g_value_set_int (
1015 value,
1016 e_cal_model_get_work_day_start_minute (
1017 E_CAL_MODEL (object)));
1018 return;
1019
1020 case PROP_WORK_DAY_START_MON:
1021 g_value_set_int (
1022 value,
1023 e_cal_model_get_work_day_start_mon (
1024 E_CAL_MODEL (object)));
1025 return;
1026
1027 case PROP_WORK_DAY_END_MON:
1028 g_value_set_int (
1029 value,
1030 e_cal_model_get_work_day_end_mon (
1031 E_CAL_MODEL (object)));
1032 return;
1033
1034 case PROP_WORK_DAY_START_TUE:
1035 g_value_set_int (
1036 value,
1037 e_cal_model_get_work_day_start_tue (
1038 E_CAL_MODEL (object)));
1039 return;
1040
1041 case PROP_WORK_DAY_END_TUE:
1042 g_value_set_int (
1043 value,
1044 e_cal_model_get_work_day_end_tue (
1045 E_CAL_MODEL (object)));
1046 return;
1047
1048 case PROP_WORK_DAY_START_WED:
1049 g_value_set_int (
1050 value,
1051 e_cal_model_get_work_day_start_wed (
1052 E_CAL_MODEL (object)));
1053 return;
1054
1055 case PROP_WORK_DAY_END_WED:
1056 g_value_set_int (
1057 value,
1058 e_cal_model_get_work_day_end_wed (
1059 E_CAL_MODEL (object)));
1060 return;
1061
1062 case PROP_WORK_DAY_START_THU:
1063 g_value_set_int (
1064 value,
1065 e_cal_model_get_work_day_start_thu (
1066 E_CAL_MODEL (object)));
1067 return;
1068
1069 case PROP_WORK_DAY_END_THU:
1070 g_value_set_int (
1071 value,
1072 e_cal_model_get_work_day_end_thu (
1073 E_CAL_MODEL (object)));
1074 return;
1075
1076 case PROP_WORK_DAY_START_FRI:
1077 g_value_set_int (
1078 value,
1079 e_cal_model_get_work_day_start_fri (
1080 E_CAL_MODEL (object)));
1081 return;
1082
1083 case PROP_WORK_DAY_END_FRI:
1084 g_value_set_int (
1085 value,
1086 e_cal_model_get_work_day_end_fri (
1087 E_CAL_MODEL (object)));
1088 return;
1089
1090 case PROP_WORK_DAY_START_SAT:
1091 g_value_set_int (
1092 value,
1093 e_cal_model_get_work_day_start_sat (
1094 E_CAL_MODEL (object)));
1095 return;
1096
1097 case PROP_WORK_DAY_END_SAT:
1098 g_value_set_int (
1099 value,
1100 e_cal_model_get_work_day_end_sat (
1101 E_CAL_MODEL (object)));
1102 return;
1103
1104 case PROP_WORK_DAY_START_SUN:
1105 g_value_set_int (
1106 value,
1107 e_cal_model_get_work_day_start_sun (
1108 E_CAL_MODEL (object)));
1109 return;
1110
1111 case PROP_WORK_DAY_END_SUN:
1112 g_value_set_int (
1113 value,
1114 e_cal_model_get_work_day_end_sun (
1115 E_CAL_MODEL (object)));
1116 return;
1117 }
1118
1119 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1120 }
1121
1122 static void
cal_model_constructed(GObject * object)1123 cal_model_constructed (GObject *object)
1124 {
1125 e_extensible_load_extensions (E_EXTENSIBLE (object));
1126
1127 /* Chain up to parent's constructed() method. */
1128 G_OBJECT_CLASS (e_cal_model_parent_class)->constructed (object);
1129 }
1130
1131 static void
cal_model_dispose(GObject * object)1132 cal_model_dispose (GObject *object)
1133 {
1134 ECalModelPrivate *priv;
1135
1136 priv = E_CAL_MODEL_GET_PRIVATE (object);
1137
1138 g_clear_object (&priv->data_model);
1139 g_clear_object (&priv->registry);
1140 g_clear_object (&priv->shell);
1141 g_clear_object (&priv->client_cache);
1142 g_clear_object (&priv->zone);
1143
1144 g_clear_pointer (&priv->default_source_uid, g_free);
1145
1146 /* Chain up to parent's dispose() method. */
1147 G_OBJECT_CLASS (e_cal_model_parent_class)->dispose (object);
1148 }
1149
1150 static void
cal_model_finalize(GObject * object)1151 cal_model_finalize (GObject *object)
1152 {
1153 ECalModelPrivate *priv;
1154 gint ii;
1155
1156 priv = E_CAL_MODEL_GET_PRIVATE (object);
1157
1158 g_free (priv->default_category);
1159
1160 for (ii = 0; ii < priv->objects->len; ii++) {
1161 ECalModelComponent *comp_data;
1162
1163 comp_data = g_ptr_array_index (priv->objects, ii);
1164 if (comp_data == NULL) {
1165 g_warning ("comp_data is null\n");
1166 continue;
1167 }
1168 g_object_unref (comp_data);
1169 }
1170 g_ptr_array_free (priv->objects, TRUE);
1171
1172 /* Chain up to parent's finalize() method. */
1173 G_OBJECT_CLASS (e_cal_model_parent_class)->finalize (object);
1174 }
1175
1176 static const gchar *
cal_model_get_color_for_component(ECalModel * model,ECalModelComponent * comp_data)1177 cal_model_get_color_for_component (ECalModel *model,
1178 ECalModelComponent *comp_data)
1179 {
1180 ESource *source;
1181 ESourceSelectable *extension;
1182 const gchar *color_spec;
1183 const gchar *extension_name;
1184 const gchar *uid;
1185 gint i, first_empty = 0;
1186 ICalProperty *prop;
1187
1188 static AssignedColorData assigned_colors[] = {
1189 { "#BECEDD", NULL }, /* 190 206 221 Blue */
1190 { "#E2F0EF", NULL }, /* 226 240 239 Light Blue */
1191 { "#C6E2B7", NULL }, /* 198 226 183 Green */
1192 { "#E2F0D3", NULL }, /* 226 240 211 Light Green */
1193 { "#E2D4B7", NULL }, /* 226 212 183 Khaki */
1194 { "#EAEAC1", NULL }, /* 234 234 193 Light Khaki */
1195 { "#F0B8B7", NULL }, /* 240 184 183 Pink */
1196 { "#FED4D3", NULL }, /* 254 212 211 Light Pink */
1197 { "#E2C6E1", NULL }, /* 226 198 225 Purple */
1198 { "#F0E2EF", NULL } /* 240 226 239 Light Purple */
1199 };
1200
1201 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1202
1203 prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_COLOR_PROPERTY);
1204 if (prop) {
1205 GdkRGBA rgba;
1206
1207 color_spec = i_cal_property_get_color (prop);
1208 if (color_spec && gdk_rgba_parse (&rgba, color_spec)) {
1209 g_free (comp_data->color);
1210 comp_data->color = g_strdup (color_spec);
1211
1212 g_object_unref (prop);
1213
1214 return comp_data->color;
1215 }
1216
1217 g_object_unref (prop);
1218 }
1219
1220 switch (e_cal_client_get_source_type (comp_data->client)) {
1221 case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
1222 extension_name = E_SOURCE_EXTENSION_CALENDAR;
1223 break;
1224 case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
1225 extension_name = E_SOURCE_EXTENSION_TASK_LIST;
1226 break;
1227 case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
1228 extension_name = E_SOURCE_EXTENSION_MEMO_LIST;
1229 break;
1230 default:
1231 g_return_val_if_reached (NULL);
1232 }
1233
1234 source = e_client_get_source (E_CLIENT (comp_data->client));
1235 extension = e_source_get_extension (source, extension_name);
1236 color_spec = e_source_selectable_get_color (extension);
1237
1238 if (color_spec != NULL) {
1239 g_free (comp_data->color);
1240 comp_data->color = g_strdup (color_spec);
1241 return comp_data->color;
1242 }
1243
1244 uid = e_source_get_uid (source);
1245
1246 for (i = 0; i < G_N_ELEMENTS (assigned_colors); i++) {
1247 GList *l;
1248
1249 if (assigned_colors[i].uids == NULL) {
1250 first_empty = i;
1251 continue;
1252 }
1253
1254 for (l = assigned_colors[i].uids; l != NULL; l = l->next)
1255 if (g_strcmp0 (l->data, uid) == 0)
1256 return assigned_colors[i].color;
1257 }
1258
1259 /* return the first unused color */
1260 assigned_colors[first_empty].uids = g_list_append (
1261 assigned_colors[first_empty].uids, g_strdup (uid));
1262
1263 return assigned_colors[first_empty].color;
1264 }
1265
1266 static gint
cal_model_column_count(ETableModel * etm)1267 cal_model_column_count (ETableModel *etm)
1268 {
1269 return E_CAL_MODEL_FIELD_LAST;
1270 }
1271
1272 static gint
cal_model_row_count(ETableModel * etm)1273 cal_model_row_count (ETableModel *etm)
1274 {
1275 ECalModelPrivate *priv;
1276 ECalModel *model = (ECalModel *) etm;
1277
1278 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
1279
1280 priv = model->priv;
1281
1282 return priv->objects->len;
1283 }
1284
1285 static const gchar *
cal_model_kind_to_extension_name(ECalModel * model)1286 cal_model_kind_to_extension_name (ECalModel *model)
1287 {
1288 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1289
1290 switch (model->priv->kind) {
1291 case I_CAL_VEVENT_COMPONENT:
1292 return E_SOURCE_EXTENSION_CALENDAR;
1293 case I_CAL_VJOURNAL_COMPONENT:
1294 return E_SOURCE_EXTENSION_MEMO_LIST;
1295 case I_CAL_VTODO_COMPONENT:
1296 return E_SOURCE_EXTENSION_TASK_LIST;
1297 default:
1298 g_warn_if_reached ();
1299 break;
1300 }
1301
1302 return NULL;
1303 }
1304
1305 typedef struct {
1306 ECalModel *model;
1307 ETableModel *table_model;
1308 GHashTable *values;
1309 gboolean success;
1310 } CreateComponentData;
1311
1312 static void
create_component_data_free(gpointer ptr)1313 create_component_data_free (gpointer ptr)
1314 {
1315 CreateComponentData *ccd = ptr;
1316
1317 if (ccd) {
1318 GHashTableIter iter;
1319 gpointer key, value;
1320
1321 g_hash_table_iter_init (&iter, ccd->values);
1322 while (g_hash_table_iter_next (&iter, &key, &value)) {
1323 gint column = GPOINTER_TO_INT (key);
1324
1325 e_table_model_free_value (ccd->table_model, column, value);
1326 }
1327
1328 if (ccd->success)
1329 g_signal_emit (ccd->model, signals[ROW_APPENDED], 0);
1330
1331 g_clear_object (&ccd->model);
1332 g_clear_object (&ccd->table_model);
1333 g_hash_table_destroy (ccd->values);
1334 g_slice_free (CreateComponentData, ccd);
1335 }
1336 }
1337
1338 static void
cal_model_create_component_from_values_thread(EAlertSinkThreadJobData * job_data,gpointer user_data,GCancellable * cancellable,GError ** error)1339 cal_model_create_component_from_values_thread (EAlertSinkThreadJobData *job_data,
1340 gpointer user_data,
1341 GCancellable *cancellable,
1342 GError **error)
1343 {
1344 CreateComponentData *ccd = user_data;
1345 EClientCache *client_cache;
1346 ESourceRegistry *registry;
1347 ESource *source;
1348 EClient *client;
1349 ECalModelComponent *comp_data;
1350 ICalProperty *prop;
1351 const gchar *source_uid;
1352 gchar *display_name;
1353 GError *local_error = NULL;
1354
1355 g_return_if_fail (ccd != NULL);
1356
1357 source_uid = e_cal_model_get_default_source_uid (ccd->model);
1358 g_return_if_fail (source_uid != NULL);
1359
1360 client_cache = e_cal_model_get_client_cache (ccd->model);
1361 registry = e_cal_model_get_registry (ccd->model);
1362
1363 source = e_source_registry_ref_source (registry, source_uid);
1364 if (!source) {
1365 g_set_error (&local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
1366 _("Source with UID “%s” not found"), source_uid);
1367 e_alert_sink_thread_job_set_alert_arg_0 (job_data, source_uid);
1368 return;
1369 }
1370
1371 display_name = e_util_get_source_full_name (registry, source);
1372 e_alert_sink_thread_job_set_alert_arg_0 (job_data, display_name);
1373 g_free (display_name);
1374
1375 client = e_client_cache_get_client_sync (client_cache, source,
1376 cal_model_kind_to_extension_name (ccd->model), (guint32) -1, cancellable, &local_error);
1377 g_clear_object (&source);
1378
1379 if (!client) {
1380 e_util_propagate_open_source_job_error (job_data,
1381 cal_model_kind_to_extension_name (ccd->model), local_error, error);
1382 return;
1383 }
1384
1385 comp_data = g_object_new (E_TYPE_CAL_MODEL_COMPONENT, NULL);
1386 comp_data->client = E_CAL_CLIENT (g_object_ref (client));
1387 comp_data->icalcomp = e_cal_model_create_component_with_defaults_sync (ccd->model, comp_data->client, FALSE, cancellable, error);
1388
1389 if (comp_data->icalcomp) {
1390 ECalModelClass *model_class;
1391 gchar *uid = NULL;
1392 gpointer dtstart;
1393
1394 /* set values for our fields */
1395 set_categories (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_CATEGORIES));
1396 set_classification (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_CLASSIFICATION));
1397 set_description (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_DESCRIPTION));
1398 set_summary (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_SUMMARY));
1399
1400 dtstart = e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_DTSTART);
1401 if (dtstart) {
1402 set_dtstart (ccd->model, comp_data, dtstart);
1403 } else if (ccd->model->priv->get_default_time) {
1404 time_t tt = ccd->model->priv->get_default_time (ccd->model, ccd->model->priv->get_default_time_user_data);
1405
1406 if (tt > 0) {
1407 /* Store Memo DTSTART as date, not as date-time */
1408 ICalTime *itt = i_cal_time_new_from_timet_with_zone (tt,
1409 i_cal_component_isa (comp_data->icalcomp) == I_CAL_VJOURNAL_COMPONENT, e_cal_model_get_timezone (ccd->model));
1410
1411 prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_DTSTART_PROPERTY);
1412
1413 if (prop) {
1414 i_cal_property_set_dtstart (prop, itt);
1415 g_object_unref (prop);
1416 } else {
1417 prop = i_cal_property_new_dtstart (itt);
1418 i_cal_component_take_property (comp_data->icalcomp, prop);
1419 }
1420 }
1421 }
1422
1423 /* call the class' method for filling the component */
1424 model_class = E_CAL_MODEL_GET_CLASS (ccd->model);
1425 if (model_class->fill_component_from_values != NULL) {
1426 model_class->fill_component_from_values (ccd->model, comp_data, ccd->values);
1427 }
1428
1429 prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_CLASS_PROPERTY);
1430 if (!prop || i_cal_property_get_class (prop) == I_CAL_CLASS_NONE) {
1431 ICalProperty_Class ical_class = I_CAL_CLASS_PUBLIC;
1432 GSettings *settings;
1433
1434 settings = e_util_ref_settings ("org.gnome.evolution.calendar");
1435 if (g_settings_get_boolean (settings, "classify-private"))
1436 ical_class = I_CAL_CLASS_PRIVATE;
1437 g_object_unref (settings);
1438
1439 if (!prop) {
1440 prop = i_cal_property_new_class (ical_class);
1441 i_cal_component_take_property (comp_data->icalcomp, prop);
1442 } else {
1443 i_cal_property_set_class (prop, ical_class);
1444 g_object_unref (prop);
1445 }
1446 } else {
1447 g_clear_object (&prop);
1448 }
1449
1450 ccd->success = e_cal_client_create_object_sync (comp_data->client, comp_data->icalcomp, E_CAL_OPERATION_FLAG_NONE, &uid, cancellable, error);
1451
1452 g_free (uid);
1453 }
1454
1455 g_object_unref (comp_data);
1456 g_object_unref (client);
1457 }
1458
1459 static void
cal_model_append_row(ETableModel * etm,ETableModel * source,gint row)1460 cal_model_append_row (ETableModel *etm,
1461 ETableModel *source,
1462 gint row)
1463 {
1464 ECalModelClass *model_class;
1465 ECalModel *model = (ECalModel *) etm;
1466 GHashTable *values;
1467 GCancellable *cancellable;
1468 CreateComponentData *ccd;
1469 const gchar *description;
1470 const gchar *alert_ident;
1471
1472 g_return_if_fail (E_IS_CAL_MODEL (model));
1473 g_return_if_fail (E_IS_TABLE_MODEL (source));
1474
1475 switch (e_cal_model_get_component_kind (model)) {
1476 case I_CAL_VEVENT_COMPONENT:
1477 description = _("Creating an event");
1478 alert_ident = "calendar:failed-create-event";
1479 break;
1480 case I_CAL_VJOURNAL_COMPONENT:
1481 description = _("Creating a memo");
1482 alert_ident = "calendar:failed-create-memo";
1483 break;
1484 case I_CAL_VTODO_COMPONENT:
1485 description = _("Creating a task");
1486 alert_ident = "calendar:failed-create-task";
1487 break;
1488 default:
1489 g_warn_if_reached ();
1490 return;
1491 }
1492
1493 values = g_hash_table_new (g_direct_hash, g_direct_equal);
1494
1495 /* store values for our fields */
1496 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_CATEGORIES, row);
1497 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_CLASSIFICATION, row);
1498 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_DESCRIPTION, row);
1499 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_SUMMARY, row);
1500 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_DTSTART, row);
1501
1502 /* call the class' method to store other values */
1503 model_class = E_CAL_MODEL_GET_CLASS (model);
1504 if (model_class->store_values_from_model != NULL) {
1505 model_class->store_values_from_model (model, source, row, values);
1506 }
1507
1508 ccd = g_slice_new0 (CreateComponentData);
1509 ccd->model = g_object_ref (model);
1510 ccd->table_model = g_object_ref (source);
1511 ccd->values = values;
1512 ccd->success = FALSE;
1513
1514 cancellable = e_cal_data_model_submit_thread_job (model->priv->data_model, description,
1515 alert_ident, NULL, cal_model_create_component_from_values_thread,
1516 ccd, create_component_data_free);
1517
1518 g_clear_object (&cancellable);
1519 }
1520
1521 static gpointer
cal_model_value_at(ETableModel * etm,gint col,gint row)1522 cal_model_value_at (ETableModel *etm,
1523 gint col,
1524 gint row)
1525 {
1526 ECalModelPrivate *priv;
1527 ECalModelComponent *comp_data;
1528 ECalModel *model = (ECalModel *) etm;
1529 ESourceRegistry *registry;
1530
1531 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1532
1533 priv = model->priv;
1534
1535 registry = e_cal_model_get_registry (model);
1536
1537 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
1538 g_return_val_if_fail (row >= 0 && row < priv->objects->len, NULL);
1539
1540 comp_data = g_ptr_array_index (priv->objects, row);
1541 g_return_val_if_fail (comp_data != NULL, NULL);
1542 g_return_val_if_fail (comp_data->icalcomp != NULL, NULL);
1543
1544 switch (col) {
1545 case E_CAL_MODEL_FIELD_CATEGORIES :
1546 return get_categories (comp_data);
1547 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1548 return get_classification (comp_data);
1549 case E_CAL_MODEL_FIELD_COLOR :
1550 return (gpointer) get_color (model, comp_data);
1551 case E_CAL_MODEL_FIELD_COMPONENT :
1552 return comp_data->icalcomp;
1553 case E_CAL_MODEL_FIELD_DESCRIPTION :
1554 return get_description (comp_data);
1555 case E_CAL_MODEL_FIELD_DTSTART :
1556 return (gpointer) get_dtstart (model, comp_data);
1557 case E_CAL_MODEL_FIELD_CREATED :
1558 return (gpointer) get_datetime_from_utc (
1559 model, comp_data, I_CAL_CREATED_PROPERTY,
1560 i_cal_property_get_created, &comp_data->created);
1561 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1562 {
1563 gpointer result = (gpointer) get_datetime_from_utc (
1564 model, comp_data, I_CAL_LASTMODIFIED_PROPERTY,
1565 i_cal_property_get_lastmodified, &comp_data->lastmodified);
1566 if (!result && !e_cal_util_component_has_property (comp_data->icalcomp, I_CAL_METHOD_PROPERTY))
1567 return get_datetime_from_utc (model, comp_data, I_CAL_DTSTAMP_PROPERTY, i_cal_property_get_dtstamp, &comp_data->lastmodified);
1568
1569 return result;
1570
1571 }
1572 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1573 return GINT_TO_POINTER (e_cal_util_component_has_alarms (comp_data->icalcomp));
1574 case E_CAL_MODEL_FIELD_ICON :
1575 {
1576 gint retval = comp_data->priv->icon_index;
1577
1578 if (retval >= 0)
1579 return GINT_TO_POINTER (retval);
1580
1581 retval = 0;
1582
1583 if (i_cal_component_isa (comp_data->icalcomp) == I_CAL_VEVENT_COMPONENT) {
1584 if (e_cal_util_component_has_attendee (comp_data->icalcomp))
1585 retval = 1;
1586 if (e_cal_util_component_has_recurrences (comp_data->icalcomp) ||
1587 e_cal_util_component_is_instance (comp_data->icalcomp))
1588 retval = 2;
1589 } else if (i_cal_component_isa (comp_data->icalcomp) == I_CAL_VJOURNAL_COMPONENT) {
1590 if (e_cal_util_component_has_attendee (comp_data->icalcomp))
1591 retval = 1;
1592 } else {
1593 ECalComponent *comp;
1594
1595 comp = e_cal_component_new_from_icalcomponent (i_cal_component_clone (comp_data->icalcomp));
1596 if (comp) {
1597 if (e_cal_component_has_recurrences (comp))
1598 retval = 1;
1599 else if (itip_organizer_is_user (registry, comp, comp_data->client))
1600 retval = 3;
1601 else {
1602 GSList *attendees = NULL, *sl;
1603
1604 attendees = e_cal_component_get_attendees (comp);
1605 for (sl = attendees; sl != NULL; sl = sl->next) {
1606 ECalComponentAttendee *ca = sl->data;
1607 const gchar *text;
1608
1609 text = itip_strip_mailto (e_cal_component_attendee_get_value (ca));
1610 if (itip_address_is_user (registry, text)) {
1611 if (e_cal_component_attendee_get_delegatedto (ca) != NULL)
1612 retval = 3;
1613 else
1614 retval = 2;
1615 break;
1616 }
1617 }
1618
1619 g_slist_free_full (attendees, e_cal_component_attendee_free);
1620 }
1621
1622 g_object_unref (comp);
1623 }
1624 }
1625
1626 comp_data->priv->icon_index = retval;
1627
1628 return GINT_TO_POINTER (retval);
1629 }
1630 case E_CAL_MODEL_FIELD_SUMMARY :
1631 return get_summary (comp_data);
1632 case E_CAL_MODEL_FIELD_UID :
1633 return get_uid (comp_data);
1634 case E_CAL_MODEL_FIELD_SOURCE:
1635 return get_source_description (registry, comp_data);
1636 case E_CAL_MODEL_FIELD_CANCELLED:
1637 return GINT_TO_POINTER (i_cal_component_get_status (comp_data->icalcomp) == I_CAL_STATUS_CANCELLED ? 1 : 0);
1638 }
1639
1640 return (gpointer) "";
1641 }
1642
1643 static void
cal_model_set_value_at(ETableModel * etm,gint col,gint row,gconstpointer value)1644 cal_model_set_value_at (ETableModel *etm,
1645 gint col,
1646 gint row,
1647 gconstpointer value)
1648 {
1649 ECalModelPrivate *priv;
1650 ECalModelComponent *comp_data;
1651 ECalModel *model = (ECalModel *) etm;
1652 ECalObjModType mod = E_CAL_OBJ_MOD_ALL;
1653
1654 g_return_if_fail (E_IS_CAL_MODEL (model));
1655
1656 priv = model->priv;
1657
1658 g_return_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST);
1659 g_return_if_fail (row >= 0 && row < priv->objects->len);
1660
1661 comp_data = g_ptr_array_index (priv->objects, row);
1662 g_return_if_fail (comp_data != NULL);
1663
1664 if (!e_cal_dialogs_recur_icalcomp (comp_data->client, comp_data->icalcomp, &mod, NULL, FALSE))
1665 return;
1666
1667 switch (col) {
1668 case E_CAL_MODEL_FIELD_CATEGORIES :
1669 set_categories (comp_data, value);
1670 break;
1671 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1672 set_classification (comp_data, value);
1673 break;
1674 case E_CAL_MODEL_FIELD_DESCRIPTION :
1675 set_description (comp_data, value);
1676 break;
1677 case E_CAL_MODEL_FIELD_DTSTART :
1678 set_dtstart (model, comp_data, value);
1679 break;
1680 case E_CAL_MODEL_FIELD_SUMMARY :
1681 set_summary (comp_data, value);
1682 break;
1683 }
1684
1685 e_cal_ops_modify_component (model, comp_data->client, comp_data->icalcomp, mod, E_CAL_OPS_SEND_FLAG_DONT_SEND);
1686 }
1687
1688 static gboolean
cal_model_is_cell_editable(ETableModel * etm,gint col,gint row)1689 cal_model_is_cell_editable (ETableModel *etm,
1690 gint col,
1691 gint row)
1692 {
1693 ECalModelPrivate *priv;
1694 ECalModel *model = (ECalModel *) etm;
1695
1696 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
1697
1698 priv = model->priv;
1699
1700 g_return_val_if_fail (col >= 0 && col <= E_CAL_MODEL_FIELD_LAST, FALSE);
1701 g_return_val_if_fail (row >= -1 || (row >= 0 && row < priv->objects->len), FALSE);
1702
1703 if (!e_cal_model_test_row_editable (E_CAL_MODEL (etm), row))
1704 return FALSE;
1705
1706 switch (col) {
1707 case E_CAL_MODEL_FIELD_CATEGORIES :
1708 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1709 case E_CAL_MODEL_FIELD_DESCRIPTION :
1710 case E_CAL_MODEL_FIELD_DTSTART :
1711 case E_CAL_MODEL_FIELD_SUMMARY :
1712 return TRUE;
1713 }
1714
1715 return FALSE;
1716 }
1717
1718 static gpointer
cal_model_duplicate_value(ETableModel * etm,gint col,gconstpointer value)1719 cal_model_duplicate_value (ETableModel *etm,
1720 gint col,
1721 gconstpointer value)
1722 {
1723 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
1724
1725 switch (col) {
1726 case E_CAL_MODEL_FIELD_CATEGORIES :
1727 case E_CAL_MODEL_FIELD_DESCRIPTION :
1728 case E_CAL_MODEL_FIELD_SUMMARY :
1729 case E_CAL_MODEL_FIELD_SOURCE:
1730 return g_strdup (value);
1731 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1732 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1733 case E_CAL_MODEL_FIELD_ICON :
1734 case E_CAL_MODEL_FIELD_COLOR :
1735 case E_CAL_MODEL_FIELD_CANCELLED:
1736 return (gpointer) value;
1737 case E_CAL_MODEL_FIELD_COMPONENT :
1738 return i_cal_component_clone ((ICalComponent *) value);
1739 case E_CAL_MODEL_FIELD_DTSTART :
1740 case E_CAL_MODEL_FIELD_CREATED :
1741 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1742 return e_cell_date_edit_value_copy (value);
1743 }
1744
1745 return NULL;
1746 }
1747
1748 static void
cal_model_free_value(ETableModel * etm,gint col,gpointer value)1749 cal_model_free_value (ETableModel *etm,
1750 gint col,
1751 gpointer value)
1752 {
1753 g_return_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST);
1754
1755 switch (col) {
1756 case E_CAL_MODEL_FIELD_CATEGORIES :
1757 case E_CAL_MODEL_FIELD_DESCRIPTION :
1758 case E_CAL_MODEL_FIELD_SUMMARY :
1759 case E_CAL_MODEL_FIELD_SOURCE:
1760 g_free (value);
1761 break;
1762 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1763 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1764 case E_CAL_MODEL_FIELD_ICON :
1765 case E_CAL_MODEL_FIELD_COLOR :
1766 case E_CAL_MODEL_FIELD_CANCELLED:
1767 break;
1768 case E_CAL_MODEL_FIELD_DTSTART:
1769 case E_CAL_MODEL_FIELD_CREATED :
1770 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1771 if (value)
1772 e_cell_date_edit_value_free (value);
1773 break;
1774 case E_CAL_MODEL_FIELD_COMPONENT :
1775 if (value)
1776 g_object_unref ((ICalComponent *) value);
1777 break;
1778 }
1779 }
1780
1781 static gpointer
cal_model_initialize_value(ETableModel * etm,gint col)1782 cal_model_initialize_value (ETableModel *etm,
1783 gint col)
1784 {
1785 ECalModelPrivate *priv;
1786 ECalModel *model = (ECalModel *) etm;
1787
1788 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1789 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
1790
1791 priv = model->priv;
1792
1793 switch (col) {
1794 case E_CAL_MODEL_FIELD_CATEGORIES :
1795 return g_strdup (priv->default_category ? priv->default_category:"");
1796 case E_CAL_MODEL_FIELD_DESCRIPTION :
1797 case E_CAL_MODEL_FIELD_SUMMARY :
1798 case E_CAL_MODEL_FIELD_SOURCE:
1799 return g_strdup ("");
1800 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1801 case E_CAL_MODEL_FIELD_DTSTART :
1802 case E_CAL_MODEL_FIELD_CREATED :
1803 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1804 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1805 case E_CAL_MODEL_FIELD_ICON :
1806 case E_CAL_MODEL_FIELD_COLOR :
1807 case E_CAL_MODEL_FIELD_COMPONENT :
1808 case E_CAL_MODEL_FIELD_CANCELLED:
1809 return NULL;
1810 }
1811
1812 return NULL;
1813 }
1814
1815 static gboolean
cal_model_value_is_empty(ETableModel * etm,gint col,gconstpointer value)1816 cal_model_value_is_empty (ETableModel *etm,
1817 gint col,
1818 gconstpointer value)
1819 {
1820 ECalModelPrivate *priv;
1821 ECalModel *model = (ECalModel *) etm;
1822
1823 g_return_val_if_fail (E_IS_CAL_MODEL (model), TRUE);
1824 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, TRUE);
1825
1826 priv = model->priv;
1827
1828 switch (col) {
1829 case E_CAL_MODEL_FIELD_CATEGORIES :
1830 /* This could be a hack or not. If the categories field only
1831 * contains the default category, then it possibly means that
1832 * the user has not entered anything at all in the click-to-add;
1833 * the category is in the value because we put it there in
1834 * ecm_initialize_value().
1835 */
1836 if (priv->default_category && value && strcmp (priv->default_category, value) == 0)
1837 return TRUE;
1838 else
1839 return string_is_empty (value);
1840 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1841 case E_CAL_MODEL_FIELD_DESCRIPTION :
1842 case E_CAL_MODEL_FIELD_SUMMARY :
1843 case E_CAL_MODEL_FIELD_SOURCE:
1844 return string_is_empty (value);
1845 case E_CAL_MODEL_FIELD_DTSTART :
1846 case E_CAL_MODEL_FIELD_CREATED :
1847 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1848 return value ? FALSE : TRUE;
1849 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1850 case E_CAL_MODEL_FIELD_ICON :
1851 case E_CAL_MODEL_FIELD_COLOR :
1852 case E_CAL_MODEL_FIELD_COMPONENT :
1853 case E_CAL_MODEL_FIELD_CANCELLED:
1854 return TRUE;
1855 }
1856
1857 return TRUE;
1858 }
1859
1860 static gchar *
cal_model_value_to_string(ETableModel * etm,gint col,gconstpointer value)1861 cal_model_value_to_string (ETableModel *etm,
1862 gint col,
1863 gconstpointer value)
1864 {
1865 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, g_strdup (""));
1866
1867 switch (col) {
1868 case E_CAL_MODEL_FIELD_CATEGORIES :
1869 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1870 case E_CAL_MODEL_FIELD_DESCRIPTION :
1871 case E_CAL_MODEL_FIELD_SUMMARY :
1872 case E_CAL_MODEL_FIELD_SOURCE:
1873 return g_strdup (value);
1874 case E_CAL_MODEL_FIELD_DTSTART :
1875 case E_CAL_MODEL_FIELD_CREATED :
1876 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1877 return e_cal_model_date_value_to_string (E_CAL_MODEL (etm), value);
1878 case E_CAL_MODEL_FIELD_ICON :
1879 if (GPOINTER_TO_INT (value) == 0)
1880 return g_strdup (_("Normal"));
1881 else if (GPOINTER_TO_INT (value) == 1)
1882 return g_strdup (_("Recurring"));
1883 else
1884 return g_strdup (_("Assigned"));
1885 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1886 case E_CAL_MODEL_FIELD_CANCELLED:
1887 return g_strdup (value ? _("Yes") : _("No"));
1888 case E_CAL_MODEL_FIELD_COLOR :
1889 case E_CAL_MODEL_FIELD_COMPONENT :
1890 return g_strdup ("");
1891 }
1892
1893 return g_strdup ("");
1894 }
1895
1896 static gint
e_cal_model_get_component_index(ECalModel * model,ECalClient * client,const ECalComponentId * id)1897 e_cal_model_get_component_index (ECalModel *model,
1898 ECalClient *client,
1899 const ECalComponentId *id)
1900 {
1901 gint ii;
1902
1903 for (ii = 0; ii < model->priv->objects->len; ii++) {
1904 ECalModelComponent *comp_data = g_ptr_array_index (model->priv->objects, ii);
1905
1906 if (comp_data) {
1907 const gchar *uid;
1908 gboolean has_rid = e_cal_component_id_get_rid (id) != NULL;
1909
1910 uid = i_cal_component_get_uid (comp_data->icalcomp);
1911
1912 if (uid && *uid) {
1913 if ((!client || comp_data->client == client) && strcmp (uid, e_cal_component_id_get_uid (id)) == 0) {
1914 if (has_rid) {
1915 gchar *rid;
1916
1917 rid = e_cal_util_component_get_recurid_as_string (comp_data->icalcomp);
1918
1919 if (!(rid && *rid && strcmp (rid, e_cal_component_id_get_rid (id)) == 0)) {
1920 g_free (rid);
1921 continue;
1922 }
1923
1924 g_free (rid);
1925 }
1926
1927 return ii;
1928 }
1929 }
1930 }
1931 }
1932
1933 return -1;
1934 }
1935
1936 static void
cal_model_data_subscriber_component_added_or_modified(ECalDataModelSubscriber * subscriber,ECalClient * client,ECalComponent * comp,gboolean is_added)1937 cal_model_data_subscriber_component_added_or_modified (ECalDataModelSubscriber *subscriber,
1938 ECalClient *client,
1939 ECalComponent *comp,
1940 gboolean is_added)
1941 {
1942 ECalModel *model;
1943 ECalModelComponent *comp_data;
1944 ETableModel *table_model;
1945 ECalComponentId *id;
1946 ICalComponent *icomp;
1947 gint index;
1948
1949 model = E_CAL_MODEL (subscriber);
1950 table_model = E_TABLE_MODEL (model);
1951
1952 id = e_cal_component_get_id (comp);
1953
1954 /* The component should not exist, when it's claimed being added, thus, when it's the main
1955 component, remove any existing instances and add it from scratch. */
1956 if (is_added && !e_cal_component_id_get_rid (id)) {
1957 GSList *removed_comps = NULL;
1958
1959 for (index = 0; index < model->priv->objects->len; index++) {
1960 comp_data = g_ptr_array_index (model->priv->objects, index);
1961
1962 if (comp_data && comp_data->client == client) {
1963 const gchar *uid;
1964
1965 uid = i_cal_component_get_uid (comp_data->icalcomp);
1966
1967 if (uid && *uid && g_strcmp0 (uid, e_cal_component_id_get_uid (id)) == 0) {
1968 e_table_model_pre_change (table_model);
1969
1970 g_ptr_array_remove_index (model->priv->objects, index);
1971 removed_comps = g_slist_prepend (removed_comps, comp_data);
1972 e_table_model_row_deleted (table_model, index);
1973
1974 index--;
1975 }
1976 }
1977 }
1978
1979 g_signal_emit (model, signals[COMPS_DELETED], 0, removed_comps);
1980
1981 g_slist_free_full (removed_comps, g_object_unref);
1982
1983 index = -1;
1984 } else {
1985 index = e_cal_model_get_component_index (model, client, id);
1986 }
1987
1988 e_cal_component_id_free (id);
1989
1990 if (index < 0 && !is_added)
1991 return;
1992
1993 icomp = i_cal_component_clone (e_cal_component_get_icalcomponent (comp));
1994
1995 if (index < 0) {
1996 e_table_model_pre_change (table_model);
1997
1998 comp_data = g_object_new (E_TYPE_CAL_MODEL_COMPONENT, NULL);
1999 comp_data->is_new_component = FALSE;
2000 comp_data->client = g_object_ref (client);
2001 comp_data->icalcomp = icomp;
2002 e_cal_model_set_instance_times (comp_data, model->priv->zone);
2003 g_ptr_array_add (model->priv->objects, comp_data);
2004
2005 e_table_model_row_inserted (table_model, model->priv->objects->len - 1);
2006 } else {
2007 e_table_model_pre_change (table_model);
2008
2009 comp_data = g_ptr_array_index (model->priv->objects, index);
2010 e_cal_model_component_set_icalcomponent (comp_data, model, icomp);
2011
2012 e_table_model_row_changed (table_model, index);
2013 }
2014 }
2015
2016 static void
e_cal_model_data_subscriber_component_added(ECalDataModelSubscriber * subscriber,ECalClient * client,ECalComponent * comp)2017 e_cal_model_data_subscriber_component_added (ECalDataModelSubscriber *subscriber,
2018 ECalClient *client,
2019 ECalComponent *comp)
2020 {
2021 cal_model_data_subscriber_component_added_or_modified (subscriber, client, comp, TRUE);
2022 }
2023
2024 static void
e_cal_model_data_subscriber_component_modified(ECalDataModelSubscriber * subscriber,ECalClient * client,ECalComponent * comp)2025 e_cal_model_data_subscriber_component_modified (ECalDataModelSubscriber *subscriber,
2026 ECalClient *client,
2027 ECalComponent *comp)
2028 {
2029 cal_model_data_subscriber_component_added_or_modified (subscriber, client, comp, FALSE);
2030 }
2031
2032 static void
e_cal_model_data_subscriber_component_removed(ECalDataModelSubscriber * subscriber,ECalClient * client,const gchar * uid,const gchar * rid)2033 e_cal_model_data_subscriber_component_removed (ECalDataModelSubscriber *subscriber,
2034 ECalClient *client,
2035 const gchar *uid,
2036 const gchar *rid)
2037 {
2038 ECalModel *model;
2039 ECalModelComponent *comp_data;
2040 ETableModel *table_model;
2041 ECalComponentId *id;
2042 GSList *link;
2043 gint index;
2044
2045 model = E_CAL_MODEL (subscriber);
2046
2047 id = e_cal_component_id_new (uid, rid);
2048
2049 index = e_cal_model_get_component_index (model, client, id);
2050
2051 e_cal_component_id_free (id);
2052
2053 if (index < 0)
2054 return;
2055
2056 table_model = E_TABLE_MODEL (model);
2057 e_table_model_pre_change (table_model);
2058
2059 comp_data = g_ptr_array_remove_index (model->priv->objects, index);
2060 if (!comp_data) {
2061 e_table_model_no_change (table_model);
2062 return;
2063 }
2064
2065 link = g_slist_append (NULL, comp_data);
2066 g_signal_emit (model, signals[COMPS_DELETED], 0, link);
2067
2068 g_slist_free (link);
2069 g_object_unref (comp_data);
2070
2071 e_table_model_row_deleted (table_model, index);
2072 }
2073
2074 static void
e_cal_model_data_subscriber_freeze(ECalDataModelSubscriber * subscriber)2075 e_cal_model_data_subscriber_freeze (ECalDataModelSubscriber *subscriber)
2076 {
2077 /* No freeze/thaw, the ETableModel doesn't notify about changes when frozen */
2078
2079 /* ETableModel *table_model = E_TABLE_MODEL (subscriber);
2080 e_table_model_freeze (table_model); */
2081 }
2082
2083 static void
e_cal_model_data_subscriber_thaw(ECalDataModelSubscriber * subscriber)2084 e_cal_model_data_subscriber_thaw (ECalDataModelSubscriber *subscriber)
2085 {
2086 /* No freeze/thaw, the ETableModel doesn't notify about changes when frozen */
2087
2088 /* ETableModel *table_model = E_TABLE_MODEL (subscriber);
2089 e_table_model_thaw (table_model); */
2090 }
2091
2092 static void
e_cal_model_class_init(ECalModelClass * class)2093 e_cal_model_class_init (ECalModelClass *class)
2094 {
2095 GObjectClass *object_class;
2096
2097 g_type_class_add_private (class, sizeof (ECalModelPrivate));
2098
2099 object_class = G_OBJECT_CLASS (class);
2100 object_class->set_property = cal_model_set_property;
2101 object_class->get_property = cal_model_get_property;
2102 object_class->constructed = cal_model_constructed;
2103 object_class->dispose = cal_model_dispose;
2104 object_class->finalize = cal_model_finalize;
2105
2106 class->get_color_for_component = cal_model_get_color_for_component;
2107
2108 g_object_class_install_property (
2109 object_class,
2110 PROP_DATA_MODEL,
2111 g_param_spec_object (
2112 "data-model",
2113 "Calendar Data Model",
2114 NULL,
2115 E_TYPE_CAL_DATA_MODEL,
2116 G_PARAM_READWRITE |
2117 G_PARAM_CONSTRUCT_ONLY));
2118
2119 g_object_class_install_property (
2120 object_class,
2121 PROP_CLIENT_CACHE,
2122 g_param_spec_object (
2123 "client-cache",
2124 "Client Cache",
2125 NULL,
2126 E_TYPE_CLIENT_CACHE,
2127 G_PARAM_READABLE));
2128
2129 g_object_class_install_property (
2130 object_class,
2131 PROP_COMPRESS_WEEKEND,
2132 g_param_spec_boolean (
2133 "compress-weekend",
2134 "Compress Weekend",
2135 NULL,
2136 FALSE,
2137 G_PARAM_READWRITE));
2138
2139 g_object_class_install_property (
2140 object_class,
2141 PROP_CONFIRM_DELETE,
2142 g_param_spec_boolean (
2143 "confirm-delete",
2144 "Confirm Delete",
2145 NULL,
2146 TRUE,
2147 G_PARAM_READWRITE));
2148
2149 g_object_class_install_property (
2150 object_class,
2151 PROP_DEFAULT_REMINDER_INTERVAL,
2152 g_param_spec_int (
2153 "default-reminder-interval",
2154 "Default Reminder Interval",
2155 NULL,
2156 G_MININT,
2157 G_MAXINT,
2158 0,
2159 G_PARAM_READWRITE));
2160
2161 g_object_class_install_property (
2162 object_class,
2163 PROP_DEFAULT_REMINDER_UNITS,
2164 g_param_spec_enum (
2165 "default-reminder-units",
2166 "Default Reminder Units",
2167 NULL,
2168 E_TYPE_DURATION_TYPE,
2169 E_DURATION_MINUTES,
2170 G_PARAM_READWRITE));
2171
2172 g_object_class_install_property (
2173 object_class,
2174 PROP_DEFAULT_SOURCE_UID,
2175 g_param_spec_string (
2176 "default-source-uid",
2177 "Default source UID of an ECalClient",
2178 NULL,
2179 NULL,
2180 G_PARAM_READWRITE));
2181
2182 g_object_class_install_property (
2183 object_class,
2184 PROP_REGISTRY,
2185 g_param_spec_object (
2186 "registry",
2187 "Registry",
2188 "Data source registry",
2189 E_TYPE_SOURCE_REGISTRY,
2190 G_PARAM_READWRITE |
2191 G_PARAM_CONSTRUCT_ONLY));
2192
2193 g_object_class_install_property (
2194 object_class,
2195 PROP_SHELL,
2196 g_param_spec_object (
2197 "shell",
2198 "Shell",
2199 "EShell",
2200 E_TYPE_SHELL,
2201 G_PARAM_READWRITE |
2202 G_PARAM_CONSTRUCT_ONLY));
2203
2204 g_object_class_install_property (
2205 object_class,
2206 PROP_TIMEZONE,
2207 g_param_spec_object (
2208 "timezone",
2209 "Time Zone",
2210 NULL,
2211 I_CAL_TYPE_TIMEZONE,
2212 G_PARAM_READWRITE));
2213
2214 g_object_class_install_property (
2215 object_class,
2216 PROP_USE_24_HOUR_FORMAT,
2217 g_param_spec_boolean (
2218 "use-24-hour-format",
2219 "Use 24-Hour Format",
2220 NULL,
2221 TRUE,
2222 G_PARAM_READWRITE));
2223
2224 g_object_class_install_property (
2225 object_class,
2226 PROP_USE_DEFAULT_REMINDER,
2227 g_param_spec_boolean (
2228 "use-default-reminder",
2229 "Use Default Reminder",
2230 NULL,
2231 FALSE,
2232 G_PARAM_READWRITE));
2233
2234 g_object_class_install_property (
2235 object_class,
2236 PROP_WEEK_START_DAY,
2237 g_param_spec_enum (
2238 "week-start-day",
2239 "Week Start Day",
2240 NULL,
2241 E_TYPE_DATE_WEEKDAY,
2242 G_DATE_MONDAY,
2243 G_PARAM_READWRITE |
2244 G_PARAM_CONSTRUCT));
2245
2246 g_object_class_install_property (
2247 object_class,
2248 PROP_WORK_DAY_MONDAY,
2249 g_param_spec_boolean (
2250 "work-day-monday",
2251 "Work Day: Monday",
2252 "Whether Monday is a work day",
2253 TRUE,
2254 G_PARAM_READWRITE |
2255 G_PARAM_CONSTRUCT |
2256 G_PARAM_STATIC_STRINGS));
2257
2258 g_object_class_install_property (
2259 object_class,
2260 PROP_WORK_DAY_TUESDAY,
2261 g_param_spec_boolean (
2262 "work-day-tuesday",
2263 "Work Day: Tuesday",
2264 "Whether Tuesday is a work day",
2265 TRUE,
2266 G_PARAM_READWRITE |
2267 G_PARAM_CONSTRUCT |
2268 G_PARAM_STATIC_STRINGS));
2269
2270 g_object_class_install_property (
2271 object_class,
2272 PROP_WORK_DAY_WEDNESDAY,
2273 g_param_spec_boolean (
2274 "work-day-wednesday",
2275 "Work Day: Wednesday",
2276 "Whether Wednesday is a work day",
2277 TRUE,
2278 G_PARAM_READWRITE |
2279 G_PARAM_CONSTRUCT |
2280 G_PARAM_STATIC_STRINGS));
2281
2282 g_object_class_install_property (
2283 object_class,
2284 PROP_WORK_DAY_THURSDAY,
2285 g_param_spec_boolean (
2286 "work-day-thursday",
2287 "Work Day: Thursday",
2288 "Whether Thursday is a work day",
2289 TRUE,
2290 G_PARAM_READWRITE |
2291 G_PARAM_CONSTRUCT |
2292 G_PARAM_STATIC_STRINGS));
2293
2294 g_object_class_install_property (
2295 object_class,
2296 PROP_WORK_DAY_FRIDAY,
2297 g_param_spec_boolean (
2298 "work-day-friday",
2299 "Work Day: Friday",
2300 "Whether Friday is a work day",
2301 TRUE,
2302 G_PARAM_READWRITE |
2303 G_PARAM_CONSTRUCT |
2304 G_PARAM_STATIC_STRINGS));
2305
2306 g_object_class_install_property (
2307 object_class,
2308 PROP_WORK_DAY_SATURDAY,
2309 g_param_spec_boolean (
2310 "work-day-saturday",
2311 "Work Day: Saturday",
2312 "Whether Saturday is a work day",
2313 TRUE,
2314 G_PARAM_READWRITE |
2315 G_PARAM_CONSTRUCT |
2316 G_PARAM_STATIC_STRINGS));
2317
2318 g_object_class_install_property (
2319 object_class,
2320 PROP_WORK_DAY_SUNDAY,
2321 g_param_spec_boolean (
2322 "work-day-sunday",
2323 "Work Day: Sunday",
2324 "Whether Sunday is a work day",
2325 TRUE,
2326 G_PARAM_READWRITE |
2327 G_PARAM_CONSTRUCT |
2328 G_PARAM_STATIC_STRINGS));
2329
2330 g_object_class_install_property (
2331 object_class,
2332 PROP_WORK_DAY_END_HOUR,
2333 g_param_spec_int (
2334 "work-day-end-hour",
2335 "Work Day End Hour",
2336 NULL,
2337 0,
2338 23,
2339 0,
2340 G_PARAM_READWRITE));
2341
2342 g_object_class_install_property (
2343 object_class,
2344 PROP_WORK_DAY_END_MINUTE,
2345 g_param_spec_int (
2346 "work-day-end-minute",
2347 "Work Day End Minute",
2348 NULL,
2349 0,
2350 59,
2351 0,
2352 G_PARAM_READWRITE));
2353
2354 g_object_class_install_property (
2355 object_class,
2356 PROP_WORK_DAY_START_HOUR,
2357 g_param_spec_int (
2358 "work-day-start-hour",
2359 "Work Day Start Hour",
2360 NULL,
2361 0,
2362 23,
2363 0,
2364 G_PARAM_READWRITE));
2365
2366 g_object_class_install_property (
2367 object_class,
2368 PROP_WORK_DAY_START_MINUTE,
2369 g_param_spec_int (
2370 "work-day-start-minute",
2371 "Work Day Start Minute",
2372 NULL,
2373 0,
2374 59,
2375 0,
2376 G_PARAM_READWRITE));
2377
2378 g_object_class_install_property (
2379 object_class,
2380 PROP_WORK_DAY_START_MON,
2381 g_param_spec_int (
2382 "work-day-start-mon",
2383 "Work Day Start for Monday",
2384 NULL,
2385 -1,
2386 2359,
2387 -1,
2388 G_PARAM_READWRITE));
2389
2390 g_object_class_install_property (
2391 object_class,
2392 PROP_WORK_DAY_END_MON,
2393 g_param_spec_int (
2394 "work-day-end-mon",
2395 "Work Day End for Monday",
2396 NULL,
2397 -1,
2398 2359,
2399 -1,
2400 G_PARAM_READWRITE));
2401
2402 g_object_class_install_property (
2403 object_class,
2404 PROP_WORK_DAY_START_TUE,
2405 g_param_spec_int (
2406 "work-day-start-tue",
2407 "Work Day Start for Tuesday",
2408 NULL,
2409 -1,
2410 2359,
2411 -1,
2412 G_PARAM_READWRITE));
2413
2414 g_object_class_install_property (
2415 object_class,
2416 PROP_WORK_DAY_END_TUE,
2417 g_param_spec_int (
2418 "work-day-end-tue",
2419 "Work Day End for Tuesday",
2420 NULL,
2421 -1,
2422 2359,
2423 -1,
2424 G_PARAM_READWRITE));
2425
2426 g_object_class_install_property (
2427 object_class,
2428 PROP_WORK_DAY_START_WED,
2429 g_param_spec_int (
2430 "work-day-start-wed",
2431 "Work Day Start for Wednesday",
2432 NULL,
2433 -1,
2434 2359,
2435 -1,
2436 G_PARAM_READWRITE));
2437
2438 g_object_class_install_property (
2439 object_class,
2440 PROP_WORK_DAY_END_WED,
2441 g_param_spec_int (
2442 "work-day-end-wed",
2443 "Work Day End for Wednesday",
2444 NULL,
2445 -1,
2446 2359,
2447 -1,
2448 G_PARAM_READWRITE));
2449
2450 g_object_class_install_property (
2451 object_class,
2452 PROP_WORK_DAY_START_THU,
2453 g_param_spec_int (
2454 "work-day-start-thu",
2455 "Work Day Start for Thursday",
2456 NULL,
2457 -1,
2458 2359,
2459 -1,
2460 G_PARAM_READWRITE));
2461
2462 g_object_class_install_property (
2463 object_class,
2464 PROP_WORK_DAY_END_THU,
2465 g_param_spec_int (
2466 "work-day-end-thu",
2467 "Work Day End for Thursday",
2468 NULL,
2469 -1,
2470 2359,
2471 -1,
2472 G_PARAM_READWRITE));
2473
2474 g_object_class_install_property (
2475 object_class,
2476 PROP_WORK_DAY_START_FRI,
2477 g_param_spec_int (
2478 "work-day-start-fri",
2479 "Work Day Start for Friday",
2480 NULL,
2481 -1,
2482 2359,
2483 -1,
2484 G_PARAM_READWRITE));
2485
2486 g_object_class_install_property (
2487 object_class,
2488 PROP_WORK_DAY_END_FRI,
2489 g_param_spec_int (
2490 "work-day-end-fri",
2491 "Work Day End for Friday",
2492 NULL,
2493 -1,
2494 2359,
2495 -1,
2496 G_PARAM_READWRITE));
2497
2498 g_object_class_install_property (
2499 object_class,
2500 PROP_WORK_DAY_START_SAT,
2501 g_param_spec_int (
2502 "work-day-start-sat",
2503 "Work Day Start for Saturday",
2504 NULL,
2505 -1,
2506 2359,
2507 -1,
2508 G_PARAM_READWRITE));
2509
2510 g_object_class_install_property (
2511 object_class,
2512 PROP_WORK_DAY_END_SAT,
2513 g_param_spec_int (
2514 "work-day-end-sat",
2515 "Work Day End for Saturday",
2516 NULL,
2517 -1,
2518 2359,
2519 -1,
2520 G_PARAM_READWRITE));
2521
2522 g_object_class_install_property (
2523 object_class,
2524 PROP_WORK_DAY_START_SUN,
2525 g_param_spec_int (
2526 "work-day-start-sun",
2527 "Work Day Start for Sunday",
2528 NULL,
2529 -1,
2530 2359,
2531 -1,
2532 G_PARAM_READWRITE));
2533
2534 g_object_class_install_property (
2535 object_class,
2536 PROP_WORK_DAY_END_SUN,
2537 g_param_spec_int (
2538 "work-day-end-sun",
2539 "Work Day End for Sunday",
2540 NULL,
2541 -1,
2542 2359,
2543 -1,
2544 G_PARAM_READWRITE));
2545
2546 signals[TIME_RANGE_CHANGED] = g_signal_new (
2547 "time_range_changed",
2548 G_TYPE_FROM_CLASS (class),
2549 G_SIGNAL_RUN_LAST,
2550 G_STRUCT_OFFSET (ECalModelClass, time_range_changed),
2551 NULL, NULL,
2552 e_marshal_VOID__INT64_INT64,
2553 G_TYPE_NONE, 2,
2554 G_TYPE_INT64,
2555 G_TYPE_INT64);
2556
2557 signals[ROW_APPENDED] = g_signal_new (
2558 "row_appended",
2559 G_TYPE_FROM_CLASS (class),
2560 G_SIGNAL_RUN_LAST,
2561 G_STRUCT_OFFSET (ECalModelClass, row_appended),
2562 NULL, NULL,
2563 g_cclosure_marshal_VOID__VOID,
2564 G_TYPE_NONE, 0);
2565
2566 signals[COMPS_DELETED] = g_signal_new (
2567 "comps_deleted",
2568 G_TYPE_FROM_CLASS (class),
2569 G_SIGNAL_RUN_LAST,
2570 G_STRUCT_OFFSET (ECalModelClass, comps_deleted),
2571 NULL, NULL,
2572 g_cclosure_marshal_VOID__POINTER,
2573 G_TYPE_NONE, 1,
2574 G_TYPE_POINTER);
2575
2576 signals[TIMEZONE_CHANGED] = g_signal_new (
2577 "timezone-changed",
2578 G_TYPE_FROM_CLASS (class),
2579 G_SIGNAL_RUN_LAST,
2580 G_STRUCT_OFFSET (ECalModelClass, timezone_changed),
2581 NULL, NULL,
2582 e_marshal_VOID__OBJECT_OBJECT,
2583 G_TYPE_NONE, 2,
2584 I_CAL_TYPE_TIMEZONE,
2585 I_CAL_TYPE_TIMEZONE);
2586
2587 signals[OBJECT_CREATED] = g_signal_new (
2588 "object-created",
2589 G_TYPE_FROM_CLASS (class),
2590 G_SIGNAL_RUN_LAST,
2591 G_STRUCT_OFFSET (ECalModelClass, object_created),
2592 NULL, NULL,
2593 g_cclosure_marshal_VOID__OBJECT,
2594 G_TYPE_NONE, 1, E_TYPE_CAL_CLIENT);
2595 }
2596
2597 static void
e_cal_model_table_model_init(ETableModelInterface * iface)2598 e_cal_model_table_model_init (ETableModelInterface *iface)
2599 {
2600 iface->column_count = cal_model_column_count;
2601 iface->row_count = cal_model_row_count;
2602 iface->append_row = cal_model_append_row;
2603
2604 iface->value_at = cal_model_value_at;
2605 iface->set_value_at = cal_model_set_value_at;
2606 iface->is_cell_editable = cal_model_is_cell_editable;
2607
2608 iface->duplicate_value = cal_model_duplicate_value;
2609 iface->free_value = cal_model_free_value;
2610 iface->initialize_value = cal_model_initialize_value;
2611 iface->value_is_empty = cal_model_value_is_empty;
2612 iface->value_to_string = cal_model_value_to_string;
2613 }
2614
2615 static void
e_cal_model_cal_data_model_subscriber_init(ECalDataModelSubscriberInterface * iface)2616 e_cal_model_cal_data_model_subscriber_init (ECalDataModelSubscriberInterface *iface)
2617 {
2618 iface->component_added = e_cal_model_data_subscriber_component_added;
2619 iface->component_modified = e_cal_model_data_subscriber_component_modified;
2620 iface->component_removed = e_cal_model_data_subscriber_component_removed;
2621 iface->freeze = e_cal_model_data_subscriber_freeze;
2622 iface->thaw = e_cal_model_data_subscriber_thaw;
2623 }
2624
2625 static void
e_cal_model_init(ECalModel * model)2626 e_cal_model_init (ECalModel *model)
2627 {
2628 model->priv = E_CAL_MODEL_GET_PRIVATE (model);
2629
2630 /* match none by default */
2631 model->priv->start = (time_t) -1;
2632 model->priv->end = (time_t) -1;
2633
2634 model->priv->objects = g_ptr_array_new ();
2635 model->priv->kind = I_CAL_NO_COMPONENT;
2636
2637 model->priv->use_24_hour_format = TRUE;
2638 }
2639
2640 /* updates time in a component, and keeps the timezone used in it, if exists */
2641 void
e_cal_model_update_comp_time(ECalModel * model,ECalModelComponent * comp_data,gconstpointer time_value,ICalPropertyKind kind,void (* set_func)(ICalProperty * prop,ICalTime * v),ICalProperty * (* new_func)(ICalTime * v))2642 e_cal_model_update_comp_time (ECalModel *model,
2643 ECalModelComponent *comp_data,
2644 gconstpointer time_value,
2645 ICalPropertyKind kind,
2646 void (*set_func) (ICalProperty *prop,
2647 ICalTime *v),
2648 ICalProperty * (*new_func) (ICalTime *v))
2649 {
2650 ECellDateEditValue *dv = (ECellDateEditValue *) time_value;
2651 ICalProperty *prop;
2652 ICalParameter *param;
2653 ICalTimezone *model_zone;
2654 ICalTime *tt;
2655
2656 g_return_if_fail (model != NULL);
2657 g_return_if_fail (comp_data != NULL);
2658 g_return_if_fail (set_func != NULL);
2659 g_return_if_fail (new_func != NULL);
2660
2661 prop = i_cal_component_get_first_property (comp_data->icalcomp, kind);
2662 if (prop)
2663 param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
2664 else
2665 param = NULL;
2666
2667 /* If we are setting the property to NULL (i.e. removing it), then
2668 * we remove it if it exists. */
2669 if (!dv) {
2670 if (prop) {
2671 i_cal_component_remove_property (comp_data->icalcomp, prop);
2672 g_object_unref (prop);
2673 }
2674
2675 return;
2676 }
2677
2678 model_zone = e_cal_model_get_timezone (model);
2679 tt = e_cell_date_edit_value_get_time (dv);
2680 datetime_to_zone (comp_data->client, tt, model_zone, param ? i_cal_parameter_get_tzid (param) : NULL);
2681
2682 if (prop) {
2683 set_func (prop, tt);
2684 } else {
2685 prop = new_func (tt);
2686 i_cal_component_take_property (comp_data->icalcomp, prop);
2687
2688 prop = i_cal_component_get_first_property (comp_data->icalcomp, kind);
2689 }
2690
2691 if (param) {
2692 const gchar *tzid = i_cal_parameter_get_tzid (param);
2693
2694 /* If the TZID is set to "UTC", we don't want to save the TZID. */
2695 if (!tzid || !*tzid || !strcmp (tzid, "UTC")) {
2696 i_cal_property_remove_parameter_by_kind (prop, I_CAL_TZID_PARAMETER);
2697 }
2698 } else if (model_zone) {
2699 const gchar *tzid = i_cal_timezone_get_tzid (model_zone);
2700
2701 if (tzid && *tzid) {
2702 param = i_cal_parameter_new_tzid (tzid);
2703 i_cal_property_take_parameter (prop, param);
2704 }
2705 }
2706
2707 g_clear_object (&prop);
2708 }
2709
2710 /**
2711 * e_cal_model_test_row_editable
2712 * @model: an #ECalModel
2713 * @row: Row of our interest. -1 is editable only when default client is
2714 * editable.
2715 *
2716 * Checks if component at @row is editable or not. It doesn't check bounds
2717 * for @row.
2718 *
2719 * Returns: Whether @row is editable or not.
2720 **/
2721 gboolean
e_cal_model_test_row_editable(ECalModel * model,gint row)2722 e_cal_model_test_row_editable (ECalModel *model,
2723 gint row)
2724 {
2725 gboolean readonly = FALSE;
2726 ECalClient *client = NULL;
2727
2728 if (row != -1) {
2729 ECalModelComponent *comp_data;
2730
2731 comp_data = e_cal_model_get_component_at (model, row);
2732
2733 if (comp_data != NULL && comp_data->client != NULL)
2734 client = g_object_ref (comp_data->client);
2735
2736 readonly = (client == NULL);
2737 } else {
2738 const gchar *source_uid;
2739
2740 source_uid = e_cal_model_get_default_source_uid (model);
2741
2742 /* if the source cannot be opened, then expect the client being writable;
2743 there will be shown an error if not, when saving changes anyway */
2744 readonly = source_uid == NULL;
2745
2746 if (source_uid != NULL) {
2747 ESourceRegistry *registry = e_cal_model_get_registry (model);
2748 EClientCache *client_cache = e_cal_model_get_client_cache (model);
2749 ESource *source;
2750
2751 source = e_source_registry_ref_source (registry, source_uid);
2752 if (source) {
2753 EClient *e_client;
2754
2755 e_client = e_client_cache_ref_cached_client (client_cache, source,
2756 cal_model_kind_to_extension_name (model));
2757 if (e_client) {
2758 client = E_CAL_CLIENT (e_client);
2759 } else {
2760 const gchar *parent_uid = e_source_get_parent (source);
2761
2762 /* There are couple known to be always read-only */
2763 readonly = g_strcmp0 (parent_uid, "webcal-stub") == 0 ||
2764 g_strcmp0 (parent_uid, "weather-stub") == 0 ||
2765 g_strcmp0 (parent_uid, "contacts-stub") == 0;
2766 }
2767 }
2768
2769 g_clear_object (&source);
2770 }
2771 }
2772
2773 if (!readonly && client)
2774 readonly = e_client_is_readonly (E_CLIENT (client));
2775
2776 g_clear_object (&client);
2777
2778 return !readonly;
2779 }
2780
2781 ESourceRegistry *
e_cal_model_get_registry(ECalModel * model)2782 e_cal_model_get_registry (ECalModel *model)
2783 {
2784 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2785
2786 return model->priv->registry;
2787 }
2788
2789 EShell *
e_cal_model_get_shell(ECalModel * model)2790 e_cal_model_get_shell (ECalModel *model)
2791 {
2792 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2793
2794 return model->priv->shell;
2795 }
2796
2797 ECalDataModel *
e_cal_model_get_data_model(ECalModel * model)2798 e_cal_model_get_data_model (ECalModel *model)
2799 {
2800 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2801
2802 return model->priv->data_model;
2803 }
2804
2805 EClientCache *
e_cal_model_get_client_cache(ECalModel * model)2806 e_cal_model_get_client_cache (ECalModel *model)
2807 {
2808 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2809
2810 return model->priv->client_cache;
2811 }
2812
2813 gboolean
e_cal_model_get_confirm_delete(ECalModel * model)2814 e_cal_model_get_confirm_delete (ECalModel *model)
2815 {
2816 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2817
2818 return model->priv->confirm_delete;
2819 }
2820
2821 void
e_cal_model_set_confirm_delete(ECalModel * model,gboolean confirm_delete)2822 e_cal_model_set_confirm_delete (ECalModel *model,
2823 gboolean confirm_delete)
2824 {
2825 g_return_if_fail (E_IS_CAL_MODEL (model));
2826
2827 if (model->priv->confirm_delete == confirm_delete)
2828 return;
2829
2830 model->priv->confirm_delete = confirm_delete;
2831
2832 g_object_notify (G_OBJECT (model), "confirm-delete");
2833 }
2834
2835 ICalComponentKind
e_cal_model_get_component_kind(ECalModel * model)2836 e_cal_model_get_component_kind (ECalModel *model)
2837 {
2838 g_return_val_if_fail (E_IS_CAL_MODEL (model), I_CAL_NO_COMPONENT);
2839
2840 return model->priv->kind;
2841 }
2842
2843 void
e_cal_model_set_component_kind(ECalModel * model,ICalComponentKind kind)2844 e_cal_model_set_component_kind (ECalModel *model,
2845 ICalComponentKind kind)
2846 {
2847 g_return_if_fail (E_IS_CAL_MODEL (model));
2848
2849 model->priv->kind = kind;
2850 }
2851
2852 ICalTimezone *
e_cal_model_get_timezone(ECalModel * model)2853 e_cal_model_get_timezone (ECalModel *model)
2854 {
2855 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2856
2857 return model->priv->zone;
2858 }
2859
2860 void
e_cal_model_set_timezone(ECalModel * model,const ICalTimezone * zone)2861 e_cal_model_set_timezone (ECalModel *model,
2862 const ICalTimezone *zone)
2863 {
2864 ICalTimezone *old_zone;
2865
2866 g_return_if_fail (E_IS_CAL_MODEL (model));
2867
2868 if (model->priv->zone == zone)
2869 return;
2870
2871 e_table_model_pre_change (E_TABLE_MODEL (model));
2872 old_zone = model->priv->zone;
2873 model->priv->zone = zone ? e_cal_util_copy_timezone (zone) : NULL;
2874
2875 /* the timezone affects the times shown for date fields,
2876 * so we need to redisplay everything */
2877 e_table_model_changed (E_TABLE_MODEL (model));
2878
2879 g_object_notify (G_OBJECT (model), "timezone");
2880 g_signal_emit (
2881 model, signals[TIMEZONE_CHANGED], 0,
2882 old_zone, model->priv->zone);
2883
2884 g_clear_object (&old_zone);
2885 }
2886
2887 gboolean
e_cal_model_get_compress_weekend(ECalModel * model)2888 e_cal_model_get_compress_weekend (ECalModel *model)
2889 {
2890 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2891
2892 return model->priv->compress_weekend;
2893 }
2894
2895 void
e_cal_model_set_compress_weekend(ECalModel * model,gboolean compress_weekend)2896 e_cal_model_set_compress_weekend (ECalModel *model,
2897 gboolean compress_weekend)
2898 {
2899 g_return_if_fail (E_IS_CAL_MODEL (model));
2900
2901 if (model->priv->compress_weekend == compress_weekend)
2902 return;
2903
2904 model->priv->compress_weekend = compress_weekend;
2905
2906 g_object_notify (G_OBJECT (model), "compress-weekend");
2907 }
2908
2909 void
e_cal_model_set_default_category(ECalModel * model,const gchar * default_category)2910 e_cal_model_set_default_category (ECalModel *model,
2911 const gchar *default_category)
2912 {
2913 g_return_if_fail (E_IS_CAL_MODEL (model));
2914
2915 g_free (model->priv->default_category);
2916 model->priv->default_category = g_strdup (default_category);
2917 }
2918
2919 gint
e_cal_model_get_default_reminder_interval(ECalModel * model)2920 e_cal_model_get_default_reminder_interval (ECalModel *model)
2921 {
2922 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
2923
2924 return model->priv->default_reminder_interval;
2925 }
2926
2927 void
e_cal_model_set_default_reminder_interval(ECalModel * model,gint default_reminder_interval)2928 e_cal_model_set_default_reminder_interval (ECalModel *model,
2929 gint default_reminder_interval)
2930 {
2931 g_return_if_fail (E_IS_CAL_MODEL (model));
2932
2933 if (model->priv->default_reminder_interval == default_reminder_interval)
2934 return;
2935
2936 model->priv->default_reminder_interval = default_reminder_interval;
2937
2938 g_object_notify (G_OBJECT (model), "default-reminder-interval");
2939 }
2940
2941 EDurationType
e_cal_model_get_default_reminder_units(ECalModel * model)2942 e_cal_model_get_default_reminder_units (ECalModel *model)
2943 {
2944 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
2945
2946 return model->priv->default_reminder_units;
2947 }
2948
2949 void
e_cal_model_set_default_reminder_units(ECalModel * model,EDurationType default_reminder_units)2950 e_cal_model_set_default_reminder_units (ECalModel *model,
2951 EDurationType default_reminder_units)
2952 {
2953 g_return_if_fail (E_IS_CAL_MODEL (model));
2954
2955 if (model->priv->default_reminder_units == default_reminder_units)
2956 return;
2957
2958 model->priv->default_reminder_units = default_reminder_units;
2959
2960 g_object_notify (G_OBJECT (model), "default-reminder-units");
2961 }
2962
2963 gboolean
e_cal_model_get_use_24_hour_format(ECalModel * model)2964 e_cal_model_get_use_24_hour_format (ECalModel *model)
2965 {
2966 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2967
2968 return model->priv->use_24_hour_format;
2969 }
2970
2971 void
e_cal_model_set_use_24_hour_format(ECalModel * model,gboolean use_24_hour_format)2972 e_cal_model_set_use_24_hour_format (ECalModel *model,
2973 gboolean use_24_hour_format)
2974 {
2975 g_return_if_fail (E_IS_CAL_MODEL (model));
2976
2977 if (model->priv->use_24_hour_format == use_24_hour_format)
2978 return;
2979
2980 e_table_model_pre_change (E_TABLE_MODEL (model));
2981 model->priv->use_24_hour_format = use_24_hour_format;
2982
2983 /* Get the views to redraw themselves. */
2984 e_table_model_changed (E_TABLE_MODEL (model));
2985
2986 g_object_notify (G_OBJECT (model), "use-24-hour-format");
2987 }
2988
2989 gboolean
e_cal_model_get_use_default_reminder(ECalModel * model)2990 e_cal_model_get_use_default_reminder (ECalModel *model)
2991 {
2992 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2993
2994 return model->priv->use_default_reminder;
2995 }
2996
2997 void
e_cal_model_set_use_default_reminder(ECalModel * model,gboolean use_default_reminder)2998 e_cal_model_set_use_default_reminder (ECalModel *model,
2999 gboolean use_default_reminder)
3000 {
3001 g_return_if_fail (E_IS_CAL_MODEL (model));
3002
3003 if (model->priv->use_default_reminder == use_default_reminder)
3004 return;
3005
3006 model->priv->use_default_reminder = use_default_reminder;
3007
3008 g_object_notify (G_OBJECT (model), "use-default-reminder");
3009 }
3010
3011 GDateWeekday
e_cal_model_get_week_start_day(ECalModel * model)3012 e_cal_model_get_week_start_day (ECalModel *model)
3013 {
3014 g_return_val_if_fail (E_IS_CAL_MODEL (model), G_DATE_BAD_WEEKDAY);
3015
3016 return model->priv->week_start_day;
3017 }
3018
3019 void
e_cal_model_set_week_start_day(ECalModel * model,GDateWeekday week_start_day)3020 e_cal_model_set_week_start_day (ECalModel *model,
3021 GDateWeekday week_start_day)
3022 {
3023 g_return_if_fail (E_IS_CAL_MODEL (model));
3024 g_return_if_fail (g_date_valid_weekday (week_start_day));
3025
3026 if (model->priv->week_start_day == week_start_day)
3027 return;
3028
3029 model->priv->week_start_day = week_start_day;
3030
3031 g_object_notify (G_OBJECT (model), "week-start-day");
3032 }
3033
3034 gboolean
e_cal_model_get_work_day(ECalModel * model,GDateWeekday weekday)3035 e_cal_model_get_work_day (ECalModel *model,
3036 GDateWeekday weekday)
3037 {
3038 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
3039 g_return_val_if_fail (g_date_valid_weekday (weekday), FALSE);
3040
3041 return model->priv->work_days[weekday];
3042 }
3043
3044 void
e_cal_model_set_work_day(ECalModel * model,GDateWeekday weekday,gboolean work_day)3045 e_cal_model_set_work_day (ECalModel *model,
3046 GDateWeekday weekday,
3047 gboolean work_day)
3048 {
3049 const gchar *property_name = NULL;
3050
3051 g_return_if_fail (E_IS_CAL_MODEL (model));
3052 g_return_if_fail (g_date_valid_weekday (weekday));
3053
3054 if (work_day == model->priv->work_days[weekday])
3055 return;
3056
3057 model->priv->work_days[weekday] = work_day;
3058
3059 switch (weekday) {
3060 case G_DATE_MONDAY:
3061 property_name = "work-day-monday";
3062 break;
3063 case G_DATE_TUESDAY:
3064 property_name = "work-day-tuesday";
3065 break;
3066 case G_DATE_WEDNESDAY:
3067 property_name = "work-day-wednesday";
3068 break;
3069 case G_DATE_THURSDAY:
3070 property_name = "work-day-thursday";
3071 break;
3072 case G_DATE_FRIDAY:
3073 property_name = "work-day-friday";
3074 break;
3075 case G_DATE_SATURDAY:
3076 property_name = "work-day-saturday";
3077 break;
3078 case G_DATE_SUNDAY:
3079 property_name = "work-day-sunday";
3080 break;
3081 default:
3082 g_warn_if_reached ();
3083 }
3084
3085 g_object_notify (G_OBJECT (model), property_name);
3086 }
3087
3088 /**
3089 * e_cal_model_get_work_day_first:
3090 * @model: an #ECalModel
3091 *
3092 * Returns the first work day with respect to #ECalModel:work-week-start.
3093 * If no work days are set, the function returns %G_DATE_BAD_WEEKDAY.
3094 *
3095 * Returns: first work day of the week, or %G_DATE_BAD_WEEKDAY
3096 **/
3097 GDateWeekday
e_cal_model_get_work_day_first(ECalModel * model)3098 e_cal_model_get_work_day_first (ECalModel *model)
3099 {
3100 GDateWeekday weekday;
3101 gint ii;
3102
3103 g_return_val_if_fail (E_IS_CAL_MODEL (model), G_DATE_BAD_WEEKDAY);
3104
3105 weekday = e_cal_model_get_week_start_day (model);
3106
3107 for (ii = 0; ii < 7; ii++) {
3108 if (e_cal_model_get_work_day (model, weekday))
3109 return weekday;
3110 weekday = e_weekday_get_next (weekday);
3111 }
3112
3113 return G_DATE_BAD_WEEKDAY;
3114 }
3115
3116 /**
3117 * e_cal_model_get_work_day_last:
3118 * @model: an #ECalModel
3119 *
3120 * Returns the last work day with respect to #ECalModel:work-week-start.
3121 * If no work days are set, the function returns %G_DATE_BAD_WEEKDAY.
3122 *
3123 * Returns: last work day of the week, or %G_DATE_BAD_WEEKDAY
3124 **/
3125 GDateWeekday
e_cal_model_get_work_day_last(ECalModel * model)3126 e_cal_model_get_work_day_last (ECalModel *model)
3127 {
3128 GDateWeekday weekday;
3129 gint ii;
3130
3131 g_return_val_if_fail (E_IS_CAL_MODEL (model), G_DATE_BAD_WEEKDAY);
3132
3133 weekday = e_cal_model_get_week_start_day (model);
3134
3135 for (ii = 0; ii < 7; ii++) {
3136 weekday = e_weekday_get_prev (weekday);
3137 if (e_cal_model_get_work_day (model, weekday))
3138 return weekday;
3139 }
3140
3141 return G_DATE_BAD_WEEKDAY;
3142 }
3143
3144 gint
e_cal_model_get_work_day_end_hour(ECalModel * model)3145 e_cal_model_get_work_day_end_hour (ECalModel *model)
3146 {
3147 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3148
3149 return model->priv->work_day_end_hour;
3150 }
3151
3152 void
e_cal_model_set_work_day_end_hour(ECalModel * model,gint work_day_end_hour)3153 e_cal_model_set_work_day_end_hour (ECalModel *model,
3154 gint work_day_end_hour)
3155 {
3156 g_return_if_fail (E_IS_CAL_MODEL (model));
3157
3158 if (model->priv->work_day_end_hour == work_day_end_hour)
3159 return;
3160
3161 model->priv->work_day_end_hour = work_day_end_hour;
3162
3163 g_object_notify (G_OBJECT (model), "work-day-end-hour");
3164 }
3165
3166 gint
e_cal_model_get_work_day_end_minute(ECalModel * model)3167 e_cal_model_get_work_day_end_minute (ECalModel *model)
3168 {
3169 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3170
3171 return model->priv->work_day_end_minute;
3172 }
3173
3174 void
e_cal_model_set_work_day_end_minute(ECalModel * model,gint work_day_end_minute)3175 e_cal_model_set_work_day_end_minute (ECalModel *model,
3176 gint work_day_end_minute)
3177 {
3178 g_return_if_fail (E_IS_CAL_MODEL (model));
3179
3180 if (model->priv->work_day_end_minute == work_day_end_minute)
3181 return;
3182
3183 model->priv->work_day_end_minute = work_day_end_minute;
3184
3185 g_object_notify (G_OBJECT (model), "work-day-end-minute");
3186 }
3187
3188 gint
e_cal_model_get_work_day_start_hour(ECalModel * model)3189 e_cal_model_get_work_day_start_hour (ECalModel *model)
3190 {
3191 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3192
3193 return model->priv->work_day_start_hour;
3194 }
3195
3196 void
e_cal_model_set_work_day_start_hour(ECalModel * model,gint work_day_start_hour)3197 e_cal_model_set_work_day_start_hour (ECalModel *model,
3198 gint work_day_start_hour)
3199 {
3200 g_return_if_fail (E_IS_CAL_MODEL (model));
3201
3202 if (model->priv->work_day_start_hour == work_day_start_hour)
3203 return;
3204
3205 model->priv->work_day_start_hour = work_day_start_hour;
3206
3207 g_object_notify (G_OBJECT (model), "work-day-start-hour");
3208 }
3209
3210 gint
e_cal_model_get_work_day_start_minute(ECalModel * model)3211 e_cal_model_get_work_day_start_minute (ECalModel *model)
3212 {
3213 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3214
3215 return model->priv->work_day_start_minute;
3216 }
3217
3218 void
e_cal_model_set_work_day_start_minute(ECalModel * model,gint work_day_start_minute)3219 e_cal_model_set_work_day_start_minute (ECalModel *model,
3220 gint work_day_start_minute)
3221 {
3222 g_return_if_fail (E_IS_CAL_MODEL (model));
3223
3224 if (model->priv->work_day_start_minute == work_day_start_minute)
3225 return;
3226
3227 model->priv->work_day_start_minute = work_day_start_minute;
3228
3229 g_object_notify (G_OBJECT (model), "work-day-start-minute");
3230 }
3231
3232 gint
e_cal_model_get_work_day_start_mon(ECalModel * model)3233 e_cal_model_get_work_day_start_mon (ECalModel *model)
3234 {
3235 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3236
3237 return model->priv->work_day_start_mon;
3238 }
3239
3240 void
e_cal_model_set_work_day_start_mon(ECalModel * model,gint work_day_start)3241 e_cal_model_set_work_day_start_mon (ECalModel *model,
3242 gint work_day_start)
3243 {
3244 g_return_if_fail (E_IS_CAL_MODEL (model));
3245
3246 if (model->priv->work_day_start_mon == work_day_start)
3247 return;
3248
3249 model->priv->work_day_start_mon = work_day_start;
3250
3251 g_object_notify (G_OBJECT (model), "work-day-start-mon");
3252 }
3253
3254 gint
e_cal_model_get_work_day_end_mon(ECalModel * model)3255 e_cal_model_get_work_day_end_mon (ECalModel *model)
3256 {
3257 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3258
3259 return model->priv->work_day_end_mon;
3260 }
3261
3262 void
e_cal_model_set_work_day_end_mon(ECalModel * model,gint work_day_end)3263 e_cal_model_set_work_day_end_mon (ECalModel *model,
3264 gint work_day_end)
3265 {
3266 g_return_if_fail (E_IS_CAL_MODEL (model));
3267
3268 if (model->priv->work_day_end_mon == work_day_end)
3269 return;
3270
3271 model->priv->work_day_end_mon = work_day_end;
3272
3273 g_object_notify (G_OBJECT (model), "work-day-end-mon");
3274 }
3275
3276 gint
e_cal_model_get_work_day_start_tue(ECalModel * model)3277 e_cal_model_get_work_day_start_tue (ECalModel *model)
3278 {
3279 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3280
3281 return model->priv->work_day_start_tue;
3282 }
3283
3284 void
e_cal_model_set_work_day_start_tue(ECalModel * model,gint work_day_start)3285 e_cal_model_set_work_day_start_tue (ECalModel *model,
3286 gint work_day_start)
3287 {
3288 g_return_if_fail (E_IS_CAL_MODEL (model));
3289
3290 if (model->priv->work_day_start_tue == work_day_start)
3291 return;
3292
3293 model->priv->work_day_start_tue = work_day_start;
3294
3295 g_object_notify (G_OBJECT (model), "work-day-start-tue");
3296 }
3297
3298 gint
e_cal_model_get_work_day_end_tue(ECalModel * model)3299 e_cal_model_get_work_day_end_tue (ECalModel *model)
3300 {
3301 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3302
3303 return model->priv->work_day_end_tue;
3304 }
3305
3306 void
e_cal_model_set_work_day_end_tue(ECalModel * model,gint work_day_end)3307 e_cal_model_set_work_day_end_tue (ECalModel *model,
3308 gint work_day_end)
3309 {
3310 g_return_if_fail (E_IS_CAL_MODEL (model));
3311
3312 if (model->priv->work_day_end_tue == work_day_end)
3313 return;
3314
3315 model->priv->work_day_end_tue = work_day_end;
3316
3317 g_object_notify (G_OBJECT (model), "work-day-end-tue");
3318 }
3319
3320 gint
e_cal_model_get_work_day_start_wed(ECalModel * model)3321 e_cal_model_get_work_day_start_wed (ECalModel *model)
3322 {
3323 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3324
3325 return model->priv->work_day_start_wed;
3326 }
3327
3328 void
e_cal_model_set_work_day_start_wed(ECalModel * model,gint work_day_start)3329 e_cal_model_set_work_day_start_wed (ECalModel *model,
3330 gint work_day_start)
3331 {
3332 g_return_if_fail (E_IS_CAL_MODEL (model));
3333
3334 if (model->priv->work_day_start_wed == work_day_start)
3335 return;
3336
3337 model->priv->work_day_start_wed = work_day_start;
3338
3339 g_object_notify (G_OBJECT (model), "work-day-start-wed");
3340 }
3341
3342 gint
e_cal_model_get_work_day_end_wed(ECalModel * model)3343 e_cal_model_get_work_day_end_wed (ECalModel *model)
3344 {
3345 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3346
3347 return model->priv->work_day_end_wed;
3348 }
3349
3350 void
e_cal_model_set_work_day_end_wed(ECalModel * model,gint work_day_end)3351 e_cal_model_set_work_day_end_wed (ECalModel *model,
3352 gint work_day_end)
3353 {
3354 g_return_if_fail (E_IS_CAL_MODEL (model));
3355
3356 if (model->priv->work_day_end_wed == work_day_end)
3357 return;
3358
3359 model->priv->work_day_end_wed = work_day_end;
3360
3361 g_object_notify (G_OBJECT (model), "work-day-end-wed");
3362 }
3363
3364 gint
e_cal_model_get_work_day_start_thu(ECalModel * model)3365 e_cal_model_get_work_day_start_thu (ECalModel *model)
3366 {
3367 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3368
3369 return model->priv->work_day_start_thu;
3370 }
3371
3372 void
e_cal_model_set_work_day_start_thu(ECalModel * model,gint work_day_start)3373 e_cal_model_set_work_day_start_thu (ECalModel *model,
3374 gint work_day_start)
3375 {
3376 g_return_if_fail (E_IS_CAL_MODEL (model));
3377
3378 if (model->priv->work_day_start_thu == work_day_start)
3379 return;
3380
3381 model->priv->work_day_start_thu = work_day_start;
3382
3383 g_object_notify (G_OBJECT (model), "work-day-start-thu");
3384 }
3385
3386 gint
e_cal_model_get_work_day_end_thu(ECalModel * model)3387 e_cal_model_get_work_day_end_thu (ECalModel *model)
3388 {
3389 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3390
3391 return model->priv->work_day_end_thu;
3392 }
3393
3394 void
e_cal_model_set_work_day_end_thu(ECalModel * model,gint work_day_end)3395 e_cal_model_set_work_day_end_thu (ECalModel *model,
3396 gint work_day_end)
3397 {
3398 g_return_if_fail (E_IS_CAL_MODEL (model));
3399
3400 if (model->priv->work_day_end_thu == work_day_end)
3401 return;
3402
3403 model->priv->work_day_end_thu = work_day_end;
3404
3405 g_object_notify (G_OBJECT (model), "work-day-end-thu");
3406 }
3407
3408 gint
e_cal_model_get_work_day_start_fri(ECalModel * model)3409 e_cal_model_get_work_day_start_fri (ECalModel *model)
3410 {
3411 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3412
3413 return model->priv->work_day_start_fri;
3414 }
3415
3416 void
e_cal_model_set_work_day_start_fri(ECalModel * model,gint work_day_start)3417 e_cal_model_set_work_day_start_fri (ECalModel *model,
3418 gint work_day_start)
3419 {
3420 g_return_if_fail (E_IS_CAL_MODEL (model));
3421
3422 if (model->priv->work_day_start_fri == work_day_start)
3423 return;
3424
3425 model->priv->work_day_start_fri = work_day_start;
3426
3427 g_object_notify (G_OBJECT (model), "work-day-start-fri");
3428 }
3429
3430 gint
e_cal_model_get_work_day_end_fri(ECalModel * model)3431 e_cal_model_get_work_day_end_fri (ECalModel *model)
3432 {
3433 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3434
3435 return model->priv->work_day_end_fri;
3436 }
3437
3438 void
e_cal_model_set_work_day_end_fri(ECalModel * model,gint work_day_end)3439 e_cal_model_set_work_day_end_fri (ECalModel *model,
3440 gint work_day_end)
3441 {
3442 g_return_if_fail (E_IS_CAL_MODEL (model));
3443
3444 if (model->priv->work_day_end_fri == work_day_end)
3445 return;
3446
3447 model->priv->work_day_end_fri = work_day_end;
3448
3449 g_object_notify (G_OBJECT (model), "work-day-end-fri");
3450 }
3451
3452 gint
e_cal_model_get_work_day_start_sat(ECalModel * model)3453 e_cal_model_get_work_day_start_sat (ECalModel *model)
3454 {
3455 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3456
3457 return model->priv->work_day_start_sat;
3458 }
3459
3460 void
e_cal_model_set_work_day_start_sat(ECalModel * model,gint work_day_start)3461 e_cal_model_set_work_day_start_sat (ECalModel *model,
3462 gint work_day_start)
3463 {
3464 g_return_if_fail (E_IS_CAL_MODEL (model));
3465
3466 if (model->priv->work_day_start_sat == work_day_start)
3467 return;
3468
3469 model->priv->work_day_start_sat = work_day_start;
3470
3471 g_object_notify (G_OBJECT (model), "work-day-start-sat");
3472 }
3473
3474 gint
e_cal_model_get_work_day_end_sat(ECalModel * model)3475 e_cal_model_get_work_day_end_sat (ECalModel *model)
3476 {
3477 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3478
3479 return model->priv->work_day_end_sat;
3480 }
3481
3482 void
e_cal_model_set_work_day_end_sat(ECalModel * model,gint work_day_end)3483 e_cal_model_set_work_day_end_sat (ECalModel *model,
3484 gint work_day_end)
3485 {
3486 g_return_if_fail (E_IS_CAL_MODEL (model));
3487
3488 if (model->priv->work_day_end_sat == work_day_end)
3489 return;
3490
3491 model->priv->work_day_end_sat = work_day_end;
3492
3493 g_object_notify (G_OBJECT (model), "work-day-end-sat");
3494 }
3495
3496 gint
e_cal_model_get_work_day_start_sun(ECalModel * model)3497 e_cal_model_get_work_day_start_sun (ECalModel *model)
3498 {
3499 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3500
3501 return model->priv->work_day_start_sun;
3502 }
3503
3504 void
e_cal_model_set_work_day_start_sun(ECalModel * model,gint work_day_start)3505 e_cal_model_set_work_day_start_sun (ECalModel *model,
3506 gint work_day_start)
3507 {
3508 g_return_if_fail (E_IS_CAL_MODEL (model));
3509
3510 if (model->priv->work_day_start_sun == work_day_start)
3511 return;
3512
3513 model->priv->work_day_start_sun = work_day_start;
3514
3515 g_object_notify (G_OBJECT (model), "work-day-start-sun");
3516 }
3517
3518 gint
e_cal_model_get_work_day_end_sun(ECalModel * model)3519 e_cal_model_get_work_day_end_sun (ECalModel *model)
3520 {
3521 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3522
3523 return model->priv->work_day_end_sun;
3524 }
3525
3526 void
e_cal_model_set_work_day_end_sun(ECalModel * model,gint work_day_end)3527 e_cal_model_set_work_day_end_sun (ECalModel *model,
3528 gint work_day_end)
3529 {
3530 g_return_if_fail (E_IS_CAL_MODEL (model));
3531
3532 if (model->priv->work_day_end_sun == work_day_end)
3533 return;
3534
3535 model->priv->work_day_end_sun = work_day_end;
3536
3537 g_object_notify (G_OBJECT (model), "work-day-end-sun");
3538 }
3539
3540 void
e_cal_model_get_work_day_range_for(ECalModel * model,GDateWeekday weekday,gint * start_hour,gint * start_minute,gint * end_hour,gint * end_minute)3541 e_cal_model_get_work_day_range_for (ECalModel *model,
3542 GDateWeekday weekday,
3543 gint *start_hour,
3544 gint *start_minute,
3545 gint *end_hour,
3546 gint *end_minute)
3547 {
3548 gint start_adept = -1, end_adept = -1;
3549
3550 g_return_if_fail (E_IS_CAL_MODEL (model));
3551 g_return_if_fail (start_hour != NULL);
3552 g_return_if_fail (start_minute != NULL);
3553 g_return_if_fail (end_hour != NULL);
3554 g_return_if_fail (end_minute != NULL);
3555
3556 switch (weekday) {
3557 case G_DATE_MONDAY:
3558 start_adept = e_cal_model_get_work_day_start_mon (model);
3559 end_adept = e_cal_model_get_work_day_end_mon (model);
3560 break;
3561 case G_DATE_TUESDAY:
3562 start_adept = e_cal_model_get_work_day_start_tue (model);
3563 end_adept = e_cal_model_get_work_day_end_tue (model);
3564 break;
3565 case G_DATE_WEDNESDAY:
3566 start_adept = e_cal_model_get_work_day_start_wed (model);
3567 end_adept = e_cal_model_get_work_day_end_wed (model);
3568 break;
3569 case G_DATE_THURSDAY:
3570 start_adept = e_cal_model_get_work_day_start_thu (model);
3571 end_adept = e_cal_model_get_work_day_end_thu (model);
3572 break;
3573 case G_DATE_FRIDAY:
3574 start_adept = e_cal_model_get_work_day_start_fri (model);
3575 end_adept = e_cal_model_get_work_day_end_fri (model);
3576 break;
3577 case G_DATE_SATURDAY:
3578 start_adept = e_cal_model_get_work_day_start_sat (model);
3579 end_adept = e_cal_model_get_work_day_end_sat (model);
3580 break;
3581 case G_DATE_SUNDAY:
3582 start_adept = e_cal_model_get_work_day_start_sun (model);
3583 end_adept = e_cal_model_get_work_day_end_sun (model);
3584 break;
3585 default:
3586 break;
3587 }
3588
3589 if (start_adept > 0 && (start_adept / 100) >= 0 && (start_adept / 100) <= 23 &&
3590 (start_adept % 100) >= 0 && (start_adept % 100) <= 59) {
3591 *start_hour = start_adept / 100;
3592 *start_minute = start_adept % 100;
3593 } else {
3594 *start_hour = e_cal_model_get_work_day_start_hour (model);
3595 *start_minute = e_cal_model_get_work_day_start_minute (model);
3596 }
3597
3598 if (end_adept > 0 && (end_adept / 100) >= 0 && (end_adept / 100) <= 23 &&
3599 (end_adept % 100) >= 0 && (end_adept % 100) <= 59) {
3600 *end_hour = end_adept / 100;
3601 *end_minute = end_adept % 100;
3602 } else {
3603 *end_hour = e_cal_model_get_work_day_end_hour (model);
3604 *end_minute = e_cal_model_get_work_day_end_minute (model);
3605 }
3606 }
3607
3608 const gchar *
e_cal_model_get_default_source_uid(ECalModel * model)3609 e_cal_model_get_default_source_uid (ECalModel *model)
3610 {
3611 g_return_val_if_fail (model != NULL, NULL);
3612 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3613
3614 if (model->priv->default_source_uid && !*model->priv->default_source_uid)
3615 return NULL;
3616
3617 return model->priv->default_source_uid;
3618 }
3619
3620 void
e_cal_model_set_default_source_uid(ECalModel * model,const gchar * source_uid)3621 e_cal_model_set_default_source_uid (ECalModel *model,
3622 const gchar *source_uid)
3623 {
3624 g_return_if_fail (E_IS_CAL_MODEL (model));
3625
3626 if (g_strcmp0 (model->priv->default_source_uid, source_uid) == 0)
3627 return;
3628
3629 g_free (model->priv->default_source_uid);
3630 model->priv->default_source_uid = g_strdup (source_uid);
3631
3632 g_object_notify (G_OBJECT (model), "default-source-uid");
3633 }
3634
3635 static ECalModelComponent *
search_by_id_and_client(ECalModelPrivate * priv,ECalClient * client,const ECalComponentId * id)3636 search_by_id_and_client (ECalModelPrivate *priv,
3637 ECalClient *client,
3638 const ECalComponentId *id)
3639 {
3640 gint i;
3641
3642 for (i = 0; i < priv->objects->len; i++) {
3643 ECalModelComponent *comp_data = g_ptr_array_index (priv->objects, i);
3644
3645 if (comp_data) {
3646 const gchar *uid;
3647 gchar *rid;
3648 gboolean has_rid = e_cal_component_id_get_rid (id) != NULL;
3649
3650 uid = i_cal_component_get_uid (comp_data->icalcomp);
3651 rid = e_cal_util_component_get_recurid_as_string (comp_data->icalcomp);
3652
3653 if (uid && *uid) {
3654 if ((!client || comp_data->client == client) &&
3655 !g_strcmp0 (e_cal_component_id_get_uid (id), uid)) {
3656 if (has_rid) {
3657 if (!(rid && *rid && !g_strcmp0 (e_cal_component_id_get_rid (id), rid))) {
3658 g_free (rid);
3659 continue;
3660 }
3661 }
3662 g_free (rid);
3663 return comp_data;
3664 }
3665 }
3666
3667 g_free (rid);
3668 }
3669 }
3670
3671 return NULL;
3672 }
3673
3674 void
e_cal_model_remove_all_objects(ECalModel * model)3675 e_cal_model_remove_all_objects (ECalModel *model)
3676 {
3677 ECalModelComponent *comp_data;
3678 ETableModel *table_model;
3679 GSList *comps = NULL;
3680 guint ii;
3681
3682 table_model = E_TABLE_MODEL (model);
3683
3684 for (ii = 0; ii < model->priv->objects->len; ii++) {
3685 comp_data = g_ptr_array_index (model->priv->objects, ii);
3686
3687 if (comp_data)
3688 comps = g_slist_prepend (comps, comp_data);
3689 }
3690
3691 ii = model->priv->objects->len;
3692
3693 e_table_model_pre_change (table_model);
3694 e_table_model_rows_deleted (table_model, 0, ii);
3695
3696 g_ptr_array_set_size (model->priv->objects, 0);
3697
3698 if (comps)
3699 g_signal_emit (model, signals[COMPS_DELETED], 0, comps);
3700
3701 g_slist_free_full (comps, g_object_unref);
3702 }
3703
3704 void
e_cal_model_get_time_range(ECalModel * model,time_t * start,time_t * end)3705 e_cal_model_get_time_range (ECalModel *model,
3706 time_t *start,
3707 time_t *end)
3708 {
3709 ECalModelPrivate *priv;
3710
3711 g_return_if_fail (model != NULL);
3712 g_return_if_fail (E_IS_CAL_MODEL (model));
3713
3714 priv = model->priv;
3715
3716 if (start)
3717 *start = priv->start;
3718
3719 if (end)
3720 *end = priv->end;
3721 }
3722
3723 void
e_cal_model_set_time_range(ECalModel * model,time_t start,time_t end)3724 e_cal_model_set_time_range (ECalModel *model,
3725 time_t start,
3726 time_t end)
3727 {
3728 ECalModelPrivate *priv;
3729 ECalDataModelSubscriber *subscriber;
3730
3731 g_return_if_fail (model != NULL);
3732 g_return_if_fail (E_IS_CAL_MODEL (model));
3733 g_return_if_fail (start >= 0 && end >= 0);
3734 g_return_if_fail (start <= end);
3735
3736 priv = model->priv;
3737
3738 if (start != (time_t) 0 && end != (time_t) 0) {
3739 end = time_day_end_with_zone (end, priv->zone) - 1;
3740 }
3741
3742 if (priv->start == start && priv->end == end)
3743 return;
3744
3745 subscriber = E_CAL_DATA_MODEL_SUBSCRIBER (model);
3746 priv->start = start;
3747 priv->end = end;
3748
3749 g_signal_emit (model, signals[TIME_RANGE_CHANGED], 0, (gint64) start, (gint64) end);
3750
3751 e_cal_data_model_subscribe (model->priv->data_model, subscriber, start, end);
3752 }
3753
3754 /**
3755 * e_cal_model_create_component_with_defaults_sync
3756 */
3757 ICalComponent *
e_cal_model_create_component_with_defaults_sync(ECalModel * model,ECalClient * client,gboolean all_day,GCancellable * cancellable,GError ** error)3758 e_cal_model_create_component_with_defaults_sync (ECalModel *model,
3759 ECalClient *client,
3760 gboolean all_day,
3761 GCancellable *cancellable,
3762 GError **error)
3763 {
3764 ECalComponent *comp = NULL;
3765 ICalComponent *icomp;
3766
3767 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3768
3769 if (client) {
3770 switch (model->priv->kind) {
3771 case I_CAL_VEVENT_COMPONENT :
3772 comp = cal_comp_event_new_with_defaults_sync (
3773 client, all_day,
3774 e_cal_model_get_use_default_reminder (model),
3775 e_cal_model_get_default_reminder_interval (model),
3776 e_cal_model_get_default_reminder_units (model),
3777 cancellable, error);
3778 break;
3779 case I_CAL_VTODO_COMPONENT :
3780 comp = cal_comp_task_new_with_defaults_sync (client, cancellable, error);
3781 break;
3782 case I_CAL_VJOURNAL_COMPONENT :
3783 comp = cal_comp_memo_new_with_defaults_sync (client, cancellable, error);
3784 break;
3785 default:
3786 g_warn_if_reached ();
3787 return NULL;
3788 }
3789 }
3790
3791 if (comp) {
3792 icomp = i_cal_component_clone (e_cal_component_get_icalcomponent (comp));
3793 g_object_unref (comp);
3794 } else {
3795 icomp = i_cal_component_new (model->priv->kind);
3796 }
3797
3798 /* make sure the component has a UID */
3799 if (!i_cal_component_get_uid (icomp)) {
3800 gchar *uid;
3801
3802 uid = e_util_generate_uid ();
3803 i_cal_component_set_uid (icomp, uid);
3804
3805 g_free (uid);
3806 }
3807
3808 return icomp;
3809 }
3810
3811 /**
3812 * Returns information about attendees in the component.
3813 * If there are no attendees, the function returns NULL.
3814 *
3815 * The information is like "Status: Accepted: X Declined: Y ...".
3816 *
3817 * Free returned pointer with g_free.
3818 **/
3819 gchar *
e_cal_model_get_attendees_status_info(ECalModel * model,ECalComponent * comp,ECalClient * cal_client)3820 e_cal_model_get_attendees_status_info (ECalModel *model,
3821 ECalComponent *comp,
3822 ECalClient *cal_client)
3823 {
3824 struct _values {
3825 ICalParameterPartstat status;
3826 const gchar *caption;
3827 gint count;
3828 } values[] = {
3829 { I_CAL_PARTSTAT_ACCEPTED, N_("Accepted"), 0 },
3830 { I_CAL_PARTSTAT_DECLINED, N_("Declined"), 0 },
3831 { I_CAL_PARTSTAT_TENTATIVE, N_("Tentative"), 0 },
3832 { I_CAL_PARTSTAT_DELEGATED, N_("Delegated"), 0 },
3833 { I_CAL_PARTSTAT_NEEDSACTION, N_("Needs action"), 0 },
3834 { I_CAL_PARTSTAT_NONE, N_("Other"), 0 },
3835 { I_CAL_PARTSTAT_X, NULL, -1 }
3836 };
3837
3838 ESourceRegistry *registry;
3839 GSList *attendees = NULL, *a;
3840 gboolean have = FALSE;
3841 gchar *res = NULL;
3842 gint i;
3843
3844 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3845
3846 registry = e_cal_model_get_registry (model);
3847
3848 if (!comp || !e_cal_component_has_attendees (comp) ||
3849 !itip_organizer_is_user_ex (registry, comp, cal_client, TRUE))
3850 return NULL;
3851
3852 attendees = e_cal_component_get_attendees (comp);
3853
3854 for (a = attendees; a; a = a->next) {
3855 ECalComponentAttendee *att = a->data;
3856
3857 if (att && e_cal_component_attendee_get_cutype (att) == I_CAL_CUTYPE_INDIVIDUAL &&
3858 (e_cal_component_attendee_get_role (att) == I_CAL_ROLE_CHAIR ||
3859 e_cal_component_attendee_get_role (att) == I_CAL_ROLE_REQPARTICIPANT ||
3860 e_cal_component_attendee_get_role (att) == I_CAL_ROLE_OPTPARTICIPANT)) {
3861 have = TRUE;
3862
3863 for (i = 0; values[i].count != -1; i++) {
3864 if (e_cal_component_attendee_get_partstat (att) == values[i].status || values[i].status == I_CAL_PARTSTAT_NONE) {
3865 values[i].count++;
3866 break;
3867 }
3868 }
3869 }
3870 }
3871
3872 if (have) {
3873 GString *str = g_string_new ("");
3874
3875 for (i = 0; values[i].count != -1; i++) {
3876 if (values[i].count > 0) {
3877 if (str->str && *str->str)
3878 g_string_append (str, " ");
3879
3880 g_string_append_printf (str, "%s: %d", _(values[i].caption), values[i].count);
3881 }
3882 }
3883
3884 g_string_prepend (str, ": ");
3885
3886 /* To Translators: 'Status' here means the state of the attendees, the resulting string will be in a form:
3887 * Status: Accepted: X Declined: Y ... */
3888 g_string_prepend (str, _("Status"));
3889
3890 res = g_string_free (str, FALSE);
3891 }
3892
3893 g_slist_free_full (attendees, e_cal_component_attendee_free);
3894
3895 return res;
3896 }
3897
3898 /**
3899 * e_cal_model_get_color_for_component
3900 */
3901 const gchar *
e_cal_model_get_color_for_component(ECalModel * model,ECalModelComponent * comp_data)3902 e_cal_model_get_color_for_component (ECalModel *model,
3903 ECalModelComponent *comp_data)
3904 {
3905 ECalModelClass *model_class;
3906 const gchar *color = NULL;
3907
3908 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3909 g_return_val_if_fail (comp_data != NULL, NULL);
3910
3911 model_class = (ECalModelClass *) G_OBJECT_GET_CLASS (model);
3912 if (model_class->get_color_for_component != NULL)
3913 color = model_class->get_color_for_component (model, comp_data);
3914
3915 if (!color)
3916 color = cal_model_get_color_for_component (model, comp_data);
3917
3918 return color;
3919 }
3920
3921 gboolean
e_cal_model_get_rgba_for_component(ECalModel * model,ECalModelComponent * comp_data,GdkRGBA * rgba)3922 e_cal_model_get_rgba_for_component (ECalModel *model,
3923 ECalModelComponent *comp_data,
3924 GdkRGBA *rgba)
3925 {
3926 const gchar *color;
3927
3928 color = e_cal_model_get_color_for_component (model, comp_data);
3929 if (!color)
3930 return FALSE;
3931
3932 return gdk_rgba_parse (rgba, color);
3933 }
3934
3935 /**
3936 * e_cal_model_get_rgb_color_for_component:
3937 *
3938 * Deprecated: 3.20: Use e_cal_model_get_rgba_for_component() instead
3939 */
3940 gboolean
e_cal_model_get_rgb_color_for_component(ECalModel * model,ECalModelComponent * comp_data,gdouble * red,gdouble * green,gdouble * blue)3941 e_cal_model_get_rgb_color_for_component (ECalModel *model,
3942 ECalModelComponent *comp_data,
3943 gdouble *red,
3944 gdouble *green,
3945 gdouble *blue)
3946 {
3947 GdkRGBA rgba;
3948
3949 if (!e_cal_model_get_rgba_for_component (model, comp_data, &rgba))
3950 return FALSE;
3951
3952 if (red)
3953 *red = rgba.red;
3954 if (green)
3955 *green = rgba.green;
3956 if (blue)
3957 *blue = rgba.blue;
3958
3959 return TRUE;
3960 }
3961
3962 /**
3963 * e_cal_model_get_component_at
3964 */
3965 ECalModelComponent *
e_cal_model_get_component_at(ECalModel * model,gint row)3966 e_cal_model_get_component_at (ECalModel *model,
3967 gint row)
3968 {
3969 ECalModelPrivate *priv;
3970
3971 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3972
3973 priv = model->priv;
3974
3975 g_return_val_if_fail (row >= 0 && row < priv->objects->len, NULL);
3976
3977 return g_ptr_array_index (priv->objects, row);
3978 }
3979
3980 ECalModelComponent *
e_cal_model_get_component_for_client_and_uid(ECalModel * model,ECalClient * client,const ECalComponentId * id)3981 e_cal_model_get_component_for_client_and_uid (ECalModel *model,
3982 ECalClient *client,
3983 const ECalComponentId *id)
3984 {
3985 ECalModelPrivate *priv;
3986
3987 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3988
3989 priv = model->priv;
3990
3991 return search_by_id_and_client (priv, client, id);
3992 }
3993
3994 /**
3995 * e_cal_model_date_value_to_string
3996 */
3997 gchar *
e_cal_model_date_value_to_string(ECalModel * model,gconstpointer value)3998 e_cal_model_date_value_to_string (ECalModel *model,
3999 gconstpointer value)
4000 {
4001 ECalModelPrivate *priv;
4002 ECellDateEditValue *dv = (ECellDateEditValue *) value;
4003 struct tm tmp_tm;
4004 gchar buffer[64];
4005
4006 g_return_val_if_fail (E_IS_CAL_MODEL (model), g_strdup (""));
4007
4008 priv = model->priv;
4009
4010 if (!dv)
4011 return g_strdup ("");
4012
4013 /* We currently convert all the dates to the current timezone. */
4014 tmp_tm = e_cal_util_icaltime_to_tm_with_zone (e_cell_date_edit_value_get_time (dv), e_cell_date_edit_value_get_zone (dv), priv->zone);
4015
4016 memset (buffer, 0, sizeof (buffer));
4017 e_time_format_date_and_time (&tmp_tm, priv->use_24_hour_format,
4018 TRUE, FALSE,
4019 buffer, sizeof (buffer));
4020 return g_strdup (buffer);
4021 }
4022
4023 typedef struct _GenerateInstacesData {
4024 ECalModelGenerateInstancesData mdata;
4025 ECalRecurInstanceCb cb;
4026 ECalClient *client;
4027 ICalTimezone *zone;
4028 } GenerateInstancesData;
4029
4030 static gboolean
ecm_generate_instances_cb(ICalComponent * comp,ICalTime * instance_start,ICalTime * instance_end,gpointer user_data,GCancellable * cancellable,GError ** error)4031 ecm_generate_instances_cb (ICalComponent *comp,
4032 ICalTime *instance_start,
4033 ICalTime *instance_end,
4034 gpointer user_data,
4035 GCancellable *cancellable,
4036 GError **error)
4037 {
4038 GenerateInstancesData *gid = user_data;
4039 ICalTime *changed_instance_start = NULL, *changed_instance_end = NULL;
4040 gboolean res;
4041
4042 g_return_val_if_fail (gid != NULL, FALSE);
4043 g_return_val_if_fail (gid->mdata.comp_data != NULL, FALSE);
4044
4045 cal_comp_get_instance_times (gid->mdata.comp_data->client, comp,
4046 gid->zone, &changed_instance_start, &changed_instance_end, cancellable);
4047
4048 res = gid->cb (comp, changed_instance_start, changed_instance_end, &gid->mdata, cancellable, error);
4049
4050 g_clear_object (&changed_instance_start);
4051 g_clear_object (&changed_instance_end);
4052
4053 return res;
4054 }
4055
4056 /**
4057 * e_cal_model_generate_instances_sync
4058 *
4059 * cb function is not called with cb_data, but with ECalModelGenerateInstancesData which contains cb_data
4060 */
4061 void
e_cal_model_generate_instances_sync(ECalModel * model,time_t start,time_t end,GCancellable * cancellable,ECalRecurInstanceCb cb,gpointer cb_data)4062 e_cal_model_generate_instances_sync (ECalModel *model,
4063 time_t start,
4064 time_t end,
4065 GCancellable *cancellable,
4066 ECalRecurInstanceCb cb,
4067 gpointer cb_data)
4068 {
4069 GenerateInstancesData gid;
4070 gint i, n;
4071
4072 g_return_if_fail (cb != NULL);
4073
4074 gid.mdata.cb_data = cb_data;
4075 gid.cb = cb;
4076 gid.zone = model->priv->zone;
4077
4078 n = e_table_model_row_count (E_TABLE_MODEL (model));
4079 for (i = 0; i < n; i++) {
4080 ECalModelComponent *comp_data = e_cal_model_get_component_at (model, i);
4081
4082 if (comp_data->instance_start < end && comp_data->instance_end > start) {
4083 gid.mdata.comp_data = comp_data;
4084
4085 e_cal_client_generate_instances_for_object_sync (comp_data->client, comp_data->icalcomp, start, end,
4086 cancellable, ecm_generate_instances_cb, &gid);
4087 }
4088 }
4089 }
4090
4091 /**
4092 * e_cal_model_get_object_array
4093 */
4094 GPtrArray *
e_cal_model_get_object_array(ECalModel * model)4095 e_cal_model_get_object_array (ECalModel *model)
4096 {
4097 g_return_val_if_fail (model != NULL, NULL);
4098 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
4099 g_return_val_if_fail (model->priv != NULL, NULL);
4100
4101 return model->priv->objects;
4102 }
4103
4104 void
e_cal_model_set_instance_times(ECalModelComponent * comp_data,const ICalTimezone * zone)4105 e_cal_model_set_instance_times (ECalModelComponent *comp_data,
4106 const ICalTimezone *zone)
4107 {
4108 ICalTime *instance_start = NULL, *instance_end = NULL;
4109
4110 if (i_cal_component_isa (comp_data->icalcomp) == I_CAL_VEVENT_COMPONENT) {
4111 ICalTime *start_time, *end_time;
4112
4113 start_time = i_cal_component_get_dtstart (comp_data->icalcomp);
4114 end_time = i_cal_component_get_dtend (comp_data->icalcomp);
4115
4116 if (i_cal_time_is_date (start_time) && i_cal_time_is_null_time (end_time)) {
4117 /* If end_time is null and it's an all day event,
4118 * just make start_time = end_time so that end_time
4119 * will be a valid date
4120 */
4121 g_clear_object (&end_time);
4122 end_time = i_cal_time_clone (start_time);
4123 i_cal_time_adjust (end_time, 1, 0, 0, 0);
4124 i_cal_component_set_dtend (comp_data->icalcomp, end_time);
4125 } else if (i_cal_time_is_date (start_time) && i_cal_time_is_date (end_time) &&
4126 (i_cal_time_compare_date_only (start_time, end_time) == 0)) {
4127 /* If both DTSTART and DTEND are DATE values, and they are the
4128 * same day, we add 1 day to DTEND. This means that most
4129 * events created with the old Evolution behavior will still
4130 * work OK. */
4131 i_cal_time_adjust (end_time, 1, 0, 0, 0);
4132 i_cal_component_set_dtend (comp_data->icalcomp, end_time);
4133 }
4134
4135 g_clear_object (&start_time);
4136 g_clear_object (&end_time);
4137 }
4138
4139 cal_comp_get_instance_times (comp_data->client, comp_data->icalcomp, zone,
4140 &instance_start, &instance_end, NULL);
4141
4142 comp_data->instance_start = instance_start ? i_cal_time_as_timet_with_zone (instance_start,
4143 i_cal_time_get_timezone (instance_start)) : comp_data->instance_start;
4144 comp_data->instance_end = instance_end ? i_cal_time_as_timet_with_zone (instance_end,
4145 i_cal_time_get_timezone (instance_end)) : comp_data->instance_end;
4146
4147 g_clear_object (&instance_start);
4148 g_clear_object (&instance_end);
4149 }
4150
4151 /**
4152 * e_cal_model_set_default_time_func:
4153 * This function will be used when creating new item from the "click-to-add",
4154 * when user didn't fill a start date there.
4155 **/
4156 void
e_cal_model_set_default_time_func(ECalModel * model,ECalModelDefaultTimeFunc func,gpointer user_data)4157 e_cal_model_set_default_time_func (ECalModel *model,
4158 ECalModelDefaultTimeFunc func,
4159 gpointer user_data)
4160 {
4161 g_return_if_fail (E_IS_CAL_MODEL (model));
4162
4163 model->priv->get_default_time = func;
4164 model->priv->get_default_time_user_data = user_data;
4165 }
4166
4167 void
e_cal_model_modify_component(ECalModel * model,ECalModelComponent * comp_data,ECalObjModType mod)4168 e_cal_model_modify_component (ECalModel *model,
4169 ECalModelComponent *comp_data,
4170 ECalObjModType mod)
4171 {
4172 g_return_if_fail (E_IS_CAL_MODEL (model));
4173 g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data));
4174
4175 e_cal_ops_modify_component (model, comp_data->client, comp_data->icalcomp, mod, E_CAL_OPS_SEND_FLAG_ASK);
4176 }
4177
4178 void
e_cal_model_util_set_value(GHashTable * values,ETableModel * table_model,gint column,gint row)4179 e_cal_model_util_set_value (GHashTable *values,
4180 ETableModel *table_model,
4181 gint column,
4182 gint row)
4183 {
4184 gpointer value;
4185
4186 g_return_if_fail (values != NULL);
4187
4188 value = e_table_model_value_at (table_model, column, row);
4189
4190 g_hash_table_insert (values, GINT_TO_POINTER (column),
4191 e_table_model_duplicate_value (table_model, column, value));
4192 }
4193
4194 gpointer
e_cal_model_util_get_value(GHashTable * values,gint column)4195 e_cal_model_util_get_value (GHashTable *values,
4196 gint column)
4197 {
4198 g_return_val_if_fail (values != NULL, NULL);
4199
4200 return g_hash_table_lookup (values, GINT_TO_POINTER (column));
4201 }
4202
4203 void
e_cal_model_emit_object_created(ECalModel * model,ECalClient * where)4204 e_cal_model_emit_object_created (ECalModel *model,
4205 ECalClient *where)
4206 {
4207 g_return_if_fail (E_IS_CAL_MODEL (model));
4208 g_return_if_fail (E_IS_CAL_CLIENT (where));
4209
4210 g_signal_emit (model, signals[OBJECT_CREATED], 0, where);
4211 }
4212
4213 gpointer
e_cal_model_util_get_status(ECalModelComponent * comp_data)4214 e_cal_model_util_get_status (ECalModelComponent *comp_data)
4215 {
4216 ICalProperty *prop;
4217 const gchar *res = "";
4218
4219 g_return_val_if_fail (comp_data != NULL, (gpointer) "");
4220
4221 prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_STATUS_PROPERTY);
4222 if (prop) {
4223 ICalPropertyStatus status;
4224
4225 status = i_cal_property_get_status (prop);
4226
4227 g_object_unref (prop);
4228
4229 res = cal_comp_util_status_to_localized_string (i_cal_component_isa (comp_data->icalcomp), status);
4230 if (!res)
4231 res = "";
4232 }
4233
4234 return (gpointer) res;
4235 }
4236
4237 ICalPropertyStatus
e_cal_model_util_set_status(ECalModelComponent * comp_data,gconstpointer value)4238 e_cal_model_util_set_status (ECalModelComponent *comp_data,
4239 gconstpointer value)
4240 {
4241 ICalProperty *prop;
4242 ICalPropertyStatus status;
4243 const gchar *str_value = value;
4244
4245 g_return_val_if_fail (comp_data != NULL, I_CAL_STATUS_NONE);
4246
4247 prop = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_STATUS_PROPERTY);
4248
4249 if (!str_value || !*str_value) {
4250 if (prop) {
4251 i_cal_component_remove_property (comp_data->icalcomp, prop);
4252 g_object_unref (prop);
4253 }
4254
4255 return I_CAL_STATUS_NONE;
4256 }
4257
4258 status = cal_comp_util_localized_string_to_status (i_cal_component_isa (comp_data->icalcomp), str_value, NULL, NULL);
4259
4260 if (status == I_CAL_STATUS_NONE) {
4261 if (prop) {
4262 i_cal_component_remove_property (comp_data->icalcomp, prop);
4263 g_object_unref (prop);
4264 }
4265 } else if (prop) {
4266 i_cal_property_set_status (prop, status);
4267 g_object_unref (prop);
4268 } else {
4269 prop = i_cal_property_new_status (status);
4270 i_cal_component_take_property (comp_data->icalcomp, prop);
4271 }
4272
4273 return status;
4274 }
4275
4276 static const gchar *
get_cmp_cache_str(gpointer cmp_cache,const gchar * str)4277 get_cmp_cache_str (gpointer cmp_cache,
4278 const gchar *str)
4279 {
4280 const gchar *value;
4281
4282 if (!cmp_cache || !str)
4283 return str;
4284
4285 value = e_table_sorting_utils_lookup_cmp_cache (cmp_cache, str);
4286 if (!value) {
4287 gchar *ckey;
4288
4289 ckey = g_utf8_collate_key (str, -1);
4290 e_table_sorting_utils_add_to_cmp_cache (cmp_cache, (gchar *) str, ckey);
4291 value = ckey;
4292 }
4293
4294 return value;
4295 }
4296
4297 static gint
cmp_cache_strings(gconstpointer str_a,gconstpointer str_b,gpointer cmp_cache)4298 cmp_cache_strings (gconstpointer str_a,
4299 gconstpointer str_b,
4300 gpointer cmp_cache)
4301 {
4302 if (!cmp_cache)
4303 return g_utf8_collate (str_a, str_b);
4304
4305 str_b = get_cmp_cache_str (cmp_cache, str_b);
4306
4307 g_return_val_if_fail (str_a != NULL, 0);
4308 g_return_val_if_fail (str_b != NULL, 0);
4309
4310 return g_strcmp0 (str_a, str_b);
4311 }
4312
4313 gint
e_cal_model_util_status_compare_cb(gconstpointer a,gconstpointer b,gpointer cmp_cache)4314 e_cal_model_util_status_compare_cb (gconstpointer a,
4315 gconstpointer b,
4316 gpointer cmp_cache)
4317 {
4318 const gchar *string_a = a;
4319 const gchar *string_b = b;
4320 gint status_a = -2;
4321 gint status_b = -2;
4322
4323 if (!string_a || !*string_a) {
4324 status_a = -1;
4325 } else {
4326 const gchar *cache_str = get_cmp_cache_str (cmp_cache, string_a);
4327
4328 status_a = cal_comp_util_localized_string_to_status (I_CAL_ANY_COMPONENT, cache_str, cmp_cache_strings, cmp_cache);
4329
4330 if (status_a == I_CAL_STATUS_NONE)
4331 status_a = -1;
4332 }
4333
4334 if (string_b == NULL || *string_b == '\0')
4335 status_b = -1;
4336 else {
4337 const gchar *cache_str = get_cmp_cache_str (cmp_cache, string_b);
4338
4339 status_b = cal_comp_util_localized_string_to_status (I_CAL_ANY_COMPONENT, cache_str, cmp_cache_strings, cmp_cache);
4340
4341 if (status_b == I_CAL_STATUS_NONE)
4342 status_b = -1;
4343 }
4344
4345 return status_a - status_b;
4346 }
4347
4348 ECellDateEditValue *
e_cal_model_util_get_datetime_value(ECalModel * model,ECalModelComponent * comp_data,ICalPropertyKind kind,ICalTime * (* get_time_func)(ICalProperty * prop))4349 e_cal_model_util_get_datetime_value (ECalModel *model,
4350 ECalModelComponent *comp_data,
4351 ICalPropertyKind kind,
4352 ICalTime * (*get_time_func) (ICalProperty *prop))
4353 {
4354 ECellDateEditValue *value;
4355 ICalProperty *prop;
4356 ICalParameter *param = NULL;
4357 ICalTimezone *zone = NULL;
4358 ICalTime *tt;
4359 const gchar *tzid;
4360 gboolean is_date;
4361
4362 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
4363 g_return_val_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data), NULL);
4364 g_return_val_if_fail (get_time_func != NULL, NULL);
4365
4366 prop = i_cal_component_get_first_property (comp_data->icalcomp, kind);
4367 if (!prop)
4368 return NULL;
4369
4370 tt = get_time_func (prop);
4371
4372 if (!tt || !i_cal_time_is_valid_time (tt) || i_cal_time_is_null_time (tt)) {
4373 g_clear_object (&prop);
4374 g_clear_object (&tt);
4375
4376 return NULL;
4377 }
4378
4379 is_date = i_cal_time_is_date (tt);
4380
4381 if (!is_date) {
4382 param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
4383 tzid = param ? i_cal_parameter_get_tzid (param) : NULL;
4384
4385 if (!tzid || !*tzid ||
4386 !e_cal_client_get_timezone_sync (comp_data->client, tzid, &zone, NULL, NULL))
4387 zone = NULL;
4388 }
4389
4390 if (e_cal_data_model_get_expand_recurrences (model->priv->data_model)) {
4391 gboolean is_date = i_cal_time_is_date (tt);
4392 time_t instance_tt = (time_t) 0;
4393
4394 if (kind == I_CAL_DTSTART_PROPERTY)
4395 instance_tt = comp_data->instance_start;
4396 else if (kind == I_CAL_DTEND_PROPERTY)
4397 instance_tt = comp_data->instance_end;
4398 else
4399 g_warn_if_reached ();
4400
4401 if (zone) {
4402 g_clear_object (&tt);
4403 tt = i_cal_time_new_from_timet_with_zone (instance_tt, is_date, zone);
4404 } else if (model->priv->zone) {
4405 g_clear_object (&tt);
4406 tt = i_cal_time_new_from_timet_with_zone (instance_tt, is_date, model->priv->zone);
4407 }
4408
4409 if (kind == I_CAL_DTEND_PROPERTY && is_date) {
4410 ICalProperty *dtstart;
4411
4412 dtstart = i_cal_component_get_first_property (comp_data->icalcomp, I_CAL_DTSTART_PROPERTY);
4413
4414 if (dtstart) {
4415 ICalTime *tt_start;
4416 ICalTimezone *start_zone = NULL;
4417
4418 tt_start = i_cal_property_get_dtstart (dtstart);
4419
4420 g_clear_object (¶m);
4421
4422 if (!i_cal_time_is_date (tt_start)) {
4423 param = i_cal_property_get_first_parameter (dtstart, I_CAL_TZID_PARAMETER);
4424 tzid = param ? i_cal_parameter_get_tzid (param) : NULL;
4425
4426 if (!tzid || !*tzid ||
4427 !e_cal_client_get_timezone_sync (comp_data->client, tzid, &start_zone, NULL, NULL))
4428 start_zone = NULL;
4429 }
4430
4431 if (start_zone) {
4432 g_clear_object (&tt_start);
4433 tt_start = i_cal_time_new_from_timet_with_zone (comp_data->instance_start, is_date, start_zone);
4434 } else {
4435 g_clear_object (&tt_start);
4436 tt_start = i_cal_time_new_from_timet_with_zone (comp_data->instance_start, is_date, model->priv->zone);
4437 }
4438
4439 i_cal_time_adjust (tt_start, 1, 0, 0, 0);
4440
4441 /* Decrease by a day only if the DTSTART will still be before, or the same as, DTEND */
4442 if (i_cal_time_compare (tt_start, tt) <= 0)
4443 i_cal_time_adjust (tt, -1, 0, 0, 0);
4444
4445 g_clear_object (&tt_start);
4446 g_clear_object (&dtstart);
4447 g_clear_object (¶m);
4448 }
4449 }
4450 }
4451
4452 value = e_cell_date_edit_value_new_take (tt, zone ? e_cal_util_copy_timezone (zone) : NULL);
4453
4454 g_clear_object (&prop);
4455 g_clear_object (¶m);
4456
4457 return value;
4458 }
4459
4460 /* Removes unneeded characters from the 'value'.
4461 It modifies the 'value' inline. */
4462 void
e_cal_model_until_sanitize_text_value(gchar * value,gint value_length)4463 e_cal_model_until_sanitize_text_value (gchar *value,
4464 gint value_length)
4465 {
4466 if (value && (value_length > 0 || value_length == -1) && *value) {
4467 gchar *ptr, *pos;
4468
4469 for (ptr = value, pos = value; (value_length > 0 || value_length == -1) && *ptr; ptr++, pos++) {
4470 if (*ptr == '\r')
4471 pos--;
4472 else if (*ptr == '\n' || *ptr == '\t')
4473 *pos = ' ';
4474 else if (pos != ptr)
4475 *pos = *ptr;
4476
4477 if (value_length != -1)
4478 value_length--;
4479 }
4480
4481 if (pos < ptr)
4482 *pos = '\0';
4483 }
4484 }
4485