Update Romanian translation
[evolution.git] / src / calendar / gui / e-cal-model.c
blob7706d2255d4c954754d87b769667011aa68f2611
1 /*
2 * Evolution calendar - Data model for ETable
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.
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.
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/>.
17 * Authors:
18 * Rodrigo Moya <rodrigo@ximian.com>
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
24 #include "evolution-config.h"
26 #include <string.h>
27 #include <glib/gi18n.h>
29 #include <libebackend/libebackend.h>
31 #include <e-util/e-util.h>
32 #include <e-util/e-util-enumtypes.h>
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"
41 #include "e-cal-model.h"
43 struct _ECalModelComponentPrivate {
44 GString *categories_str;
47 #define E_CAL_MODEL_GET_PRIVATE(obj) \
48 (G_TYPE_INSTANCE_GET_PRIVATE \
49 ((obj), E_TYPE_CAL_MODEL, ECalModelPrivate))
51 #define E_CAL_MODEL_COMPONENT_GET_PRIVATE(obj) \
52 (G_TYPE_INSTANCE_GET_PRIVATE \
53 ((obj), E_TYPE_CAL_MODEL_COMPONENT, ECalModelComponentPrivate))
55 struct _ECalModelPrivate {
56 ECalDataModel *data_model;
57 ESourceRegistry *registry;
58 EShell *shell;
59 EClientCache *client_cache;
61 /* The default source uid of an ECalClient */
62 gchar *default_source_uid;
64 /* Array for storing the objects. Each element is of type ECalModelComponent */
65 GPtrArray *objects;
67 icalcomponent_kind kind;
68 icaltimezone *zone;
70 /* The time range to display */
71 time_t start;
72 time_t end;
74 /* The search regular expression */
75 gchar *search_sexp;
77 /* The default category */
78 gchar *default_category;
80 /* Whether we display dates in 24-hour format. */
81 gboolean use_24_hour_format;
83 /* Whether to compress weekends into one cell. */
84 gboolean compress_weekend;
86 /* First day of the week */
87 GDateWeekday week_start_day;
89 /* Work days. Indices are based on GDateWeekday.
90 * The first element (G_DATE_BAD_WEEKDAY) is unused. */
91 gboolean work_days[G_DATE_SUNDAY + 1];
93 /* Work day timespan */
94 gint work_day_start_hour;
95 gint work_day_start_minute;
96 gint work_day_end_hour;
97 gint work_day_end_minute;
98 gint work_day_start_mon;
99 gint work_day_end_mon;
100 gint work_day_start_tue;
101 gint work_day_end_tue;
102 gint work_day_start_wed;
103 gint work_day_end_wed;
104 gint work_day_start_thu;
105 gint work_day_end_thu;
106 gint work_day_start_fri;
107 gint work_day_end_fri;
108 gint work_day_start_sat;
109 gint work_day_end_sat;
110 gint work_day_start_sun;
111 gint work_day_end_sun;
113 /* callback, to retrieve start time for newly added rows by click-to-add */
114 ECalModelDefaultTimeFunc get_default_time;
115 gpointer get_default_time_user_data;
117 /* Default reminder for events */
118 gboolean use_default_reminder;
119 gint default_reminder_interval;
120 EDurationType default_reminder_units;
122 /* Ask user to confirm before deleting components. */
123 gboolean confirm_delete;
126 typedef struct {
127 const gchar *color;
128 GList *uids;
129 } AssignedColorData;
131 static const gchar *cal_model_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data);
133 enum {
134 PROP_0,
135 PROP_CLIENT_CACHE,
136 PROP_COMPRESS_WEEKEND,
137 PROP_CONFIRM_DELETE,
138 PROP_DATA_MODEL,
139 PROP_DEFAULT_REMINDER_INTERVAL,
140 PROP_DEFAULT_REMINDER_UNITS,
141 PROP_DEFAULT_SOURCE_UID,
142 PROP_REGISTRY,
143 PROP_SHELL,
144 PROP_TIMEZONE,
145 PROP_USE_24_HOUR_FORMAT,
146 PROP_USE_DEFAULT_REMINDER,
147 PROP_WEEK_START_DAY,
148 PROP_WORK_DAY_MONDAY,
149 PROP_WORK_DAY_TUESDAY,
150 PROP_WORK_DAY_WEDNESDAY,
151 PROP_WORK_DAY_THURSDAY,
152 PROP_WORK_DAY_FRIDAY,
153 PROP_WORK_DAY_SATURDAY,
154 PROP_WORK_DAY_SUNDAY,
155 PROP_WORK_DAY_END_HOUR,
156 PROP_WORK_DAY_END_MINUTE,
157 PROP_WORK_DAY_START_HOUR,
158 PROP_WORK_DAY_START_MINUTE,
159 PROP_WORK_DAY_START_MON,
160 PROP_WORK_DAY_END_MON,
161 PROP_WORK_DAY_START_TUE,
162 PROP_WORK_DAY_END_TUE,
163 PROP_WORK_DAY_START_WED,
164 PROP_WORK_DAY_END_WED,
165 PROP_WORK_DAY_START_THU,
166 PROP_WORK_DAY_END_THU,
167 PROP_WORK_DAY_START_FRI,
168 PROP_WORK_DAY_END_FRI,
169 PROP_WORK_DAY_START_SAT,
170 PROP_WORK_DAY_END_SAT,
171 PROP_WORK_DAY_START_SUN,
172 PROP_WORK_DAY_END_SUN
175 enum {
176 TIME_RANGE_CHANGED,
177 ROW_APPENDED,
178 COMPS_DELETED,
179 TIMEZONE_CHANGED,
180 OBJECT_CREATED,
181 LAST_SIGNAL
184 /* Forward Declarations */
185 static void e_cal_model_table_model_init (ETableModelInterface *iface);
186 static void e_cal_model_cal_data_model_subscriber_init (ECalDataModelSubscriberInterface *iface);
188 static guint signals[LAST_SIGNAL];
190 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ECalModel, e_cal_model, G_TYPE_OBJECT,
191 G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)
192 G_IMPLEMENT_INTERFACE (E_TYPE_TABLE_MODEL, e_cal_model_table_model_init)
193 G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER, e_cal_model_cal_data_model_subscriber_init))
195 G_DEFINE_TYPE (ECalModelComponent, e_cal_model_component, G_TYPE_OBJECT)
197 static void
198 e_cal_model_component_set_icalcomponent (ECalModelComponent *comp_data,
199 ECalModel *model,
200 icalcomponent *icalcomp)
202 if (model != NULL)
203 g_return_if_fail (E_IS_CAL_MODEL (model));
204 g_return_if_fail (comp_data != NULL);
206 #define free_ptr(x) { \
207 if (x) { \
208 g_free (x); \
209 x = NULL; \
213 if (comp_data->icalcomp)
214 icalcomponent_free (comp_data->icalcomp);
215 comp_data->icalcomp = icalcomp;
217 if (comp_data->priv->categories_str)
218 g_string_free (comp_data->priv->categories_str, TRUE);
219 comp_data->priv->categories_str = NULL;
221 free_ptr (comp_data->dtstart);
222 free_ptr (comp_data->dtend);
223 free_ptr (comp_data->due);
224 free_ptr (comp_data->completed);
225 free_ptr (comp_data->created);
226 free_ptr (comp_data->lastmodified);
227 free_ptr (comp_data->color);
229 #undef free_ptr
231 if (comp_data->icalcomp && model)
232 e_cal_model_set_instance_times (comp_data, model->priv->zone);
235 static void
236 e_cal_model_component_finalize (GObject *object)
238 ECalModelComponent *comp_data = E_CAL_MODEL_COMPONENT (object);
240 if (comp_data->client) {
241 g_object_unref (comp_data->client);
242 comp_data->client = NULL;
245 e_cal_model_component_set_icalcomponent (comp_data, NULL, NULL);
247 /* Chain up to parent's finalize() method. */
248 G_OBJECT_CLASS (e_cal_model_component_parent_class)->finalize (object);
251 /* Class initialization function for the calendar component object */
252 static void
253 e_cal_model_component_class_init (ECalModelComponentClass *class)
255 GObjectClass *object_class;
257 object_class = (GObjectClass *) class;
258 g_type_class_add_private (class, sizeof (ECalModelComponentPrivate));
260 object_class->finalize = e_cal_model_component_finalize;
263 static void
264 e_cal_model_component_init (ECalModelComponent *comp)
266 comp->priv = E_CAL_MODEL_COMPONENT_GET_PRIVATE (comp);
267 comp->is_new_component = FALSE;
270 static gpointer
271 get_categories (ECalModelComponent *comp_data)
273 if (!comp_data->priv->categories_str) {
274 icalproperty *prop;
276 comp_data->priv->categories_str = g_string_new ("");
278 for (prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CATEGORIES_PROPERTY);
279 prop;
280 prop = icalcomponent_get_next_property (comp_data->icalcomp, ICAL_CATEGORIES_PROPERTY)) {
281 const gchar *categories = icalproperty_get_categories (prop);
282 if (!categories)
283 continue;
285 if (comp_data->priv->categories_str->len)
286 g_string_append_c (comp_data->priv->categories_str, ',');
287 g_string_append (comp_data->priv->categories_str, categories);
291 return g_strdup (comp_data->priv->categories_str->str);
294 static gchar *
295 get_classification (ECalModelComponent *comp_data)
297 icalproperty *prop;
298 icalproperty_class class;
300 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CLASS_PROPERTY);
302 if (!prop)
303 return _("Public");
305 class = icalproperty_get_class (prop);
307 switch (class)
309 case ICAL_CLASS_PUBLIC:
310 return _("Public");
311 case ICAL_CLASS_PRIVATE:
312 return _("Private");
313 case ICAL_CLASS_CONFIDENTIAL:
314 return _("Confidential");
315 default:
316 return _("Unknown");
320 static const gchar *
321 get_color (ECalModel *model,
322 ECalModelComponent *comp_data)
324 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
326 return e_cal_model_get_color_for_component (model, comp_data);
329 static gpointer
330 get_description (ECalModelComponent *comp_data)
332 icalproperty *prop;
334 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DESCRIPTION_PROPERTY);
335 if (prop) {
336 GString *str = g_string_new (NULL);
337 do {
338 str = g_string_append (str, icalproperty_get_description (prop));
339 } while ((prop = icalcomponent_get_next_property (comp_data->icalcomp, ICAL_DESCRIPTION_PROPERTY)));
341 return g_string_free (str, FALSE);
344 return g_strdup ("");
347 static ECellDateEditValue *
348 get_dtstart (ECalModel *model,
349 ECalModelComponent *comp_data)
351 ECalModelPrivate *priv;
352 struct icaltimetype tt_start;
354 priv = model->priv;
356 if (!comp_data->dtstart) {
357 icalproperty *prop;
358 icaltimezone *zone;
359 gboolean got_zone = FALSE;
361 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DTSTART_PROPERTY);
362 if (!prop)
363 return NULL;
365 tt_start = icalproperty_get_dtstart (prop);
367 if (icaltime_get_tzid (tt_start)
368 && e_cal_client_get_timezone_sync (comp_data->client, icaltime_get_tzid (tt_start), &zone, NULL, NULL))
369 got_zone = TRUE;
371 if (e_cal_data_model_get_expand_recurrences (priv->data_model)) {
372 if (got_zone)
373 tt_start = icaltime_from_timet_with_zone (comp_data->instance_start, tt_start.is_date, zone);
374 else if (priv->zone)
375 tt_start = icaltime_from_timet_with_zone (comp_data->instance_start, tt_start.is_date, priv->zone);
378 if (!icaltime_is_valid_time (tt_start) || icaltime_is_null_time (tt_start))
379 return NULL;
381 comp_data->dtstart = g_new0 (ECellDateEditValue, 1);
382 comp_data->dtstart->tt = tt_start;
384 if (got_zone)
385 comp_data->dtstart->zone = zone;
386 else
387 comp_data->dtstart->zone = NULL;
390 return e_cal_model_copy_cell_date_value (comp_data->dtstart);
393 static ECellDateEditValue *
394 get_datetime_from_utc (ECalModel *model,
395 ECalModelComponent *comp_data,
396 icalproperty_kind propkind,
397 struct icaltimetype (*get_value) (const icalproperty *prop),
398 ECellDateEditValue **buffer)
400 g_return_val_if_fail (buffer != NULL, NULL);
402 if (!*buffer) {
403 ECalModelPrivate *priv;
404 struct icaltimetype tt_value;
405 icalproperty *prop;
406 ECellDateEditValue *res;
408 priv = model->priv;
410 prop = icalcomponent_get_first_property (comp_data->icalcomp, propkind);
411 if (!prop)
412 return NULL;
414 tt_value = get_value (prop);
416 /* these are always in UTC, thus convert to default zone, if any and done */
417 if (priv->zone)
418 icaltimezone_convert_time (&tt_value, icaltimezone_get_utc_timezone (), priv->zone);
420 if (!icaltime_is_valid_time (tt_value) || icaltime_is_null_time (tt_value))
421 return NULL;
423 res = g_new0 (ECellDateEditValue, 1);
424 res->tt = tt_value;
425 res->zone = NULL;
427 *buffer = res;
430 return e_cal_model_copy_cell_date_value (*buffer);
433 static gpointer
434 get_summary (ECalModelComponent *comp_data)
436 icalproperty *prop;
438 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_SUMMARY_PROPERTY);
439 if (prop)
440 return g_strdup (icalproperty_get_summary (prop));
442 return g_strdup ("");
445 static gchar *
446 get_uid (ECalModelComponent *comp_data)
448 return (gchar *) icalcomponent_get_uid (comp_data->icalcomp);
451 static gchar *
452 get_source_description (ESourceRegistry *registry,
453 ECalModelComponent *comp_data)
455 if (!registry || !comp_data || !comp_data->client)
456 return NULL;
458 return e_util_get_source_full_name (registry, e_client_get_source (E_CLIENT (comp_data->client)));
461 static void
462 set_categories (ECalModelComponent *comp_data,
463 const gchar *value)
465 icalproperty *prop;
467 /* remove all categories first */
468 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CATEGORIES_PROPERTY);
469 while (prop) {
470 icalproperty *to_remove = prop;
471 prop = icalcomponent_get_next_property (comp_data->icalcomp, ICAL_CATEGORIES_PROPERTY);
473 icalcomponent_remove_property (comp_data->icalcomp, to_remove);
474 icalproperty_free (to_remove);
477 if (comp_data->priv->categories_str)
478 g_string_free (comp_data->priv->categories_str, TRUE);
479 comp_data->priv->categories_str = NULL;
481 /* then set a new value; no need to populate categories_str,
482 * it'll be populated on demand (in the get_categories() function)
484 if (value && *value) {
485 prop = icalproperty_new_categories (value);
486 icalcomponent_add_property (comp_data->icalcomp, prop);
490 static void
491 set_classification (ECalModelComponent *comp_data,
492 const gchar *value)
494 icalproperty *prop;
496 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CLASS_PROPERTY);
497 if (!value || !(*value)) {
498 if (prop) {
499 icalcomponent_remove_property (comp_data->icalcomp, prop);
500 icalproperty_free (prop);
502 } else {
503 icalproperty_class ical_class;
505 if (!g_ascii_strcasecmp (value, "PUBLIC"))
506 ical_class = ICAL_CLASS_PUBLIC;
507 else if (!g_ascii_strcasecmp (value, "PRIVATE"))
508 ical_class = ICAL_CLASS_PRIVATE;
509 else if (!g_ascii_strcasecmp (value, "CONFIDENTIAL"))
510 ical_class = ICAL_CLASS_CONFIDENTIAL;
511 else
512 ical_class = ICAL_CLASS_NONE;
514 if (!prop) {
515 prop = icalproperty_new_class (ical_class);
516 icalcomponent_add_property (comp_data->icalcomp, prop);
517 } else
518 icalproperty_set_class (prop, ical_class);
522 static void
523 set_description (ECalModelComponent *comp_data,
524 const gchar *value)
526 icalproperty *prop;
528 /* remove old description(s) */
529 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DESCRIPTION_PROPERTY);
530 while (prop) {
531 icalproperty *next;
533 next = icalcomponent_get_next_property (comp_data->icalcomp, ICAL_DESCRIPTION_PROPERTY);
535 icalcomponent_remove_property (comp_data->icalcomp, prop);
536 icalproperty_free (prop);
538 prop = next;
541 /* now add the new description */
542 if (!value || !(*value))
543 return;
545 prop = icalproperty_new_description (value);
546 icalcomponent_add_property (comp_data->icalcomp, prop);
549 static void
550 set_dtstart (ECalModel *model,
551 ECalModelComponent *comp_data,
552 gconstpointer value)
554 e_cal_model_update_comp_time (
555 model, comp_data, value,
556 ICAL_DTSTART_PROPERTY,
557 icalproperty_set_dtstart,
558 icalproperty_new_dtstart);
561 static void
562 set_summary (ECalModelComponent *comp_data,
563 const gchar *value)
565 icalproperty *prop;
567 prop = icalcomponent_get_first_property (
568 comp_data->icalcomp, ICAL_SUMMARY_PROPERTY);
570 if (string_is_empty (value)) {
571 if (prop) {
572 icalcomponent_remove_property (comp_data->icalcomp, prop);
573 icalproperty_free (prop);
575 } else {
576 if (prop)
577 icalproperty_set_summary (prop, value);
578 else {
579 prop = icalproperty_new_summary (value);
580 icalcomponent_add_property (comp_data->icalcomp, prop);
585 static void
586 datetime_to_zone (ECalClient *client,
587 struct icaltimetype *tt,
588 icaltimezone *tt_zone,
589 const gchar *tzid)
591 icaltimezone *from, *to;
592 const gchar *tt_tzid = NULL;
594 g_return_if_fail (tt != NULL);
596 if (tt_zone)
597 tt_tzid = icaltimezone_get_tzid (tt_zone);
599 if (tt_tzid == NULL || tzid == NULL ||
600 tt_tzid == tzid || g_str_equal (tt_tzid, tzid))
601 return;
603 from = tt_zone;
604 to = icaltimezone_get_builtin_timezone_from_tzid (tzid);
605 if (!to) {
606 /* do not check failure here, maybe the zone is not available there */
607 e_cal_client_get_timezone_sync (client, tzid, &to, NULL, NULL);
610 icaltimezone_convert_time (tt, from, to);
613 static void
614 cal_model_set_data_model (ECalModel *model,
615 ECalDataModel *data_model)
617 g_return_if_fail (E_IS_CAL_DATA_MODEL (data_model));
618 g_return_if_fail (model->priv->data_model == NULL);
620 /* Be aware of a circular dependency, once this @model is subscribed to
621 the @data_model, then the @data_model increases reference count
622 of the @model.
624 model->priv->data_model = g_object_ref (data_model);
627 static void
628 cal_model_set_registry (ECalModel *model,
629 ESourceRegistry *registry)
631 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
632 g_return_if_fail (model->priv->registry == NULL);
634 model->priv->registry = g_object_ref (registry);
637 static void
638 cal_model_set_shell (ECalModel *model,
639 EShell *shell)
641 EClientCache *client_cache;
643 g_return_if_fail (E_IS_SHELL (shell));
644 g_return_if_fail (model->priv->shell == NULL);
646 model->priv->shell = g_object_ref (shell);
648 client_cache = e_shell_get_client_cache (shell);
650 g_return_if_fail (E_IS_CLIENT_CACHE (client_cache));
651 g_return_if_fail (model->priv->client_cache == NULL);
653 model->priv->client_cache = g_object_ref (client_cache);
656 static void
657 cal_model_set_property (GObject *object,
658 guint property_id,
659 const GValue *value,
660 GParamSpec *pspec)
662 switch (property_id) {
663 case PROP_COMPRESS_WEEKEND:
664 e_cal_model_set_compress_weekend (
665 E_CAL_MODEL (object),
666 g_value_get_boolean (value));
667 return;
669 case PROP_CONFIRM_DELETE:
670 e_cal_model_set_confirm_delete (
671 E_CAL_MODEL (object),
672 g_value_get_boolean (value));
673 return;
675 case PROP_DATA_MODEL:
676 cal_model_set_data_model (
677 E_CAL_MODEL (object),
678 g_value_get_object (value));
679 return;
681 case PROP_DEFAULT_SOURCE_UID:
682 e_cal_model_set_default_source_uid (
683 E_CAL_MODEL (object),
684 g_value_get_string (value));
685 return;
687 case PROP_DEFAULT_REMINDER_INTERVAL:
688 e_cal_model_set_default_reminder_interval (
689 E_CAL_MODEL (object),
690 g_value_get_int (value));
691 return;
693 case PROP_DEFAULT_REMINDER_UNITS:
694 e_cal_model_set_default_reminder_units (
695 E_CAL_MODEL (object),
696 g_value_get_enum (value));
697 return;
699 case PROP_REGISTRY:
700 cal_model_set_registry (
701 E_CAL_MODEL (object),
702 g_value_get_object (value));
703 return;
705 case PROP_SHELL:
706 cal_model_set_shell (
707 E_CAL_MODEL (object),
708 g_value_get_object (value));
709 return;
711 case PROP_TIMEZONE:
712 e_cal_model_set_timezone (
713 E_CAL_MODEL (object),
714 g_value_get_pointer (value));
715 return;
717 case PROP_USE_24_HOUR_FORMAT:
718 e_cal_model_set_use_24_hour_format (
719 E_CAL_MODEL (object),
720 g_value_get_boolean (value));
721 return;
723 case PROP_USE_DEFAULT_REMINDER:
724 e_cal_model_set_use_default_reminder (
725 E_CAL_MODEL (object),
726 g_value_get_boolean (value));
727 return;
729 case PROP_WEEK_START_DAY:
730 e_cal_model_set_week_start_day (
731 E_CAL_MODEL (object),
732 g_value_get_enum (value));
733 return;
735 case PROP_WORK_DAY_MONDAY:
736 e_cal_model_set_work_day (
737 E_CAL_MODEL (object),
738 G_DATE_MONDAY,
739 g_value_get_boolean (value));
740 return;
742 case PROP_WORK_DAY_TUESDAY:
743 e_cal_model_set_work_day (
744 E_CAL_MODEL (object),
745 G_DATE_TUESDAY,
746 g_value_get_boolean (value));
747 return;
749 case PROP_WORK_DAY_WEDNESDAY:
750 e_cal_model_set_work_day (
751 E_CAL_MODEL (object),
752 G_DATE_WEDNESDAY,
753 g_value_get_boolean (value));
754 return;
756 case PROP_WORK_DAY_THURSDAY:
757 e_cal_model_set_work_day (
758 E_CAL_MODEL (object),
759 G_DATE_THURSDAY,
760 g_value_get_boolean (value));
761 return;
763 case PROP_WORK_DAY_FRIDAY:
764 e_cal_model_set_work_day (
765 E_CAL_MODEL (object),
766 G_DATE_FRIDAY,
767 g_value_get_boolean (value));
768 return;
770 case PROP_WORK_DAY_SATURDAY:
771 e_cal_model_set_work_day (
772 E_CAL_MODEL (object),
773 G_DATE_SATURDAY,
774 g_value_get_boolean (value));
775 return;
777 case PROP_WORK_DAY_SUNDAY:
778 e_cal_model_set_work_day (
779 E_CAL_MODEL (object),
780 G_DATE_SUNDAY,
781 g_value_get_boolean (value));
782 return;
784 case PROP_WORK_DAY_END_HOUR:
785 e_cal_model_set_work_day_end_hour (
786 E_CAL_MODEL (object),
787 g_value_get_int (value));
788 return;
790 case PROP_WORK_DAY_END_MINUTE:
791 e_cal_model_set_work_day_end_minute (
792 E_CAL_MODEL (object),
793 g_value_get_int (value));
794 return;
796 case PROP_WORK_DAY_START_HOUR:
797 e_cal_model_set_work_day_start_hour (
798 E_CAL_MODEL (object),
799 g_value_get_int (value));
800 return;
802 case PROP_WORK_DAY_START_MINUTE:
803 e_cal_model_set_work_day_start_minute (
804 E_CAL_MODEL (object),
805 g_value_get_int (value));
806 return;
808 case PROP_WORK_DAY_START_MON:
809 e_cal_model_set_work_day_start_mon (
810 E_CAL_MODEL (object),
811 g_value_get_int (value));
812 return;
814 case PROP_WORK_DAY_END_MON:
815 e_cal_model_set_work_day_end_mon (
816 E_CAL_MODEL (object),
817 g_value_get_int (value));
818 return;
820 case PROP_WORK_DAY_START_TUE:
821 e_cal_model_set_work_day_start_tue (
822 E_CAL_MODEL (object),
823 g_value_get_int (value));
824 return;
826 case PROP_WORK_DAY_END_TUE:
827 e_cal_model_set_work_day_end_tue (
828 E_CAL_MODEL (object),
829 g_value_get_int (value));
830 return;
832 case PROP_WORK_DAY_START_WED:
833 e_cal_model_set_work_day_start_wed (
834 E_CAL_MODEL (object),
835 g_value_get_int (value));
836 return;
838 case PROP_WORK_DAY_END_WED:
839 e_cal_model_set_work_day_end_wed (
840 E_CAL_MODEL (object),
841 g_value_get_int (value));
842 return;
844 case PROP_WORK_DAY_START_THU:
845 e_cal_model_set_work_day_start_thu (
846 E_CAL_MODEL (object),
847 g_value_get_int (value));
848 return;
850 case PROP_WORK_DAY_END_THU:
851 e_cal_model_set_work_day_end_thu (
852 E_CAL_MODEL (object),
853 g_value_get_int (value));
854 return;
856 case PROP_WORK_DAY_START_FRI:
857 e_cal_model_set_work_day_start_fri (
858 E_CAL_MODEL (object),
859 g_value_get_int (value));
860 return;
862 case PROP_WORK_DAY_END_FRI:
863 e_cal_model_set_work_day_end_fri (
864 E_CAL_MODEL (object),
865 g_value_get_int (value));
866 return;
868 case PROP_WORK_DAY_START_SAT:
869 e_cal_model_set_work_day_start_sat (
870 E_CAL_MODEL (object),
871 g_value_get_int (value));
872 return;
874 case PROP_WORK_DAY_END_SAT:
875 e_cal_model_set_work_day_end_sat (
876 E_CAL_MODEL (object),
877 g_value_get_int (value));
878 return;
880 case PROP_WORK_DAY_START_SUN:
881 e_cal_model_set_work_day_start_sun (
882 E_CAL_MODEL (object),
883 g_value_get_int (value));
884 return;
886 case PROP_WORK_DAY_END_SUN:
887 e_cal_model_set_work_day_end_sun (
888 E_CAL_MODEL (object),
889 g_value_get_int (value));
890 return;
893 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
896 static void
897 cal_model_get_property (GObject *object,
898 guint property_id,
899 GValue *value,
900 GParamSpec *pspec)
902 switch (property_id) {
903 case PROP_CLIENT_CACHE:
904 g_value_set_object (
905 value,
906 e_cal_model_get_client_cache (
907 E_CAL_MODEL (object)));
908 return;
910 case PROP_COMPRESS_WEEKEND:
911 g_value_set_boolean (
912 value,
913 e_cal_model_get_compress_weekend (
914 E_CAL_MODEL (object)));
915 return;
917 case PROP_CONFIRM_DELETE:
918 g_value_set_boolean (
919 value,
920 e_cal_model_get_confirm_delete (
921 E_CAL_MODEL (object)));
922 return;
924 case PROP_DATA_MODEL:
925 g_value_set_object (
926 value,
927 e_cal_model_get_data_model (
928 E_CAL_MODEL (object)));
929 return;
931 case PROP_DEFAULT_SOURCE_UID:
932 g_value_set_string (
933 value,
934 e_cal_model_get_default_source_uid (
935 E_CAL_MODEL (object)));
936 return;
938 case PROP_DEFAULT_REMINDER_INTERVAL:
939 g_value_set_int (
940 value,
941 e_cal_model_get_default_reminder_interval (
942 E_CAL_MODEL (object)));
943 return;
945 case PROP_DEFAULT_REMINDER_UNITS:
946 g_value_set_enum (
947 value,
948 e_cal_model_get_default_reminder_units (
949 E_CAL_MODEL (object)));
950 return;
952 case PROP_REGISTRY:
953 g_value_set_object (
954 value,
955 e_cal_model_get_registry (
956 E_CAL_MODEL (object)));
957 return;
959 case PROP_SHELL:
960 g_value_set_object (
961 value,
962 e_cal_model_get_shell (
963 E_CAL_MODEL (object)));
964 return;
966 case PROP_TIMEZONE:
967 g_value_set_pointer (
968 value,
969 e_cal_model_get_timezone (
970 E_CAL_MODEL (object)));
971 return;
973 case PROP_USE_24_HOUR_FORMAT:
974 g_value_set_boolean (
975 value,
976 e_cal_model_get_use_24_hour_format (
977 E_CAL_MODEL (object)));
978 return;
980 case PROP_USE_DEFAULT_REMINDER:
981 g_value_set_boolean (
982 value,
983 e_cal_model_get_use_default_reminder (
984 E_CAL_MODEL (object)));
985 return;
987 case PROP_WEEK_START_DAY:
988 g_value_set_enum (
989 value,
990 e_cal_model_get_week_start_day (
991 E_CAL_MODEL (object)));
992 return;
994 case PROP_WORK_DAY_MONDAY:
995 g_value_set_boolean (
996 value,
997 e_cal_model_get_work_day (
998 E_CAL_MODEL (object), G_DATE_MONDAY));
999 return;
1001 case PROP_WORK_DAY_TUESDAY:
1002 g_value_set_boolean (
1003 value,
1004 e_cal_model_get_work_day (
1005 E_CAL_MODEL (object), G_DATE_TUESDAY));
1006 return;
1008 case PROP_WORK_DAY_WEDNESDAY:
1009 g_value_set_boolean (
1010 value,
1011 e_cal_model_get_work_day (
1012 E_CAL_MODEL (object), G_DATE_WEDNESDAY));
1013 return;
1015 case PROP_WORK_DAY_THURSDAY:
1016 g_value_set_boolean (
1017 value,
1018 e_cal_model_get_work_day (
1019 E_CAL_MODEL (object), G_DATE_THURSDAY));
1020 return;
1022 case PROP_WORK_DAY_FRIDAY:
1023 g_value_set_boolean (
1024 value,
1025 e_cal_model_get_work_day (
1026 E_CAL_MODEL (object), G_DATE_FRIDAY));
1027 return;
1029 case PROP_WORK_DAY_SATURDAY:
1030 g_value_set_boolean (
1031 value,
1032 e_cal_model_get_work_day (
1033 E_CAL_MODEL (object), G_DATE_SATURDAY));
1034 return;
1036 case PROP_WORK_DAY_SUNDAY:
1037 g_value_set_boolean (
1038 value,
1039 e_cal_model_get_work_day (
1040 E_CAL_MODEL (object), G_DATE_SUNDAY));
1041 return;
1043 case PROP_WORK_DAY_END_HOUR:
1044 g_value_set_int (
1045 value,
1046 e_cal_model_get_work_day_end_hour (
1047 E_CAL_MODEL (object)));
1048 return;
1050 case PROP_WORK_DAY_END_MINUTE:
1051 g_value_set_int (
1052 value,
1053 e_cal_model_get_work_day_end_minute (
1054 E_CAL_MODEL (object)));
1055 return;
1057 case PROP_WORK_DAY_START_HOUR:
1058 g_value_set_int (
1059 value,
1060 e_cal_model_get_work_day_start_hour (
1061 E_CAL_MODEL (object)));
1062 return;
1064 case PROP_WORK_DAY_START_MINUTE:
1065 g_value_set_int (
1066 value,
1067 e_cal_model_get_work_day_start_minute (
1068 E_CAL_MODEL (object)));
1069 return;
1071 case PROP_WORK_DAY_START_MON:
1072 g_value_set_int (
1073 value,
1074 e_cal_model_get_work_day_start_mon (
1075 E_CAL_MODEL (object)));
1076 return;
1078 case PROP_WORK_DAY_END_MON:
1079 g_value_set_int (
1080 value,
1081 e_cal_model_get_work_day_end_mon (
1082 E_CAL_MODEL (object)));
1083 return;
1085 case PROP_WORK_DAY_START_TUE:
1086 g_value_set_int (
1087 value,
1088 e_cal_model_get_work_day_start_tue (
1089 E_CAL_MODEL (object)));
1090 return;
1092 case PROP_WORK_DAY_END_TUE:
1093 g_value_set_int (
1094 value,
1095 e_cal_model_get_work_day_end_tue (
1096 E_CAL_MODEL (object)));
1097 return;
1099 case PROP_WORK_DAY_START_WED:
1100 g_value_set_int (
1101 value,
1102 e_cal_model_get_work_day_start_wed (
1103 E_CAL_MODEL (object)));
1104 return;
1106 case PROP_WORK_DAY_END_WED:
1107 g_value_set_int (
1108 value,
1109 e_cal_model_get_work_day_end_wed (
1110 E_CAL_MODEL (object)));
1111 return;
1113 case PROP_WORK_DAY_START_THU:
1114 g_value_set_int (
1115 value,
1116 e_cal_model_get_work_day_start_thu (
1117 E_CAL_MODEL (object)));
1118 return;
1120 case PROP_WORK_DAY_END_THU:
1121 g_value_set_int (
1122 value,
1123 e_cal_model_get_work_day_end_thu (
1124 E_CAL_MODEL (object)));
1125 return;
1127 case PROP_WORK_DAY_START_FRI:
1128 g_value_set_int (
1129 value,
1130 e_cal_model_get_work_day_start_fri (
1131 E_CAL_MODEL (object)));
1132 return;
1134 case PROP_WORK_DAY_END_FRI:
1135 g_value_set_int (
1136 value,
1137 e_cal_model_get_work_day_end_fri (
1138 E_CAL_MODEL (object)));
1139 return;
1141 case PROP_WORK_DAY_START_SAT:
1142 g_value_set_int (
1143 value,
1144 e_cal_model_get_work_day_start_sat (
1145 E_CAL_MODEL (object)));
1146 return;
1148 case PROP_WORK_DAY_END_SAT:
1149 g_value_set_int (
1150 value,
1151 e_cal_model_get_work_day_end_sat (
1152 E_CAL_MODEL (object)));
1153 return;
1155 case PROP_WORK_DAY_START_SUN:
1156 g_value_set_int (
1157 value,
1158 e_cal_model_get_work_day_start_sun (
1159 E_CAL_MODEL (object)));
1160 return;
1162 case PROP_WORK_DAY_END_SUN:
1163 g_value_set_int (
1164 value,
1165 e_cal_model_get_work_day_end_sun (
1166 E_CAL_MODEL (object)));
1167 return;
1170 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1173 static void
1174 cal_model_constructed (GObject *object)
1176 e_extensible_load_extensions (E_EXTENSIBLE (object));
1178 /* Chain up to parent's constructed() method. */
1179 G_OBJECT_CLASS (e_cal_model_parent_class)->constructed (object);
1182 static void
1183 cal_model_dispose (GObject *object)
1185 ECalModelPrivate *priv;
1187 priv = E_CAL_MODEL_GET_PRIVATE (object);
1189 g_clear_object (&priv->data_model);
1190 g_clear_object (&priv->registry);
1191 g_clear_object (&priv->shell);
1192 g_clear_object (&priv->client_cache);
1194 g_free (priv->default_source_uid);
1195 priv->default_source_uid = NULL;
1197 /* Chain up to parent's dispose() method. */
1198 G_OBJECT_CLASS (e_cal_model_parent_class)->dispose (object);
1201 static void
1202 cal_model_finalize (GObject *object)
1204 ECalModelPrivate *priv;
1205 gint ii;
1207 priv = E_CAL_MODEL_GET_PRIVATE (object);
1209 g_free (priv->default_category);
1211 for (ii = 0; ii < priv->objects->len; ii++) {
1212 ECalModelComponent *comp_data;
1214 comp_data = g_ptr_array_index (priv->objects, ii);
1215 if (comp_data == NULL) {
1216 g_warning ("comp_data is null\n");
1217 continue;
1219 g_object_unref (comp_data);
1221 g_ptr_array_free (priv->objects, TRUE);
1223 /* Chain up to parent's finalize() method. */
1224 G_OBJECT_CLASS (e_cal_model_parent_class)->finalize (object);
1227 static const gchar *
1228 cal_model_get_color_for_component (ECalModel *model,
1229 ECalModelComponent *comp_data)
1231 ESource *source;
1232 ESourceSelectable *extension;
1233 const gchar *color_spec;
1234 const gchar *extension_name;
1235 const gchar *uid;
1236 gint i, first_empty = 0;
1237 #ifdef HAVE_ICAL_COLOR_PROPERTY
1238 icalproperty *prop;
1239 #endif
1241 static AssignedColorData assigned_colors[] = {
1242 { "#BECEDD", NULL }, /* 190 206 221 Blue */
1243 { "#E2F0EF", NULL }, /* 226 240 239 Light Blue */
1244 { "#C6E2B7", NULL }, /* 198 226 183 Green */
1245 { "#E2F0D3", NULL }, /* 226 240 211 Light Green */
1246 { "#E2D4B7", NULL }, /* 226 212 183 Khaki */
1247 { "#EAEAC1", NULL }, /* 234 234 193 Light Khaki */
1248 { "#F0B8B7", NULL }, /* 240 184 183 Pink */
1249 { "#FED4D3", NULL }, /* 254 212 211 Light Pink */
1250 { "#E2C6E1", NULL }, /* 226 198 225 Purple */
1251 { "#F0E2EF", NULL } /* 240 226 239 Light Purple */
1254 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1256 #ifdef HAVE_ICAL_COLOR_PROPERTY
1257 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COLOR_PROPERTY);
1258 if (prop) {
1259 GdkRGBA rgba;
1261 color_spec = icalproperty_get_color (prop);
1262 if (color_spec && gdk_rgba_parse (&rgba, color_spec)) {
1263 g_free (comp_data->color);
1264 comp_data->color = g_strdup (color_spec);
1266 return comp_data->color;
1269 #endif
1271 switch (e_cal_client_get_source_type (comp_data->client)) {
1272 case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
1273 extension_name = E_SOURCE_EXTENSION_CALENDAR;
1274 break;
1275 case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
1276 extension_name = E_SOURCE_EXTENSION_TASK_LIST;
1277 break;
1278 case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
1279 extension_name = E_SOURCE_EXTENSION_MEMO_LIST;
1280 break;
1281 default:
1282 g_return_val_if_reached (NULL);
1285 source = e_client_get_source (E_CLIENT (comp_data->client));
1286 extension = e_source_get_extension (source, extension_name);
1287 color_spec = e_source_selectable_get_color (extension);
1289 if (color_spec != NULL) {
1290 g_free (comp_data->color);
1291 comp_data->color = g_strdup (color_spec);
1292 return comp_data->color;
1295 uid = e_source_get_uid (source);
1297 for (i = 0; i < G_N_ELEMENTS (assigned_colors); i++) {
1298 GList *l;
1300 if (assigned_colors[i].uids == NULL) {
1301 first_empty = i;
1302 continue;
1305 for (l = assigned_colors[i].uids; l != NULL; l = l->next)
1306 if (g_strcmp0 (l->data, uid) == 0)
1307 return assigned_colors[i].color;
1310 /* return the first unused color */
1311 assigned_colors[first_empty].uids = g_list_append (
1312 assigned_colors[first_empty].uids, g_strdup (uid));
1314 return assigned_colors[first_empty].color;
1317 static gint
1318 cal_model_column_count (ETableModel *etm)
1320 return E_CAL_MODEL_FIELD_LAST;
1323 static gint
1324 cal_model_row_count (ETableModel *etm)
1326 ECalModelPrivate *priv;
1327 ECalModel *model = (ECalModel *) etm;
1329 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
1331 priv = model->priv;
1333 return priv->objects->len;
1336 static const gchar *
1337 cal_model_kind_to_extension_name (ECalModel *model)
1339 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1341 switch (model->priv->kind) {
1342 case ICAL_VEVENT_COMPONENT:
1343 return E_SOURCE_EXTENSION_CALENDAR;
1344 case ICAL_VJOURNAL_COMPONENT:
1345 return E_SOURCE_EXTENSION_MEMO_LIST;
1346 case ICAL_VTODO_COMPONENT:
1347 return E_SOURCE_EXTENSION_TASK_LIST;
1348 default:
1349 g_warn_if_reached ();
1350 break;
1353 return NULL;
1356 typedef struct {
1357 ECalModel *model;
1358 ETableModel *table_model;
1359 GHashTable *values;
1360 gboolean success;
1361 } CreateComponentData;
1363 static void
1364 create_component_data_free (gpointer ptr)
1366 CreateComponentData *ccd = ptr;
1368 if (ccd) {
1369 GHashTableIter iter;
1370 gpointer key, value;
1372 g_hash_table_iter_init (&iter, ccd->values);
1373 while (g_hash_table_iter_next (&iter, &key, &value)) {
1374 gint column = GPOINTER_TO_INT (key);
1376 e_table_model_free_value (ccd->table_model, column, value);
1379 if (ccd->success)
1380 g_signal_emit (ccd->model, signals[ROW_APPENDED], 0);
1382 g_clear_object (&ccd->model);
1383 g_clear_object (&ccd->table_model);
1384 g_hash_table_destroy (ccd->values);
1385 g_free (ccd);
1389 static void
1390 cal_model_create_component_from_values_thread (EAlertSinkThreadJobData *job_data,
1391 gpointer user_data,
1392 GCancellable *cancellable,
1393 GError **error)
1395 CreateComponentData *ccd = user_data;
1396 EClientCache *client_cache;
1397 ESourceRegistry *registry;
1398 ESource *source;
1399 EClient *client;
1400 ECalModelComponent *comp_data;
1401 icalproperty *prop;
1402 const gchar *source_uid;
1403 gchar *display_name;
1404 GError *local_error = NULL;
1406 g_return_if_fail (ccd != NULL);
1408 source_uid = e_cal_model_get_default_source_uid (ccd->model);
1409 g_return_if_fail (source_uid != NULL);
1411 client_cache = e_cal_model_get_client_cache (ccd->model);
1412 registry = e_cal_model_get_registry (ccd->model);
1414 source = e_source_registry_ref_source (registry, source_uid);
1415 if (!source) {
1416 g_set_error (&local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
1417 _("Source with UID “%s” not found"), source_uid);
1418 e_alert_sink_thread_job_set_alert_arg_0 (job_data, source_uid);
1419 return;
1422 display_name = e_util_get_source_full_name (registry, source);
1423 e_alert_sink_thread_job_set_alert_arg_0 (job_data, display_name);
1424 g_free (display_name);
1426 client = e_client_cache_get_client_sync (client_cache, source,
1427 cal_model_kind_to_extension_name (ccd->model), (guint32) -1, cancellable, &local_error);
1428 g_clear_object (&source);
1430 if (!client) {
1431 e_util_propagate_open_source_job_error (job_data,
1432 cal_model_kind_to_extension_name (ccd->model), local_error, error);
1433 return;
1436 comp_data = g_object_new (E_TYPE_CAL_MODEL_COMPONENT, NULL);
1437 comp_data->client = g_object_ref (client);
1438 comp_data->icalcomp = e_cal_model_create_component_with_defaults_sync (ccd->model, comp_data->client, FALSE, cancellable, error);
1440 if (comp_data->icalcomp) {
1441 ECalModelClass *model_class;
1442 gchar *uid = NULL;
1443 gpointer dtstart;
1445 /* set values for our fields */
1446 set_categories (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_CATEGORIES));
1447 set_classification (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_CLASSIFICATION));
1448 set_description (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_DESCRIPTION));
1449 set_summary (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_SUMMARY));
1451 dtstart = e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_DTSTART);
1452 if (dtstart) {
1453 set_dtstart (ccd->model, comp_data, dtstart);
1454 } else if (ccd->model->priv->get_default_time) {
1455 time_t tt = ccd->model->priv->get_default_time (ccd->model, ccd->model->priv->get_default_time_user_data);
1457 if (tt > 0) {
1458 /* Store Memo DTSTART as date, not as date-time */
1459 struct icaltimetype itt = icaltime_from_timet_with_zone (tt,
1460 icalcomponent_isa (comp_data->icalcomp) == ICAL_VJOURNAL_COMPONENT, e_cal_model_get_timezone (ccd->model));
1461 icalproperty *prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DTSTART_PROPERTY);
1463 if (prop) {
1464 icalproperty_set_dtstart (prop, itt);
1465 } else {
1466 prop = icalproperty_new_dtstart (itt);
1467 icalcomponent_add_property (comp_data->icalcomp, prop);
1472 /* call the class' method for filling the component */
1473 model_class = E_CAL_MODEL_GET_CLASS (ccd->model);
1474 if (model_class->fill_component_from_values != NULL) {
1475 model_class->fill_component_from_values (ccd->model, comp_data, ccd->values);
1478 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CLASS_PROPERTY);
1479 if (!prop || icalproperty_get_class (prop) == ICAL_CLASS_NONE) {
1480 icalproperty_class ical_class = ICAL_CLASS_PUBLIC;
1481 GSettings *settings;
1483 settings = e_util_ref_settings ("org.gnome.evolution.calendar");
1484 if (g_settings_get_boolean (settings, "classify-private"))
1485 ical_class = ICAL_CLASS_PRIVATE;
1486 g_object_unref (settings);
1488 if (!prop) {
1489 prop = icalproperty_new_class (ical_class);
1490 icalcomponent_add_property (comp_data->icalcomp, prop);
1491 } else
1492 icalproperty_set_class (prop, ical_class);
1495 ccd->success = e_cal_client_create_object_sync (comp_data->client, comp_data->icalcomp, &uid, cancellable, error);
1497 g_free (uid);
1500 g_object_unref (comp_data);
1501 g_object_unref (client);
1504 static void
1505 cal_model_append_row (ETableModel *etm,
1506 ETableModel *source,
1507 gint row)
1509 ECalModelClass *model_class;
1510 ECalModel *model = (ECalModel *) etm;
1511 GHashTable *values;
1512 GCancellable *cancellable;
1513 CreateComponentData *ccd;
1514 const gchar *description;
1515 const gchar *alert_ident;
1517 g_return_if_fail (E_IS_CAL_MODEL (model));
1518 g_return_if_fail (E_IS_TABLE_MODEL (source));
1520 switch (e_cal_model_get_component_kind (model)) {
1521 case ICAL_VEVENT_COMPONENT:
1522 description = _("Creating an event");
1523 alert_ident = "calendar:failed-create-event";
1524 break;
1525 case ICAL_VJOURNAL_COMPONENT:
1526 description = _("Creating a memo");
1527 alert_ident = "calendar:failed-create-memo";
1528 break;
1529 case ICAL_VTODO_COMPONENT:
1530 description = _("Creating a task");
1531 alert_ident = "calendar:failed-create-task";
1532 break;
1533 default:
1534 g_warn_if_reached ();
1535 return;
1538 values = g_hash_table_new (g_direct_hash, g_direct_equal);
1540 /* store values for our fields */
1541 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_CATEGORIES, row);
1542 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_CLASSIFICATION, row);
1543 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_DESCRIPTION, row);
1544 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_SUMMARY, row);
1545 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_DTSTART, row);
1547 /* call the class' method to store other values */
1548 model_class = E_CAL_MODEL_GET_CLASS (model);
1549 if (model_class->store_values_from_model != NULL) {
1550 model_class->store_values_from_model (model, source, row, values);
1553 ccd = g_new0 (CreateComponentData, 1);
1554 ccd->model = g_object_ref (model);
1555 ccd->table_model = g_object_ref (source);
1556 ccd->values = values;
1557 ccd->success = FALSE;
1559 cancellable = e_cal_data_model_submit_thread_job (model->priv->data_model, description,
1560 alert_ident, NULL, cal_model_create_component_from_values_thread,
1561 ccd, create_component_data_free);
1563 g_clear_object (&cancellable);
1566 static gpointer
1567 cal_model_value_at (ETableModel *etm,
1568 gint col,
1569 gint row)
1571 ECalModelPrivate *priv;
1572 ECalModelComponent *comp_data;
1573 ECalModel *model = (ECalModel *) etm;
1574 ESourceRegistry *registry;
1576 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1578 priv = model->priv;
1580 registry = e_cal_model_get_registry (model);
1582 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
1583 g_return_val_if_fail (row >= 0 && row < priv->objects->len, NULL);
1585 comp_data = g_ptr_array_index (priv->objects, row);
1586 g_return_val_if_fail (comp_data != NULL, NULL);
1587 g_return_val_if_fail (comp_data->icalcomp != NULL, NULL);
1589 switch (col) {
1590 case E_CAL_MODEL_FIELD_CATEGORIES :
1591 return get_categories (comp_data);
1592 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1593 return get_classification (comp_data);
1594 case E_CAL_MODEL_FIELD_COLOR :
1595 return (gpointer) get_color (model, comp_data);
1596 case E_CAL_MODEL_FIELD_COMPONENT :
1597 return comp_data->icalcomp;
1598 case E_CAL_MODEL_FIELD_DESCRIPTION :
1599 return get_description (comp_data);
1600 case E_CAL_MODEL_FIELD_DTSTART :
1601 return (gpointer) get_dtstart (model, comp_data);
1602 case E_CAL_MODEL_FIELD_CREATED :
1603 return (gpointer) get_datetime_from_utc (
1604 model, comp_data, ICAL_CREATED_PROPERTY,
1605 icalproperty_get_created, &comp_data->created);
1606 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1607 return (gpointer) get_datetime_from_utc (
1608 model, comp_data, ICAL_LASTMODIFIED_PROPERTY,
1609 icalproperty_get_lastmodified, &comp_data->lastmodified);
1610 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1611 return GINT_TO_POINTER (
1612 icalcomponent_get_first_component (
1613 comp_data->icalcomp,
1614 ICAL_VALARM_COMPONENT) != NULL);
1615 case E_CAL_MODEL_FIELD_ICON :
1617 ECalComponent *comp;
1618 icalcomponent *icalcomp;
1619 gint retval = 0;
1621 comp = e_cal_component_new ();
1622 icalcomp = icalcomponent_new_clone (comp_data->icalcomp);
1623 if (e_cal_component_set_icalcomponent (comp, icalcomp)) {
1624 if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_JOURNAL) {
1625 g_object_unref (comp);
1626 return GINT_TO_POINTER (retval);
1629 if (e_cal_component_has_recurrences (comp))
1630 retval = 1;
1631 else if (itip_organizer_is_user (registry, comp, comp_data->client))
1632 retval = 3;
1633 else {
1634 GSList *attendees = NULL, *sl;
1636 e_cal_component_get_attendee_list (comp, &attendees);
1637 for (sl = attendees; sl != NULL; sl = sl->next) {
1638 ECalComponentAttendee *ca = sl->data;
1639 const gchar *text;
1641 text = itip_strip_mailto (ca->value);
1642 if (itip_address_is_user (registry, text)) {
1643 if (ca->delto != NULL)
1644 retval = 3;
1645 else
1646 retval = 2;
1647 break;
1651 e_cal_component_free_attendee_list (attendees);
1653 } else
1654 icalcomponent_free (icalcomp);
1656 g_object_unref (comp);
1658 return GINT_TO_POINTER (retval);
1660 case E_CAL_MODEL_FIELD_SUMMARY :
1661 return get_summary (comp_data);
1662 case E_CAL_MODEL_FIELD_UID :
1663 return get_uid (comp_data);
1664 case E_CAL_MODEL_FIELD_SOURCE:
1665 return get_source_description (registry, comp_data);
1668 return (gpointer) "";
1671 static void
1672 cal_model_set_value_at (ETableModel *etm,
1673 gint col,
1674 gint row,
1675 gconstpointer value)
1677 ECalModelPrivate *priv;
1678 ECalModelComponent *comp_data;
1679 ECalModel *model = (ECalModel *) etm;
1680 ECalObjModType mod = E_CAL_OBJ_MOD_ALL;
1682 g_return_if_fail (E_IS_CAL_MODEL (model));
1684 priv = model->priv;
1686 g_return_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST);
1687 g_return_if_fail (row >= 0 && row < priv->objects->len);
1689 comp_data = g_ptr_array_index (priv->objects, row);
1690 g_return_if_fail (comp_data != NULL);
1692 switch (col) {
1693 case E_CAL_MODEL_FIELD_CATEGORIES :
1694 set_categories (comp_data, value);
1695 break;
1696 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1697 set_classification (comp_data, value);
1698 break;
1699 case E_CAL_MODEL_FIELD_DESCRIPTION :
1700 set_description (comp_data, value);
1701 break;
1702 case E_CAL_MODEL_FIELD_DTSTART :
1703 set_dtstart (model, comp_data, value);
1704 break;
1705 case E_CAL_MODEL_FIELD_SUMMARY :
1706 set_summary (comp_data, value);
1707 break;
1710 if (!e_cal_dialogs_recur_icalcomp (comp_data->client, comp_data->icalcomp, &mod, NULL, FALSE))
1711 return;
1713 e_cal_ops_modify_component (model, comp_data->client, comp_data->icalcomp, mod, E_CAL_OPS_SEND_FLAG_DONT_SEND);
1716 static gboolean
1717 cal_model_is_cell_editable (ETableModel *etm,
1718 gint col,
1719 gint row)
1721 ECalModelPrivate *priv;
1722 ECalModel *model = (ECalModel *) etm;
1724 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
1726 priv = model->priv;
1728 g_return_val_if_fail (col >= 0 && col <= E_CAL_MODEL_FIELD_LAST, FALSE);
1729 g_return_val_if_fail (row >= -1 || (row >= 0 && row < priv->objects->len), FALSE);
1731 if (!e_cal_model_test_row_editable (E_CAL_MODEL (etm), row))
1732 return FALSE;
1734 switch (col) {
1735 case E_CAL_MODEL_FIELD_CATEGORIES :
1736 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1737 case E_CAL_MODEL_FIELD_DESCRIPTION :
1738 case E_CAL_MODEL_FIELD_DTSTART :
1739 case E_CAL_MODEL_FIELD_SUMMARY :
1740 return TRUE;
1743 return FALSE;
1746 static gpointer
1747 cal_model_duplicate_value (ETableModel *etm,
1748 gint col,
1749 gconstpointer value)
1751 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
1753 switch (col) {
1754 case E_CAL_MODEL_FIELD_CATEGORIES :
1755 case E_CAL_MODEL_FIELD_DESCRIPTION :
1756 case E_CAL_MODEL_FIELD_SUMMARY :
1757 case E_CAL_MODEL_FIELD_SOURCE:
1758 return g_strdup (value);
1759 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1760 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1761 case E_CAL_MODEL_FIELD_ICON :
1762 case E_CAL_MODEL_FIELD_COLOR :
1763 return (gpointer) value;
1764 case E_CAL_MODEL_FIELD_COMPONENT :
1765 return icalcomponent_new_clone ((icalcomponent *) value);
1766 case E_CAL_MODEL_FIELD_DTSTART :
1767 case E_CAL_MODEL_FIELD_CREATED :
1768 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1769 return e_cal_model_copy_cell_date_value (value);
1772 return NULL;
1775 static void
1776 cal_model_free_value (ETableModel *etm,
1777 gint col,
1778 gpointer value)
1780 g_return_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST);
1782 switch (col) {
1783 case E_CAL_MODEL_FIELD_CATEGORIES :
1784 case E_CAL_MODEL_FIELD_DESCRIPTION :
1785 case E_CAL_MODEL_FIELD_SUMMARY :
1786 case E_CAL_MODEL_FIELD_SOURCE:
1787 if (value)
1788 g_free (value);
1789 break;
1790 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1791 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1792 case E_CAL_MODEL_FIELD_ICON :
1793 case E_CAL_MODEL_FIELD_COLOR :
1794 break;
1795 case E_CAL_MODEL_FIELD_DTSTART:
1796 case E_CAL_MODEL_FIELD_CREATED :
1797 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1798 if (value)
1799 g_free (value);
1800 break;
1801 case E_CAL_MODEL_FIELD_COMPONENT :
1802 if (value)
1803 icalcomponent_free ((icalcomponent *) value);
1804 break;
1808 static gpointer
1809 cal_model_initialize_value (ETableModel *etm,
1810 gint col)
1812 ECalModelPrivate *priv;
1813 ECalModel *model = (ECalModel *) etm;
1815 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1816 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
1818 priv = model->priv;
1820 switch (col) {
1821 case E_CAL_MODEL_FIELD_CATEGORIES :
1822 return g_strdup (priv->default_category ? priv->default_category:"");
1823 case E_CAL_MODEL_FIELD_DESCRIPTION :
1824 case E_CAL_MODEL_FIELD_SUMMARY :
1825 case E_CAL_MODEL_FIELD_SOURCE:
1826 return g_strdup ("");
1827 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1828 case E_CAL_MODEL_FIELD_DTSTART :
1829 case E_CAL_MODEL_FIELD_CREATED :
1830 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1831 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1832 case E_CAL_MODEL_FIELD_ICON :
1833 case E_CAL_MODEL_FIELD_COLOR :
1834 case E_CAL_MODEL_FIELD_COMPONENT :
1835 return NULL;
1838 return NULL;
1841 static gboolean
1842 cal_model_value_is_empty (ETableModel *etm,
1843 gint col,
1844 gconstpointer value)
1846 ECalModelPrivate *priv;
1847 ECalModel *model = (ECalModel *) etm;
1849 g_return_val_if_fail (E_IS_CAL_MODEL (model), TRUE);
1850 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, TRUE);
1852 priv = model->priv;
1854 switch (col) {
1855 case E_CAL_MODEL_FIELD_CATEGORIES :
1856 /* This could be a hack or not. If the categories field only
1857 * contains the default category, then it possibly means that
1858 * the user has not entered anything at all in the click-to-add;
1859 * the category is in the value because we put it there in
1860 * ecm_initialize_value().
1862 if (priv->default_category && value && strcmp (priv->default_category, value) == 0)
1863 return TRUE;
1864 else
1865 return string_is_empty (value);
1866 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1867 case E_CAL_MODEL_FIELD_DESCRIPTION :
1868 case E_CAL_MODEL_FIELD_SUMMARY :
1869 case E_CAL_MODEL_FIELD_SOURCE:
1870 return string_is_empty (value);
1871 case E_CAL_MODEL_FIELD_DTSTART :
1872 case E_CAL_MODEL_FIELD_CREATED :
1873 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1874 return value ? FALSE : TRUE;
1875 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1876 case E_CAL_MODEL_FIELD_ICON :
1877 case E_CAL_MODEL_FIELD_COLOR :
1878 case E_CAL_MODEL_FIELD_COMPONENT :
1879 return TRUE;
1882 return TRUE;
1885 static gchar *
1886 cal_model_value_to_string (ETableModel *etm,
1887 gint col,
1888 gconstpointer value)
1890 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, g_strdup (""));
1892 switch (col) {
1893 case E_CAL_MODEL_FIELD_CATEGORIES :
1894 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1895 case E_CAL_MODEL_FIELD_DESCRIPTION :
1896 case E_CAL_MODEL_FIELD_SUMMARY :
1897 case E_CAL_MODEL_FIELD_SOURCE:
1898 return g_strdup (value);
1899 case E_CAL_MODEL_FIELD_DTSTART :
1900 case E_CAL_MODEL_FIELD_CREATED :
1901 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1902 return e_cal_model_date_value_to_string (E_CAL_MODEL (etm), value);
1903 case E_CAL_MODEL_FIELD_ICON :
1904 if (GPOINTER_TO_INT (value) == 0)
1905 return g_strdup (_("Normal"));
1906 else if (GPOINTER_TO_INT (value) == 1)
1907 return g_strdup (_("Recurring"));
1908 else
1909 return g_strdup (_("Assigned"));
1910 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1911 return g_strdup (value ? _("Yes") : _("No"));
1912 case E_CAL_MODEL_FIELD_COLOR :
1913 case E_CAL_MODEL_FIELD_COMPONENT :
1914 return g_strdup ("");
1917 return g_strdup ("");
1920 static gint
1921 e_cal_model_get_component_index (ECalModel *model,
1922 ECalClient *client,
1923 const ECalComponentId *id)
1925 gint ii;
1927 for (ii = 0; ii < model->priv->objects->len; ii++) {
1928 ECalModelComponent *comp_data = g_ptr_array_index (model->priv->objects, ii);
1930 if (comp_data) {
1931 const gchar *uid;
1932 gchar *rid = NULL;
1933 struct icaltimetype icalrid;
1934 gboolean has_rid = (id->rid && *id->rid);
1936 uid = icalcomponent_get_uid (comp_data->icalcomp);
1937 icalrid = icalcomponent_get_recurrenceid (comp_data->icalcomp);
1938 if (!icaltime_is_null_time (icalrid))
1939 rid = icaltime_as_ical_string_r (icalrid);
1941 if (uid && *uid) {
1942 if ((!client || comp_data->client == client) && strcmp (id->uid, uid) == 0) {
1943 if (has_rid) {
1944 if (!(rid && *rid && strcmp (rid, id->rid) == 0)) {
1945 g_free (rid);
1946 continue;
1949 g_free (rid);
1950 return ii;
1954 g_free (rid);
1958 return -1;
1961 static void
1962 cal_model_data_subscriber_component_added_or_modified (ECalDataModelSubscriber *subscriber,
1963 ECalClient *client,
1964 ECalComponent *comp,
1965 gboolean is_added)
1967 ECalModel *model;
1968 ECalModelComponent *comp_data;
1969 ETableModel *table_model;
1970 ECalComponentId *id;
1971 icalcomponent *icalcomp;
1972 gint index;
1974 model = E_CAL_MODEL (subscriber);
1976 id = e_cal_component_get_id (comp);
1978 index = e_cal_model_get_component_index (model, client, id);
1980 e_cal_component_free_id (id);
1982 if (index < 0 && !is_added)
1983 return;
1985 table_model = E_TABLE_MODEL (model);
1986 icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
1988 if (index < 0) {
1989 e_table_model_pre_change (table_model);
1991 comp_data = g_object_new (E_TYPE_CAL_MODEL_COMPONENT, NULL);
1992 comp_data->is_new_component = FALSE;
1993 comp_data->client = g_object_ref (client);
1994 comp_data->icalcomp = icalcomp;
1995 e_cal_model_set_instance_times (comp_data, model->priv->zone);
1996 g_ptr_array_add (model->priv->objects, comp_data);
1998 e_table_model_row_inserted (table_model, model->priv->objects->len - 1);
1999 } else {
2000 e_table_model_pre_change (table_model);
2002 comp_data = g_ptr_array_index (model->priv->objects, index);
2003 e_cal_model_component_set_icalcomponent (comp_data, model, icalcomp);
2005 e_table_model_row_changed (table_model, index);
2009 static void
2010 e_cal_model_data_subscriber_component_added (ECalDataModelSubscriber *subscriber,
2011 ECalClient *client,
2012 ECalComponent *comp)
2014 cal_model_data_subscriber_component_added_or_modified (subscriber, client, comp, TRUE);
2017 static void
2018 e_cal_model_data_subscriber_component_modified (ECalDataModelSubscriber *subscriber,
2019 ECalClient *client,
2020 ECalComponent *comp)
2022 cal_model_data_subscriber_component_added_or_modified (subscriber, client, comp, FALSE);
2025 static void
2026 e_cal_model_data_subscriber_component_removed (ECalDataModelSubscriber *subscriber,
2027 ECalClient *client,
2028 const gchar *uid,
2029 const gchar *rid)
2031 ECalModel *model;
2032 ECalModelComponent *comp_data;
2033 ETableModel *table_model;
2034 ECalComponentId id;
2035 GSList *link;
2036 gint index;
2038 model = E_CAL_MODEL (subscriber);
2040 id.uid = (gchar *) uid;
2041 id.rid = (gchar *) rid;
2043 index = e_cal_model_get_component_index (model, client, &id);
2045 if (index < 0)
2046 return;
2048 table_model = E_TABLE_MODEL (model);
2049 e_table_model_pre_change (table_model);
2051 comp_data = g_ptr_array_remove_index (model->priv->objects, index);
2052 if (!comp_data) {
2053 e_table_model_no_change (table_model);
2054 return;
2057 link = g_slist_append (NULL, comp_data);
2058 g_signal_emit (model, signals[COMPS_DELETED], 0, link);
2060 g_slist_free (link);
2061 g_object_unref (comp_data);
2063 e_table_model_row_deleted (table_model, index);
2066 static void
2067 e_cal_model_data_subscriber_freeze (ECalDataModelSubscriber *subscriber)
2069 /* No freeze/thaw, the ETableModel doesn't notify about changes when frozen */
2071 /* ETableModel *table_model = E_TABLE_MODEL (subscriber);
2072 e_table_model_freeze (table_model); */
2075 static void
2076 e_cal_model_data_subscriber_thaw (ECalDataModelSubscriber *subscriber)
2078 /* No freeze/thaw, the ETableModel doesn't notify about changes when frozen */
2080 /* ETableModel *table_model = E_TABLE_MODEL (subscriber);
2081 e_table_model_thaw (table_model); */
2084 static void
2085 e_cal_model_class_init (ECalModelClass *class)
2087 GObjectClass *object_class;
2089 g_type_class_add_private (class, sizeof (ECalModelPrivate));
2091 object_class = G_OBJECT_CLASS (class);
2092 object_class->set_property = cal_model_set_property;
2093 object_class->get_property = cal_model_get_property;
2094 object_class->constructed = cal_model_constructed;
2095 object_class->dispose = cal_model_dispose;
2096 object_class->finalize = cal_model_finalize;
2098 class->get_color_for_component = cal_model_get_color_for_component;
2100 g_object_class_install_property (
2101 object_class,
2102 PROP_DATA_MODEL,
2103 g_param_spec_object (
2104 "data-model",
2105 "Calendar Data Model",
2106 NULL,
2107 E_TYPE_CAL_DATA_MODEL,
2108 G_PARAM_READWRITE |
2109 G_PARAM_CONSTRUCT_ONLY));
2111 g_object_class_install_property (
2112 object_class,
2113 PROP_CLIENT_CACHE,
2114 g_param_spec_object (
2115 "client-cache",
2116 "Client Cache",
2117 NULL,
2118 E_TYPE_CLIENT_CACHE,
2119 G_PARAM_READABLE));
2121 g_object_class_install_property (
2122 object_class,
2123 PROP_COMPRESS_WEEKEND,
2124 g_param_spec_boolean (
2125 "compress-weekend",
2126 "Compress Weekend",
2127 NULL,
2128 FALSE,
2129 G_PARAM_READWRITE));
2131 g_object_class_install_property (
2132 object_class,
2133 PROP_CONFIRM_DELETE,
2134 g_param_spec_boolean (
2135 "confirm-delete",
2136 "Confirm Delete",
2137 NULL,
2138 TRUE,
2139 G_PARAM_READWRITE));
2141 g_object_class_install_property (
2142 object_class,
2143 PROP_DEFAULT_REMINDER_INTERVAL,
2144 g_param_spec_int (
2145 "default-reminder-interval",
2146 "Default Reminder Interval",
2147 NULL,
2148 G_MININT,
2149 G_MAXINT,
2151 G_PARAM_READWRITE));
2153 g_object_class_install_property (
2154 object_class,
2155 PROP_DEFAULT_REMINDER_UNITS,
2156 g_param_spec_enum (
2157 "default-reminder-units",
2158 "Default Reminder Units",
2159 NULL,
2160 E_TYPE_DURATION_TYPE,
2161 E_DURATION_MINUTES,
2162 G_PARAM_READWRITE));
2164 g_object_class_install_property (
2165 object_class,
2166 PROP_DEFAULT_SOURCE_UID,
2167 g_param_spec_string (
2168 "default-source-uid",
2169 "Default source UID of an ECalClient",
2170 NULL,
2171 NULL,
2172 G_PARAM_READWRITE));
2174 g_object_class_install_property (
2175 object_class,
2176 PROP_REGISTRY,
2177 g_param_spec_object (
2178 "registry",
2179 "Registry",
2180 "Data source registry",
2181 E_TYPE_SOURCE_REGISTRY,
2182 G_PARAM_READWRITE |
2183 G_PARAM_CONSTRUCT_ONLY));
2185 g_object_class_install_property (
2186 object_class,
2187 PROP_SHELL,
2188 g_param_spec_object (
2189 "shell",
2190 "Shell",
2191 "EShell",
2192 E_TYPE_SHELL,
2193 G_PARAM_READWRITE |
2194 G_PARAM_CONSTRUCT_ONLY));
2196 g_object_class_install_property (
2197 object_class,
2198 PROP_TIMEZONE,
2199 g_param_spec_pointer (
2200 "timezone",
2201 "Time Zone",
2202 NULL,
2203 G_PARAM_READWRITE));
2205 g_object_class_install_property (
2206 object_class,
2207 PROP_USE_24_HOUR_FORMAT,
2208 g_param_spec_boolean (
2209 "use-24-hour-format",
2210 "Use 24-Hour Format",
2211 NULL,
2212 TRUE,
2213 G_PARAM_READWRITE));
2215 g_object_class_install_property (
2216 object_class,
2217 PROP_USE_DEFAULT_REMINDER,
2218 g_param_spec_boolean (
2219 "use-default-reminder",
2220 "Use Default Reminder",
2221 NULL,
2222 FALSE,
2223 G_PARAM_READWRITE));
2225 g_object_class_install_property (
2226 object_class,
2227 PROP_WEEK_START_DAY,
2228 g_param_spec_enum (
2229 "week-start-day",
2230 "Week Start Day",
2231 NULL,
2232 E_TYPE_DATE_WEEKDAY,
2233 G_DATE_MONDAY,
2234 G_PARAM_READWRITE |
2235 G_PARAM_CONSTRUCT));
2237 g_object_class_install_property (
2238 object_class,
2239 PROP_WORK_DAY_MONDAY,
2240 g_param_spec_boolean (
2241 "work-day-monday",
2242 "Work Day: Monday",
2243 "Whether Monday is a work day",
2244 TRUE,
2245 G_PARAM_READWRITE |
2246 G_PARAM_CONSTRUCT |
2247 G_PARAM_STATIC_STRINGS));
2249 g_object_class_install_property (
2250 object_class,
2251 PROP_WORK_DAY_TUESDAY,
2252 g_param_spec_boolean (
2253 "work-day-tuesday",
2254 "Work Day: Tuesday",
2255 "Whether Tuesday is a work day",
2256 TRUE,
2257 G_PARAM_READWRITE |
2258 G_PARAM_CONSTRUCT |
2259 G_PARAM_STATIC_STRINGS));
2261 g_object_class_install_property (
2262 object_class,
2263 PROP_WORK_DAY_WEDNESDAY,
2264 g_param_spec_boolean (
2265 "work-day-wednesday",
2266 "Work Day: Wednesday",
2267 "Whether Wednesday is a work day",
2268 TRUE,
2269 G_PARAM_READWRITE |
2270 G_PARAM_CONSTRUCT |
2271 G_PARAM_STATIC_STRINGS));
2273 g_object_class_install_property (
2274 object_class,
2275 PROP_WORK_DAY_THURSDAY,
2276 g_param_spec_boolean (
2277 "work-day-thursday",
2278 "Work Day: Thursday",
2279 "Whether Thursday is a work day",
2280 TRUE,
2281 G_PARAM_READWRITE |
2282 G_PARAM_CONSTRUCT |
2283 G_PARAM_STATIC_STRINGS));
2285 g_object_class_install_property (
2286 object_class,
2287 PROP_WORK_DAY_FRIDAY,
2288 g_param_spec_boolean (
2289 "work-day-friday",
2290 "Work Day: Friday",
2291 "Whether Friday is a work day",
2292 TRUE,
2293 G_PARAM_READWRITE |
2294 G_PARAM_CONSTRUCT |
2295 G_PARAM_STATIC_STRINGS));
2297 g_object_class_install_property (
2298 object_class,
2299 PROP_WORK_DAY_SATURDAY,
2300 g_param_spec_boolean (
2301 "work-day-saturday",
2302 "Work Day: Saturday",
2303 "Whether Saturday is a work day",
2304 TRUE,
2305 G_PARAM_READWRITE |
2306 G_PARAM_CONSTRUCT |
2307 G_PARAM_STATIC_STRINGS));
2309 g_object_class_install_property (
2310 object_class,
2311 PROP_WORK_DAY_SUNDAY,
2312 g_param_spec_boolean (
2313 "work-day-sunday",
2314 "Work Day: Sunday",
2315 "Whether Sunday is a work day",
2316 TRUE,
2317 G_PARAM_READWRITE |
2318 G_PARAM_CONSTRUCT |
2319 G_PARAM_STATIC_STRINGS));
2321 g_object_class_install_property (
2322 object_class,
2323 PROP_WORK_DAY_END_HOUR,
2324 g_param_spec_int (
2325 "work-day-end-hour",
2326 "Work Day End Hour",
2327 NULL,
2331 G_PARAM_READWRITE));
2333 g_object_class_install_property (
2334 object_class,
2335 PROP_WORK_DAY_END_MINUTE,
2336 g_param_spec_int (
2337 "work-day-end-minute",
2338 "Work Day End Minute",
2339 NULL,
2343 G_PARAM_READWRITE));
2345 g_object_class_install_property (
2346 object_class,
2347 PROP_WORK_DAY_START_HOUR,
2348 g_param_spec_int (
2349 "work-day-start-hour",
2350 "Work Day Start Hour",
2351 NULL,
2355 G_PARAM_READWRITE));
2357 g_object_class_install_property (
2358 object_class,
2359 PROP_WORK_DAY_START_MINUTE,
2360 g_param_spec_int (
2361 "work-day-start-minute",
2362 "Work Day Start Minute",
2363 NULL,
2367 G_PARAM_READWRITE));
2369 g_object_class_install_property (
2370 object_class,
2371 PROP_WORK_DAY_START_MON,
2372 g_param_spec_int (
2373 "work-day-start-mon",
2374 "Work Day Start for Monday",
2375 NULL,
2377 2359,
2379 G_PARAM_READWRITE));
2381 g_object_class_install_property (
2382 object_class,
2383 PROP_WORK_DAY_END_MON,
2384 g_param_spec_int (
2385 "work-day-end-mon",
2386 "Work Day End for Monday",
2387 NULL,
2389 2359,
2391 G_PARAM_READWRITE));
2393 g_object_class_install_property (
2394 object_class,
2395 PROP_WORK_DAY_START_TUE,
2396 g_param_spec_int (
2397 "work-day-start-tue",
2398 "Work Day Start for Tuesday",
2399 NULL,
2401 2359,
2403 G_PARAM_READWRITE));
2405 g_object_class_install_property (
2406 object_class,
2407 PROP_WORK_DAY_END_TUE,
2408 g_param_spec_int (
2409 "work-day-end-tue",
2410 "Work Day End for Tuesday",
2411 NULL,
2413 2359,
2415 G_PARAM_READWRITE));
2417 g_object_class_install_property (
2418 object_class,
2419 PROP_WORK_DAY_START_WED,
2420 g_param_spec_int (
2421 "work-day-start-wed",
2422 "Work Day Start for Wednesday",
2423 NULL,
2425 2359,
2427 G_PARAM_READWRITE));
2429 g_object_class_install_property (
2430 object_class,
2431 PROP_WORK_DAY_END_WED,
2432 g_param_spec_int (
2433 "work-day-end-wed",
2434 "Work Day End for Wednesday",
2435 NULL,
2437 2359,
2439 G_PARAM_READWRITE));
2441 g_object_class_install_property (
2442 object_class,
2443 PROP_WORK_DAY_START_THU,
2444 g_param_spec_int (
2445 "work-day-start-thu",
2446 "Work Day Start for Thursday",
2447 NULL,
2449 2359,
2451 G_PARAM_READWRITE));
2453 g_object_class_install_property (
2454 object_class,
2455 PROP_WORK_DAY_END_THU,
2456 g_param_spec_int (
2457 "work-day-end-thu",
2458 "Work Day End for Thursday",
2459 NULL,
2461 2359,
2463 G_PARAM_READWRITE));
2465 g_object_class_install_property (
2466 object_class,
2467 PROP_WORK_DAY_START_FRI,
2468 g_param_spec_int (
2469 "work-day-start-fri",
2470 "Work Day Start for Friday",
2471 NULL,
2473 2359,
2475 G_PARAM_READWRITE));
2477 g_object_class_install_property (
2478 object_class,
2479 PROP_WORK_DAY_END_FRI,
2480 g_param_spec_int (
2481 "work-day-end-fri",
2482 "Work Day End for Friday",
2483 NULL,
2485 2359,
2487 G_PARAM_READWRITE));
2489 g_object_class_install_property (
2490 object_class,
2491 PROP_WORK_DAY_START_SAT,
2492 g_param_spec_int (
2493 "work-day-start-sat",
2494 "Work Day Start for Saturday",
2495 NULL,
2497 2359,
2499 G_PARAM_READWRITE));
2501 g_object_class_install_property (
2502 object_class,
2503 PROP_WORK_DAY_END_SAT,
2504 g_param_spec_int (
2505 "work-day-end-sat",
2506 "Work Day End for Saturday",
2507 NULL,
2509 2359,
2511 G_PARAM_READWRITE));
2513 g_object_class_install_property (
2514 object_class,
2515 PROP_WORK_DAY_START_SUN,
2516 g_param_spec_int (
2517 "work-day-start-sun",
2518 "Work Day Start for Sunday",
2519 NULL,
2521 2359,
2523 G_PARAM_READWRITE));
2525 g_object_class_install_property (
2526 object_class,
2527 PROP_WORK_DAY_END_SUN,
2528 g_param_spec_int (
2529 "work-day-end-sun",
2530 "Work Day End for Sunday",
2531 NULL,
2533 2359,
2535 G_PARAM_READWRITE));
2537 signals[TIME_RANGE_CHANGED] = g_signal_new (
2538 "time_range_changed",
2539 G_TYPE_FROM_CLASS (class),
2540 G_SIGNAL_RUN_LAST,
2541 G_STRUCT_OFFSET (ECalModelClass, time_range_changed),
2542 NULL, NULL,
2543 e_marshal_VOID__INT64_INT64,
2544 G_TYPE_NONE, 2,
2545 G_TYPE_INT64,
2546 G_TYPE_INT64);
2548 signals[ROW_APPENDED] = g_signal_new (
2549 "row_appended",
2550 G_TYPE_FROM_CLASS (class),
2551 G_SIGNAL_RUN_LAST,
2552 G_STRUCT_OFFSET (ECalModelClass, row_appended),
2553 NULL, NULL,
2554 g_cclosure_marshal_VOID__VOID,
2555 G_TYPE_NONE, 0);
2557 signals[COMPS_DELETED] = g_signal_new (
2558 "comps_deleted",
2559 G_TYPE_FROM_CLASS (class),
2560 G_SIGNAL_RUN_LAST,
2561 G_STRUCT_OFFSET (ECalModelClass, comps_deleted),
2562 NULL, NULL,
2563 g_cclosure_marshal_VOID__POINTER,
2564 G_TYPE_NONE, 1,
2565 G_TYPE_POINTER);
2567 signals[TIMEZONE_CHANGED] = g_signal_new (
2568 "timezone-changed",
2569 G_TYPE_FROM_CLASS (class),
2570 G_SIGNAL_RUN_LAST,
2571 G_STRUCT_OFFSET (ECalModelClass, timezone_changed),
2572 NULL, NULL,
2573 e_marshal_VOID__POINTER_POINTER,
2574 G_TYPE_NONE, 2,
2575 G_TYPE_POINTER,
2576 G_TYPE_POINTER);
2578 signals[OBJECT_CREATED] = g_signal_new (
2579 "object-created",
2580 G_TYPE_FROM_CLASS (class),
2581 G_SIGNAL_RUN_LAST,
2582 G_STRUCT_OFFSET (ECalModelClass, object_created),
2583 NULL, NULL,
2584 g_cclosure_marshal_VOID__OBJECT,
2585 G_TYPE_NONE, 1, E_TYPE_CAL_CLIENT);
2588 static void
2589 e_cal_model_table_model_init (ETableModelInterface *iface)
2591 iface->column_count = cal_model_column_count;
2592 iface->row_count = cal_model_row_count;
2593 iface->append_row = cal_model_append_row;
2595 iface->value_at = cal_model_value_at;
2596 iface->set_value_at = cal_model_set_value_at;
2597 iface->is_cell_editable = cal_model_is_cell_editable;
2599 iface->duplicate_value = cal_model_duplicate_value;
2600 iface->free_value = cal_model_free_value;
2601 iface->initialize_value = cal_model_initialize_value;
2602 iface->value_is_empty = cal_model_value_is_empty;
2603 iface->value_to_string = cal_model_value_to_string;
2606 static void
2607 e_cal_model_cal_data_model_subscriber_init (ECalDataModelSubscriberInterface *iface)
2609 iface->component_added = e_cal_model_data_subscriber_component_added;
2610 iface->component_modified = e_cal_model_data_subscriber_component_modified;
2611 iface->component_removed = e_cal_model_data_subscriber_component_removed;
2612 iface->freeze = e_cal_model_data_subscriber_freeze;
2613 iface->thaw = e_cal_model_data_subscriber_thaw;
2616 static void
2617 e_cal_model_init (ECalModel *model)
2619 model->priv = E_CAL_MODEL_GET_PRIVATE (model);
2621 /* match none by default */
2622 model->priv->start = (time_t) -1;
2623 model->priv->end = (time_t) -1;
2625 model->priv->objects = g_ptr_array_new ();
2626 model->priv->kind = ICAL_NO_COMPONENT;
2628 model->priv->use_24_hour_format = TRUE;
2631 /* updates time in a component, and keeps the timezone used in it, if exists */
2632 void
2633 e_cal_model_update_comp_time (ECalModel *model,
2634 ECalModelComponent *comp_data,
2635 gconstpointer time_value,
2636 icalproperty_kind kind,
2637 void (*set_func) (icalproperty *prop,
2638 struct icaltimetype v),
2639 icalproperty * (*new_func) (struct icaltimetype v))
2641 ECellDateEditValue *dv = (ECellDateEditValue *) time_value;
2642 icalproperty *prop;
2643 icalparameter *param;
2644 icaltimezone *model_zone;
2645 struct icaltimetype tt;
2647 g_return_if_fail (model != NULL);
2648 g_return_if_fail (comp_data != NULL);
2649 g_return_if_fail (set_func != NULL);
2650 g_return_if_fail (new_func != NULL);
2652 prop = icalcomponent_get_first_property (comp_data->icalcomp, kind);
2653 if (prop)
2654 param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
2655 else
2656 param = NULL;
2658 /* If we are setting the property to NULL (i.e. removing it), then
2659 * we remove it if it exists. */
2660 if (!dv) {
2661 if (prop) {
2662 icalcomponent_remove_property (comp_data->icalcomp, prop);
2663 icalproperty_free (prop);
2666 return;
2669 model_zone = e_cal_model_get_timezone (model);
2670 tt = dv->tt;
2671 datetime_to_zone (comp_data->client, &tt, model_zone, param ? icalparameter_get_tzid (param) : NULL);
2673 if (prop) {
2674 set_func (prop, tt);
2675 } else {
2676 prop = new_func (tt);
2677 icalcomponent_add_property (comp_data->icalcomp, prop);
2680 if (param) {
2681 const gchar *tzid = icalparameter_get_tzid (param);
2683 /* If the TZID is set to "UTC", we don't want to save the TZID. */
2684 if (!tzid || !*tzid || !strcmp (tzid, "UTC")) {
2685 icalproperty_remove_parameter_by_kind (prop, ICAL_TZID_PARAMETER);
2687 } else if (model_zone) {
2688 const gchar *tzid = icaltimezone_get_tzid (model_zone);
2690 if (tzid && *tzid) {
2691 param = icalparameter_new_tzid (tzid);
2692 icalproperty_add_parameter (prop, param);
2698 * e_cal_model_test_row_editable
2699 * @model: an #ECalModel
2700 * @row: Row of our interest. -1 is editable only when default client is
2701 * editable.
2703 * Checks if component at @row is editable or not. It doesn't check bounds
2704 * for @row.
2706 * Returns: Whether @row is editable or not.
2708 gboolean
2709 e_cal_model_test_row_editable (ECalModel *model,
2710 gint row)
2712 gboolean readonly = FALSE;
2713 ECalClient *client = NULL;
2715 if (row != -1) {
2716 ECalModelComponent *comp_data;
2718 comp_data = e_cal_model_get_component_at (model, row);
2720 if (comp_data != NULL && comp_data->client != NULL)
2721 client = g_object_ref (comp_data->client);
2723 readonly = (client == NULL);
2724 } else {
2725 const gchar *source_uid;
2727 source_uid = e_cal_model_get_default_source_uid (model);
2729 /* if the source cannot be opened, then expect the client being writable;
2730 there will be shown an error if not, when saving changes anyway */
2731 readonly = source_uid == NULL;
2733 if (source_uid != NULL) {
2734 ESourceRegistry *registry = e_cal_model_get_registry (model);
2735 EClientCache *client_cache = e_cal_model_get_client_cache (model);
2736 ESource *source;
2738 source = e_source_registry_ref_source (registry, source_uid);
2739 if (source) {
2740 EClient *e_client;
2742 e_client = e_client_cache_ref_cached_client (client_cache, source,
2743 cal_model_kind_to_extension_name (model));
2744 if (e_client) {
2745 client = E_CAL_CLIENT (e_client);
2746 } else {
2747 const gchar *parent_uid = e_source_get_parent (source);
2749 /* There are couple known to be always read-only */
2750 readonly = g_strcmp0 (parent_uid, "webcal-stub") == 0 ||
2751 g_strcmp0 (parent_uid, "weather-stub") == 0 ||
2752 g_strcmp0 (parent_uid, "contacts-stub") == 0;
2756 g_clear_object (&source);
2760 if (!readonly && client)
2761 readonly = e_client_is_readonly (E_CLIENT (client));
2763 g_clear_object (&client);
2765 return !readonly;
2768 ESourceRegistry *
2769 e_cal_model_get_registry (ECalModel *model)
2771 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2773 return model->priv->registry;
2776 EShell *
2777 e_cal_model_get_shell (ECalModel *model)
2779 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2781 return model->priv->shell;
2784 ECalDataModel *
2785 e_cal_model_get_data_model (ECalModel *model)
2787 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2789 return model->priv->data_model;
2792 EClientCache *
2793 e_cal_model_get_client_cache (ECalModel *model)
2795 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2797 return model->priv->client_cache;
2800 gboolean
2801 e_cal_model_get_confirm_delete (ECalModel *model)
2803 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2805 return model->priv->confirm_delete;
2808 void
2809 e_cal_model_set_confirm_delete (ECalModel *model,
2810 gboolean confirm_delete)
2812 g_return_if_fail (E_IS_CAL_MODEL (model));
2814 if (model->priv->confirm_delete == confirm_delete)
2815 return;
2817 model->priv->confirm_delete = confirm_delete;
2819 g_object_notify (G_OBJECT (model), "confirm-delete");
2822 icalcomponent_kind
2823 e_cal_model_get_component_kind (ECalModel *model)
2825 g_return_val_if_fail (E_IS_CAL_MODEL (model), ICAL_NO_COMPONENT);
2827 return model->priv->kind;
2830 void
2831 e_cal_model_set_component_kind (ECalModel *model,
2832 icalcomponent_kind kind)
2834 g_return_if_fail (E_IS_CAL_MODEL (model));
2836 model->priv->kind = kind;
2839 icaltimezone *
2840 e_cal_model_get_timezone (ECalModel *model)
2842 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2844 return model->priv->zone;
2847 void
2848 e_cal_model_set_timezone (ECalModel *model,
2849 icaltimezone *zone)
2851 icaltimezone *old_zone;
2852 g_return_if_fail (E_IS_CAL_MODEL (model));
2854 if (model->priv->zone == zone)
2855 return;
2857 e_table_model_pre_change (E_TABLE_MODEL (model));
2858 old_zone = model->priv->zone;
2859 model->priv->zone = zone;
2861 /* the timezone affects the times shown for date fields,
2862 * so we need to redisplay everything */
2863 e_table_model_changed (E_TABLE_MODEL (model));
2865 g_object_notify (G_OBJECT (model), "timezone");
2866 g_signal_emit (
2867 model, signals[TIMEZONE_CHANGED], 0,
2868 old_zone, zone);
2871 gboolean
2872 e_cal_model_get_compress_weekend (ECalModel *model)
2874 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2876 return model->priv->compress_weekend;
2879 void
2880 e_cal_model_set_compress_weekend (ECalModel *model,
2881 gboolean compress_weekend)
2883 g_return_if_fail (E_IS_CAL_MODEL (model));
2885 if (model->priv->compress_weekend == compress_weekend)
2886 return;
2888 model->priv->compress_weekend = compress_weekend;
2890 g_object_notify (G_OBJECT (model), "compress-weekend");
2893 void
2894 e_cal_model_set_default_category (ECalModel *model,
2895 const gchar *default_category)
2897 g_return_if_fail (E_IS_CAL_MODEL (model));
2899 g_free (model->priv->default_category);
2900 model->priv->default_category = g_strdup (default_category);
2903 gint
2904 e_cal_model_get_default_reminder_interval (ECalModel *model)
2906 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
2908 return model->priv->default_reminder_interval;
2911 void
2912 e_cal_model_set_default_reminder_interval (ECalModel *model,
2913 gint default_reminder_interval)
2915 g_return_if_fail (E_IS_CAL_MODEL (model));
2917 if (model->priv->default_reminder_interval == default_reminder_interval)
2918 return;
2920 model->priv->default_reminder_interval = default_reminder_interval;
2922 g_object_notify (G_OBJECT (model), "default-reminder-interval");
2925 EDurationType
2926 e_cal_model_get_default_reminder_units (ECalModel *model)
2928 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
2930 return model->priv->default_reminder_units;
2933 void
2934 e_cal_model_set_default_reminder_units (ECalModel *model,
2935 EDurationType default_reminder_units)
2937 g_return_if_fail (E_IS_CAL_MODEL (model));
2939 if (model->priv->default_reminder_units == default_reminder_units)
2940 return;
2942 model->priv->default_reminder_units = default_reminder_units;
2944 g_object_notify (G_OBJECT (model), "default-reminder-units");
2947 gboolean
2948 e_cal_model_get_use_24_hour_format (ECalModel *model)
2950 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2952 return model->priv->use_24_hour_format;
2955 void
2956 e_cal_model_set_use_24_hour_format (ECalModel *model,
2957 gboolean use_24_hour_format)
2959 g_return_if_fail (E_IS_CAL_MODEL (model));
2961 if (model->priv->use_24_hour_format == use_24_hour_format)
2962 return;
2964 e_table_model_pre_change (E_TABLE_MODEL (model));
2965 model->priv->use_24_hour_format = use_24_hour_format;
2967 /* Get the views to redraw themselves. */
2968 e_table_model_changed (E_TABLE_MODEL (model));
2970 g_object_notify (G_OBJECT (model), "use-24-hour-format");
2973 gboolean
2974 e_cal_model_get_use_default_reminder (ECalModel *model)
2976 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2978 return model->priv->use_default_reminder;
2981 void
2982 e_cal_model_set_use_default_reminder (ECalModel *model,
2983 gboolean use_default_reminder)
2985 g_return_if_fail (E_IS_CAL_MODEL (model));
2987 if (model->priv->use_default_reminder == use_default_reminder)
2988 return;
2990 model->priv->use_default_reminder = use_default_reminder;
2992 g_object_notify (G_OBJECT (model), "use-default-reminder");
2995 GDateWeekday
2996 e_cal_model_get_week_start_day (ECalModel *model)
2998 g_return_val_if_fail (E_IS_CAL_MODEL (model), G_DATE_BAD_WEEKDAY);
3000 return model->priv->week_start_day;
3003 void
3004 e_cal_model_set_week_start_day (ECalModel *model,
3005 GDateWeekday week_start_day)
3007 g_return_if_fail (E_IS_CAL_MODEL (model));
3008 g_return_if_fail (g_date_valid_weekday (week_start_day));
3010 if (model->priv->week_start_day == week_start_day)
3011 return;
3013 model->priv->week_start_day = week_start_day;
3015 g_object_notify (G_OBJECT (model), "week-start-day");
3018 gboolean
3019 e_cal_model_get_work_day (ECalModel *model,
3020 GDateWeekday weekday)
3022 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
3023 g_return_val_if_fail (g_date_valid_weekday (weekday), FALSE);
3025 return model->priv->work_days[weekday];
3028 void
3029 e_cal_model_set_work_day (ECalModel *model,
3030 GDateWeekday weekday,
3031 gboolean work_day)
3033 const gchar *property_name = NULL;
3035 g_return_if_fail (E_IS_CAL_MODEL (model));
3036 g_return_if_fail (g_date_valid_weekday (weekday));
3038 if (work_day == model->priv->work_days[weekday])
3039 return;
3041 model->priv->work_days[weekday] = work_day;
3043 switch (weekday) {
3044 case G_DATE_MONDAY:
3045 property_name = "work-day-monday";
3046 break;
3047 case G_DATE_TUESDAY:
3048 property_name = "work-day-tuesday";
3049 break;
3050 case G_DATE_WEDNESDAY:
3051 property_name = "work-day-wednesday";
3052 break;
3053 case G_DATE_THURSDAY:
3054 property_name = "work-day-thursday";
3055 break;
3056 case G_DATE_FRIDAY:
3057 property_name = "work-day-friday";
3058 break;
3059 case G_DATE_SATURDAY:
3060 property_name = "work-day-saturday";
3061 break;
3062 case G_DATE_SUNDAY:
3063 property_name = "work-day-sunday";
3064 break;
3065 default:
3066 g_warn_if_reached ();
3069 g_object_notify (G_OBJECT (model), property_name);
3073 * e_cal_model_get_work_day_first:
3074 * @model: an #ECalModel
3076 * Returns the first work day with respect to #ECalModel:work-week-start.
3077 * If no work days are set, the function returns %G_DATE_BAD_WEEKDAY.
3079 * Returns: first work day of the week, or %G_DATE_BAD_WEEKDAY
3081 GDateWeekday
3082 e_cal_model_get_work_day_first (ECalModel *model)
3084 GDateWeekday weekday;
3085 gint ii;
3087 g_return_val_if_fail (E_IS_CAL_MODEL (model), G_DATE_BAD_WEEKDAY);
3089 weekday = e_cal_model_get_week_start_day (model);
3091 for (ii = 0; ii < 7; ii++) {
3092 if (e_cal_model_get_work_day (model, weekday))
3093 return weekday;
3094 weekday = e_weekday_get_next (weekday);
3097 return G_DATE_BAD_WEEKDAY;
3101 * e_cal_model_get_work_day_last:
3102 * @model: an #ECalModel
3104 * Returns the last work day with respect to #ECalModel:work-week-start.
3105 * If no work days are set, the function returns %G_DATE_BAD_WEEKDAY.
3107 * Returns: last work day of the week, or %G_DATE_BAD_WEEKDAY
3109 GDateWeekday
3110 e_cal_model_get_work_day_last (ECalModel *model)
3112 GDateWeekday weekday;
3113 gint ii;
3115 g_return_val_if_fail (E_IS_CAL_MODEL (model), G_DATE_BAD_WEEKDAY);
3117 weekday = e_cal_model_get_week_start_day (model);
3119 for (ii = 0; ii < 7; ii++) {
3120 weekday = e_weekday_get_prev (weekday);
3121 if (e_cal_model_get_work_day (model, weekday))
3122 return weekday;
3125 return G_DATE_BAD_WEEKDAY;
3128 gint
3129 e_cal_model_get_work_day_end_hour (ECalModel *model)
3131 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3133 return model->priv->work_day_end_hour;
3136 void
3137 e_cal_model_set_work_day_end_hour (ECalModel *model,
3138 gint work_day_end_hour)
3140 g_return_if_fail (E_IS_CAL_MODEL (model));
3142 if (model->priv->work_day_end_hour == work_day_end_hour)
3143 return;
3145 model->priv->work_day_end_hour = work_day_end_hour;
3147 g_object_notify (G_OBJECT (model), "work-day-end-hour");
3150 gint
3151 e_cal_model_get_work_day_end_minute (ECalModel *model)
3153 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3155 return model->priv->work_day_end_minute;
3158 void
3159 e_cal_model_set_work_day_end_minute (ECalModel *model,
3160 gint work_day_end_minute)
3162 g_return_if_fail (E_IS_CAL_MODEL (model));
3164 if (model->priv->work_day_end_minute == work_day_end_minute)
3165 return;
3167 model->priv->work_day_end_minute = work_day_end_minute;
3169 g_object_notify (G_OBJECT (model), "work-day-end-minute");
3172 gint
3173 e_cal_model_get_work_day_start_hour (ECalModel *model)
3175 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3177 return model->priv->work_day_start_hour;
3180 void
3181 e_cal_model_set_work_day_start_hour (ECalModel *model,
3182 gint work_day_start_hour)
3184 g_return_if_fail (E_IS_CAL_MODEL (model));
3186 if (model->priv->work_day_start_hour == work_day_start_hour)
3187 return;
3189 model->priv->work_day_start_hour = work_day_start_hour;
3191 g_object_notify (G_OBJECT (model), "work-day-start-hour");
3194 gint
3195 e_cal_model_get_work_day_start_minute (ECalModel *model)
3197 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3199 return model->priv->work_day_start_minute;
3202 void
3203 e_cal_model_set_work_day_start_minute (ECalModel *model,
3204 gint work_day_start_minute)
3206 g_return_if_fail (E_IS_CAL_MODEL (model));
3208 if (model->priv->work_day_start_minute == work_day_start_minute)
3209 return;
3211 model->priv->work_day_start_minute = work_day_start_minute;
3213 g_object_notify (G_OBJECT (model), "work-day-start-minute");
3216 gint
3217 e_cal_model_get_work_day_start_mon (ECalModel *model)
3219 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3221 return model->priv->work_day_start_mon;
3224 void
3225 e_cal_model_set_work_day_start_mon (ECalModel *model,
3226 gint work_day_start)
3228 g_return_if_fail (E_IS_CAL_MODEL (model));
3230 if (model->priv->work_day_start_mon == work_day_start)
3231 return;
3233 model->priv->work_day_start_mon = work_day_start;
3235 g_object_notify (G_OBJECT (model), "work-day-start-mon");
3238 gint
3239 e_cal_model_get_work_day_end_mon (ECalModel *model)
3241 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3243 return model->priv->work_day_end_mon;
3246 void
3247 e_cal_model_set_work_day_end_mon (ECalModel *model,
3248 gint work_day_end)
3250 g_return_if_fail (E_IS_CAL_MODEL (model));
3252 if (model->priv->work_day_end_mon == work_day_end)
3253 return;
3255 model->priv->work_day_end_mon = work_day_end;
3257 g_object_notify (G_OBJECT (model), "work-day-end-mon");
3260 gint
3261 e_cal_model_get_work_day_start_tue (ECalModel *model)
3263 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3265 return model->priv->work_day_start_tue;
3268 void
3269 e_cal_model_set_work_day_start_tue (ECalModel *model,
3270 gint work_day_start)
3272 g_return_if_fail (E_IS_CAL_MODEL (model));
3274 if (model->priv->work_day_start_tue == work_day_start)
3275 return;
3277 model->priv->work_day_start_tue = work_day_start;
3279 g_object_notify (G_OBJECT (model), "work-day-start-tue");
3282 gint
3283 e_cal_model_get_work_day_end_tue (ECalModel *model)
3285 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3287 return model->priv->work_day_end_tue;
3290 void
3291 e_cal_model_set_work_day_end_tue (ECalModel *model,
3292 gint work_day_end)
3294 g_return_if_fail (E_IS_CAL_MODEL (model));
3296 if (model->priv->work_day_end_tue == work_day_end)
3297 return;
3299 model->priv->work_day_end_tue = work_day_end;
3301 g_object_notify (G_OBJECT (model), "work-day-end-tue");
3304 gint
3305 e_cal_model_get_work_day_start_wed (ECalModel *model)
3307 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3309 return model->priv->work_day_start_wed;
3312 void
3313 e_cal_model_set_work_day_start_wed (ECalModel *model,
3314 gint work_day_start)
3316 g_return_if_fail (E_IS_CAL_MODEL (model));
3318 if (model->priv->work_day_start_wed == work_day_start)
3319 return;
3321 model->priv->work_day_start_wed = work_day_start;
3323 g_object_notify (G_OBJECT (model), "work-day-start-wed");
3326 gint
3327 e_cal_model_get_work_day_end_wed (ECalModel *model)
3329 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3331 return model->priv->work_day_end_wed;
3334 void
3335 e_cal_model_set_work_day_end_wed (ECalModel *model,
3336 gint work_day_end)
3338 g_return_if_fail (E_IS_CAL_MODEL (model));
3340 if (model->priv->work_day_end_wed == work_day_end)
3341 return;
3343 model->priv->work_day_end_wed = work_day_end;
3345 g_object_notify (G_OBJECT (model), "work-day-end-wed");
3348 gint
3349 e_cal_model_get_work_day_start_thu (ECalModel *model)
3351 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3353 return model->priv->work_day_start_thu;
3356 void
3357 e_cal_model_set_work_day_start_thu (ECalModel *model,
3358 gint work_day_start)
3360 g_return_if_fail (E_IS_CAL_MODEL (model));
3362 if (model->priv->work_day_start_thu == work_day_start)
3363 return;
3365 model->priv->work_day_start_thu = work_day_start;
3367 g_object_notify (G_OBJECT (model), "work-day-start-thu");
3370 gint
3371 e_cal_model_get_work_day_end_thu (ECalModel *model)
3373 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3375 return model->priv->work_day_end_thu;
3378 void
3379 e_cal_model_set_work_day_end_thu (ECalModel *model,
3380 gint work_day_end)
3382 g_return_if_fail (E_IS_CAL_MODEL (model));
3384 if (model->priv->work_day_end_thu == work_day_end)
3385 return;
3387 model->priv->work_day_end_thu = work_day_end;
3389 g_object_notify (G_OBJECT (model), "work-day-end-thu");
3392 gint
3393 e_cal_model_get_work_day_start_fri (ECalModel *model)
3395 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3397 return model->priv->work_day_start_fri;
3400 void
3401 e_cal_model_set_work_day_start_fri (ECalModel *model,
3402 gint work_day_start)
3404 g_return_if_fail (E_IS_CAL_MODEL (model));
3406 if (model->priv->work_day_start_fri == work_day_start)
3407 return;
3409 model->priv->work_day_start_fri = work_day_start;
3411 g_object_notify (G_OBJECT (model), "work-day-start-fri");
3414 gint
3415 e_cal_model_get_work_day_end_fri (ECalModel *model)
3417 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3419 return model->priv->work_day_end_fri;
3422 void
3423 e_cal_model_set_work_day_end_fri (ECalModel *model,
3424 gint work_day_end)
3426 g_return_if_fail (E_IS_CAL_MODEL (model));
3428 if (model->priv->work_day_end_fri == work_day_end)
3429 return;
3431 model->priv->work_day_end_fri = work_day_end;
3433 g_object_notify (G_OBJECT (model), "work-day-end-fri");
3436 gint
3437 e_cal_model_get_work_day_start_sat (ECalModel *model)
3439 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3441 return model->priv->work_day_start_sat;
3444 void
3445 e_cal_model_set_work_day_start_sat (ECalModel *model,
3446 gint work_day_start)
3448 g_return_if_fail (E_IS_CAL_MODEL (model));
3450 if (model->priv->work_day_start_sat == work_day_start)
3451 return;
3453 model->priv->work_day_start_sat = work_day_start;
3455 g_object_notify (G_OBJECT (model), "work-day-start-sat");
3458 gint
3459 e_cal_model_get_work_day_end_sat (ECalModel *model)
3461 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3463 return model->priv->work_day_end_sat;
3466 void
3467 e_cal_model_set_work_day_end_sat (ECalModel *model,
3468 gint work_day_end)
3470 g_return_if_fail (E_IS_CAL_MODEL (model));
3472 if (model->priv->work_day_end_sat == work_day_end)
3473 return;
3475 model->priv->work_day_end_sat = work_day_end;
3477 g_object_notify (G_OBJECT (model), "work-day-end-sat");
3480 gint
3481 e_cal_model_get_work_day_start_sun (ECalModel *model)
3483 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3485 return model->priv->work_day_start_sun;
3488 void
3489 e_cal_model_set_work_day_start_sun (ECalModel *model,
3490 gint work_day_start)
3492 g_return_if_fail (E_IS_CAL_MODEL (model));
3494 if (model->priv->work_day_start_sun == work_day_start)
3495 return;
3497 model->priv->work_day_start_sun = work_day_start;
3499 g_object_notify (G_OBJECT (model), "work-day-start-sun");
3502 gint
3503 e_cal_model_get_work_day_end_sun (ECalModel *model)
3505 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3507 return model->priv->work_day_end_sun;
3510 void
3511 e_cal_model_set_work_day_end_sun (ECalModel *model,
3512 gint work_day_end)
3514 g_return_if_fail (E_IS_CAL_MODEL (model));
3516 if (model->priv->work_day_end_sun == work_day_end)
3517 return;
3519 model->priv->work_day_end_sun = work_day_end;
3521 g_object_notify (G_OBJECT (model), "work-day-end-sun");
3524 void
3525 e_cal_model_get_work_day_range_for (ECalModel *model,
3526 GDateWeekday weekday,
3527 gint *start_hour,
3528 gint *start_minute,
3529 gint *end_hour,
3530 gint *end_minute)
3532 gint start_adept = -1, end_adept = -1;
3534 g_return_if_fail (E_IS_CAL_MODEL (model));
3535 g_return_if_fail (start_hour != NULL);
3536 g_return_if_fail (start_minute != NULL);
3537 g_return_if_fail (end_hour != NULL);
3538 g_return_if_fail (end_minute != NULL);
3540 switch (weekday) {
3541 case G_DATE_MONDAY:
3542 start_adept = e_cal_model_get_work_day_start_mon (model);
3543 end_adept = e_cal_model_get_work_day_end_mon (model);
3544 break;
3545 case G_DATE_TUESDAY:
3546 start_adept = e_cal_model_get_work_day_start_tue (model);
3547 end_adept = e_cal_model_get_work_day_end_tue (model);
3548 break;
3549 case G_DATE_WEDNESDAY:
3550 start_adept = e_cal_model_get_work_day_start_wed (model);
3551 end_adept = e_cal_model_get_work_day_end_wed (model);
3552 break;
3553 case G_DATE_THURSDAY:
3554 start_adept = e_cal_model_get_work_day_start_thu (model);
3555 end_adept = e_cal_model_get_work_day_end_thu (model);
3556 break;
3557 case G_DATE_FRIDAY:
3558 start_adept = e_cal_model_get_work_day_start_fri (model);
3559 end_adept = e_cal_model_get_work_day_end_fri (model);
3560 break;
3561 case G_DATE_SATURDAY:
3562 start_adept = e_cal_model_get_work_day_start_sat (model);
3563 end_adept = e_cal_model_get_work_day_end_sat (model);
3564 break;
3565 case G_DATE_SUNDAY:
3566 start_adept = e_cal_model_get_work_day_start_sun (model);
3567 end_adept = e_cal_model_get_work_day_end_sun (model);
3568 break;
3569 default:
3570 break;
3573 if (start_adept > 0 && (start_adept / 100) >= 0 && (start_adept / 100) <= 23 &&
3574 (start_adept % 100) >= 0 && (start_adept % 100) <= 59) {
3575 *start_hour = start_adept / 100;
3576 *start_minute = start_adept % 100;
3577 } else {
3578 *start_hour = e_cal_model_get_work_day_start_hour (model);
3579 *start_minute = e_cal_model_get_work_day_start_minute (model);
3582 if (end_adept > 0 && (end_adept / 100) >= 0 && (end_adept / 100) <= 23 &&
3583 (end_adept % 100) >= 0 && (end_adept % 100) <= 59) {
3584 *end_hour = end_adept / 100;
3585 *end_minute = end_adept % 100;
3586 } else {
3587 *end_hour = e_cal_model_get_work_day_end_hour (model);
3588 *end_minute = e_cal_model_get_work_day_end_minute (model);
3592 const gchar *
3593 e_cal_model_get_default_source_uid (ECalModel *model)
3595 g_return_val_if_fail (model != NULL, NULL);
3596 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3598 if (model->priv->default_source_uid && !*model->priv->default_source_uid)
3599 return NULL;
3601 return model->priv->default_source_uid;
3604 void
3605 e_cal_model_set_default_source_uid (ECalModel *model,
3606 const gchar *source_uid)
3608 g_return_if_fail (E_IS_CAL_MODEL (model));
3610 if (g_strcmp0 (model->priv->default_source_uid, source_uid) == 0)
3611 return;
3613 g_free (model->priv->default_source_uid);
3614 model->priv->default_source_uid = g_strdup (source_uid);
3616 g_object_notify (G_OBJECT (model), "default-source-uid");
3619 static ECalModelComponent *
3620 search_by_id_and_client (ECalModelPrivate *priv,
3621 ECalClient *client,
3622 const ECalComponentId *id)
3624 gint i;
3626 for (i = 0; i < priv->objects->len; i++) {
3627 ECalModelComponent *comp_data = g_ptr_array_index (priv->objects, i);
3629 if (comp_data) {
3630 const gchar *uid;
3631 gchar *rid = NULL;
3632 struct icaltimetype icalrid;
3633 gboolean has_rid = (id->rid && *id->rid);
3635 uid = icalcomponent_get_uid (comp_data->icalcomp);
3636 icalrid = icalcomponent_get_recurrenceid (comp_data->icalcomp);
3637 if (!icaltime_is_null_time (icalrid))
3638 rid = icaltime_as_ical_string_r (icalrid);
3640 if (uid && *uid) {
3641 if ((!client || comp_data->client == client) && !strcmp (id->uid, uid)) {
3642 if (has_rid) {
3643 if (!(rid && *rid && !strcmp (rid, id->rid))) {
3644 g_free (rid);
3645 continue;
3648 g_free (rid);
3649 return comp_data;
3653 g_free (rid);
3657 return NULL;
3660 void
3661 e_cal_model_remove_all_objects (ECalModel *model)
3663 ECalModelComponent *comp_data;
3664 ETableModel *table_model;
3665 GSList *link;
3666 gint index;
3668 table_model = E_TABLE_MODEL (model);
3669 for (index = model->priv->objects->len - 1; index >= 0; index--) {
3670 e_table_model_pre_change (table_model);
3672 comp_data = g_ptr_array_remove_index (model->priv->objects, index);
3673 if (!comp_data) {
3674 e_table_model_no_change (table_model);
3675 continue;
3678 link = g_slist_append (NULL, comp_data);
3679 g_signal_emit (model, signals[COMPS_DELETED], 0, link);
3681 g_slist_free (link);
3682 g_object_unref (comp_data);
3684 e_table_model_row_deleted (table_model, index);
3688 void
3689 e_cal_model_get_time_range (ECalModel *model,
3690 time_t *start,
3691 time_t *end)
3693 ECalModelPrivate *priv;
3695 g_return_if_fail (model != NULL);
3696 g_return_if_fail (E_IS_CAL_MODEL (model));
3698 priv = model->priv;
3700 if (start)
3701 *start = priv->start;
3703 if (end)
3704 *end = priv->end;
3707 void
3708 e_cal_model_set_time_range (ECalModel *model,
3709 time_t start,
3710 time_t end)
3712 ECalModelPrivate *priv;
3713 ECalDataModelSubscriber *subscriber;
3715 g_return_if_fail (model != NULL);
3716 g_return_if_fail (E_IS_CAL_MODEL (model));
3717 g_return_if_fail (start >= 0 && end >= 0);
3718 g_return_if_fail (start <= end);
3720 priv = model->priv;
3722 if (start != (time_t) 0 && end != (time_t) 0) {
3723 end = time_day_end_with_zone (end, priv->zone) - 1;
3726 if (priv->start == start && priv->end == end)
3727 return;
3729 subscriber = E_CAL_DATA_MODEL_SUBSCRIBER (model);
3730 priv->start = start;
3731 priv->end = end;
3733 g_signal_emit (model, signals[TIME_RANGE_CHANGED], 0, (gint64) start, (gint64) end);
3735 e_cal_data_model_unsubscribe (model->priv->data_model, subscriber);
3736 e_cal_model_remove_all_objects (model);
3737 e_cal_data_model_subscribe (model->priv->data_model, subscriber, start, end);
3741 * e_cal_model_create_component_with_defaults_sync
3743 icalcomponent *
3744 e_cal_model_create_component_with_defaults_sync (ECalModel *model,
3745 ECalClient *client,
3746 gboolean all_day,
3747 GCancellable *cancellable,
3748 GError **error)
3750 ECalComponent *comp = NULL;
3751 icalcomponent *icalcomp;
3753 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3755 if (client) {
3756 switch (model->priv->kind) {
3757 case ICAL_VEVENT_COMPONENT :
3758 comp = cal_comp_event_new_with_defaults_sync (
3759 client, all_day,
3760 e_cal_model_get_use_default_reminder (model),
3761 e_cal_model_get_default_reminder_interval (model),
3762 e_cal_model_get_default_reminder_units (model),
3763 cancellable, error);
3764 break;
3765 case ICAL_VTODO_COMPONENT :
3766 comp = cal_comp_task_new_with_defaults_sync (client, cancellable, error);
3767 break;
3768 case ICAL_VJOURNAL_COMPONENT :
3769 comp = cal_comp_memo_new_with_defaults_sync (client, cancellable, error);
3770 break;
3771 default:
3772 g_warn_if_reached ();
3773 return NULL;
3777 if (comp) {
3778 icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
3779 g_object_unref (comp);
3780 } else {
3781 icalcomp = icalcomponent_new (model->priv->kind);
3784 /* make sure the component has a UID */
3785 if (!icalcomponent_get_uid (icalcomp)) {
3786 gchar *uid;
3788 uid = e_util_generate_uid ();
3789 icalcomponent_set_uid (icalcomp, uid);
3791 g_free (uid);
3794 return icalcomp;
3798 * Returns information about attendees in the component.
3799 * If there are no attendees, the function returns NULL.
3801 * The information is like "Status: Accepted: X Declined: Y ...".
3803 * Free returned pointer with g_free.
3805 gchar *
3806 e_cal_model_get_attendees_status_info (ECalModel *model,
3807 ECalComponent *comp,
3808 ECalClient *cal_client)
3810 struct _values {
3811 icalparameter_partstat status;
3812 const gchar *caption;
3813 gint count;
3814 } values[] = {
3815 { ICAL_PARTSTAT_ACCEPTED, N_("Accepted"), 0 },
3816 { ICAL_PARTSTAT_DECLINED, N_("Declined"), 0 },
3817 { ICAL_PARTSTAT_TENTATIVE, N_("Tentative"), 0 },
3818 { ICAL_PARTSTAT_DELEGATED, N_("Delegated"), 0 },
3819 { ICAL_PARTSTAT_NEEDSACTION, N_("Needs action"), 0 },
3820 { ICAL_PARTSTAT_NONE, N_("Other"), 0 },
3821 { ICAL_PARTSTAT_X, NULL, -1 }
3824 ESourceRegistry *registry;
3825 GSList *attendees = NULL, *a;
3826 gboolean have = FALSE;
3827 gchar *res = NULL;
3828 gint i;
3830 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3832 registry = e_cal_model_get_registry (model);
3834 if (!comp || !e_cal_component_has_attendees (comp) ||
3835 !itip_organizer_is_user_ex (registry, comp, cal_client, TRUE))
3836 return NULL;
3838 e_cal_component_get_attendee_list (comp, &attendees);
3840 for (a = attendees; a; a = a->next) {
3841 ECalComponentAttendee *att = a->data;
3843 if (att && att->cutype == ICAL_CUTYPE_INDIVIDUAL &&
3844 (att->role == ICAL_ROLE_CHAIR ||
3845 att->role == ICAL_ROLE_REQPARTICIPANT ||
3846 att->role == ICAL_ROLE_OPTPARTICIPANT)) {
3847 have = TRUE;
3849 for (i = 0; values[i].count != -1; i++) {
3850 if (att->status == values[i].status || values[i].status == ICAL_PARTSTAT_NONE) {
3851 values[i].count++;
3852 break;
3858 if (have) {
3859 GString *str = g_string_new ("");
3861 for (i = 0; values[i].count != -1; i++) {
3862 if (values[i].count > 0) {
3863 if (str->str && *str->str)
3864 g_string_append (str, " ");
3866 g_string_append_printf (str, "%s: %d", _(values[i].caption), values[i].count);
3870 g_string_prepend (str, ": ");
3872 /* To Translators: 'Status' here means the state of the attendees, the resulting string will be in a form:
3873 * Status: Accepted: X Declined: Y ... */
3874 g_string_prepend (str, _("Status"));
3876 res = g_string_free (str, FALSE);
3879 if (attendees)
3880 e_cal_component_free_attendee_list (attendees);
3882 return res;
3886 * e_cal_model_get_color_for_component
3888 const gchar *
3889 e_cal_model_get_color_for_component (ECalModel *model,
3890 ECalModelComponent *comp_data)
3892 ECalModelClass *model_class;
3893 const gchar *color = NULL;
3895 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3896 g_return_val_if_fail (comp_data != NULL, NULL);
3898 model_class = (ECalModelClass *) G_OBJECT_GET_CLASS (model);
3899 if (model_class->get_color_for_component != NULL)
3900 color = model_class->get_color_for_component (model, comp_data);
3902 if (!color)
3903 color = cal_model_get_color_for_component (model, comp_data);
3905 return color;
3908 gboolean
3909 e_cal_model_get_rgba_for_component (ECalModel *model,
3910 ECalModelComponent *comp_data,
3911 GdkRGBA *rgba)
3913 const gchar *color;
3915 color = e_cal_model_get_color_for_component (model, comp_data);
3916 if (!color)
3917 return FALSE;
3919 return gdk_rgba_parse (rgba, color);
3923 * e_cal_model_get_rgb_color_for_component:
3925 * Deprecated: 3.20: Use e_cal_model_get_rgba_for_component() instead
3927 gboolean
3928 e_cal_model_get_rgb_color_for_component (ECalModel *model,
3929 ECalModelComponent *comp_data,
3930 gdouble *red,
3931 gdouble *green,
3932 gdouble *blue)
3934 GdkRGBA rgba;
3936 if (!e_cal_model_get_rgba_for_component (model, comp_data, &rgba))
3937 return FALSE;
3939 if (red)
3940 *red = rgba.red;
3941 if (green)
3942 *green = rgba.green;
3943 if (blue)
3944 *blue = rgba.blue;
3946 return TRUE;
3950 * e_cal_model_get_component_at
3952 ECalModelComponent *
3953 e_cal_model_get_component_at (ECalModel *model,
3954 gint row)
3956 ECalModelPrivate *priv;
3958 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3960 priv = model->priv;
3962 g_return_val_if_fail (row >= 0 && row < priv->objects->len, NULL);
3964 return g_ptr_array_index (priv->objects, row);
3967 ECalModelComponent *
3968 e_cal_model_get_component_for_client_and_uid (ECalModel *model,
3969 ECalClient *client,
3970 const ECalComponentId *id)
3972 ECalModelPrivate *priv;
3974 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3976 priv = model->priv;
3978 return search_by_id_and_client (priv, client, id);
3982 * e_cal_model_date_value_to_string
3984 gchar *
3985 e_cal_model_date_value_to_string (ECalModel *model,
3986 gconstpointer value)
3988 ECalModelPrivate *priv;
3989 ECellDateEditValue *dv = (ECellDateEditValue *) value;
3990 struct icaltimetype tt;
3991 struct tm tmp_tm;
3992 gchar buffer[64];
3994 g_return_val_if_fail (E_IS_CAL_MODEL (model), g_strdup (""));
3996 priv = model->priv;
3998 if (!dv)
3999 return g_strdup ("");
4001 /* We currently convert all the dates to the current timezone. */
4002 tt = dv->tt;
4003 icaltimezone_convert_time (&tt, dv->zone, priv->zone);
4005 tmp_tm.tm_year = tt.year - 1900;
4006 tmp_tm.tm_mon = tt.month - 1;
4007 tmp_tm.tm_mday = tt.day;
4008 tmp_tm.tm_hour = tt.hour;
4009 tmp_tm.tm_min = tt.minute;
4010 tmp_tm.tm_sec = tt.second;
4011 tmp_tm.tm_isdst = -1;
4013 tmp_tm.tm_wday = time_day_of_week (tt.day, tt.month - 1, tt.year);
4015 memset (buffer, 0, sizeof (buffer));
4016 e_time_format_date_and_time (&tmp_tm, priv->use_24_hour_format,
4017 TRUE, FALSE,
4018 buffer, sizeof (buffer));
4019 return g_strdup (buffer);
4022 typedef struct _GenerateInstacesData {
4023 ECalModelGenerateInstancesData mdata;
4024 ECalRecurInstanceFn cb;
4025 ECalClient *client;
4026 icaltimezone *zone;
4027 } GenerateInstancesData;
4029 static gboolean
4030 ecm_generate_instances_cb (ECalComponent *comp,
4031 time_t instance_start,
4032 time_t instance_end,
4033 gpointer user_data)
4035 GenerateInstancesData *gid = user_data;
4037 g_return_val_if_fail (gid != NULL, FALSE);
4038 g_return_val_if_fail (gid->mdata.comp_data != NULL, FALSE);
4040 cal_comp_get_instance_times (gid->mdata.comp_data->client, e_cal_component_get_icalcomponent (comp),
4041 gid->zone, &instance_start, NULL, &instance_end, NULL, NULL);
4043 return gid->cb (comp, instance_start, instance_end, &gid->mdata);
4047 * e_cal_model_generate_instances_sync
4049 * cb function is not called with cb_data, but with ECalModelGenerateInstancesData which contains cb_data
4051 void
4052 e_cal_model_generate_instances_sync (ECalModel *model,
4053 time_t start,
4054 time_t end,
4055 ECalRecurInstanceFn cb,
4056 gpointer cb_data)
4058 GenerateInstancesData gid;
4059 gint i, n;
4061 g_return_if_fail (cb != NULL);
4063 gid.mdata.cb_data = cb_data;
4064 gid.cb = cb;
4065 gid.zone = model->priv->zone;
4067 n = e_table_model_row_count (E_TABLE_MODEL (model));
4068 for (i = 0; i < n; i++) {
4069 ECalModelComponent *comp_data = e_cal_model_get_component_at (model, i);
4071 if (comp_data->instance_start < end && comp_data->instance_end > start) {
4072 gid.mdata.comp_data = comp_data;
4074 e_cal_client_generate_instances_for_object_sync (comp_data->client, comp_data->icalcomp, start, end,
4075 ecm_generate_instances_cb, &gid);
4081 * e_cal_model_get_object_array
4083 GPtrArray *
4084 e_cal_model_get_object_array (ECalModel *model)
4086 g_return_val_if_fail (model != NULL, NULL);
4087 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
4088 g_return_val_if_fail (model->priv != NULL, NULL);
4090 return model->priv->objects;
4093 void
4094 e_cal_model_set_instance_times (ECalModelComponent *comp_data,
4095 const icaltimezone *zone)
4097 if (icalcomponent_isa (comp_data->icalcomp) == ICAL_VEVENT_COMPONENT) {
4098 struct icaltimetype start_time, end_time;
4100 start_time = icalcomponent_get_dtstart (comp_data->icalcomp);
4101 end_time = icalcomponent_get_dtend (comp_data->icalcomp);
4103 if (start_time.is_date && icaltime_is_null_time (end_time)) {
4104 /* If end_time is null and it's an all day event,
4105 * just make start_time = end_time so that end_time
4106 * will be a valid date
4108 end_time = start_time;
4109 icaltime_adjust (&end_time, 1, 0, 0, 0);
4110 icalcomponent_set_dtend (comp_data->icalcomp, end_time);
4111 } else if (start_time.is_date && end_time.is_date &&
4112 (icaltime_compare_date_only (start_time, end_time) == 0)) {
4113 /* If both DTSTART and DTEND are DATE values, and they are the
4114 * same day, we add 1 day to DTEND. This means that most
4115 * events created with the old Evolution behavior will still
4116 * work OK. */
4117 icaltime_adjust (&end_time, 1, 0, 0, 0);
4118 icalcomponent_set_dtend (comp_data->icalcomp, end_time);
4122 cal_comp_get_instance_times (comp_data->client, comp_data->icalcomp, zone,
4123 &comp_data->instance_start, NULL, &comp_data->instance_end, NULL, NULL);
4127 * e_cal_model_set_default_time_func:
4128 * This function will be used when creating new item from the "click-to-add",
4129 * when user didn't fill a start date there.
4131 void
4132 e_cal_model_set_default_time_func (ECalModel *model,
4133 ECalModelDefaultTimeFunc func,
4134 gpointer user_data)
4136 g_return_if_fail (E_IS_CAL_MODEL (model));
4138 model->priv->get_default_time = func;
4139 model->priv->get_default_time_user_data = user_data;
4142 void
4143 e_cal_model_modify_component (ECalModel *model,
4144 ECalModelComponent *comp_data,
4145 ECalObjModType mod)
4147 g_return_if_fail (E_IS_CAL_MODEL (model));
4148 g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data));
4150 e_cal_ops_modify_component (model, comp_data->client, comp_data->icalcomp, mod, E_CAL_OPS_SEND_FLAG_ASK);
4153 void
4154 e_cal_model_util_set_value (GHashTable *values,
4155 ETableModel *table_model,
4156 gint column,
4157 gint row)
4159 gpointer value;
4161 g_return_if_fail (values != NULL);
4163 value = e_table_model_value_at (table_model, column, row);
4165 g_hash_table_insert (values, GINT_TO_POINTER (column),
4166 e_table_model_duplicate_value (table_model, column, value));
4169 gpointer
4170 e_cal_model_util_get_value (GHashTable *values,
4171 gint column)
4173 g_return_val_if_fail (values != NULL, NULL);
4175 return g_hash_table_lookup (values, GINT_TO_POINTER (column));
4178 void
4179 e_cal_model_emit_object_created (ECalModel *model,
4180 ECalClient *where)
4182 g_return_if_fail (E_IS_CAL_MODEL (model));
4183 g_return_if_fail (E_IS_CAL_CLIENT (where));
4185 g_signal_emit (model, signals[OBJECT_CREATED], 0, where);
4189 ECellDateEditValue *
4190 e_cal_model_copy_cell_date_value (const ECellDateEditValue *value)
4192 ECellDateEditValue *copy;
4194 if (!value)
4195 return NULL;
4198 copy = g_new0 (ECellDateEditValue, 1);
4199 copy->tt = value->tt;
4200 copy->zone = value->zone;
4202 return copy;