Bug 793125 - Crash due to popup menus left attached too long
[evolution.git] / src / calendar / gui / e-cal-model.c
blob50195b77ee0082d8c6faa0bc8efd04fbda25e247
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 if (priv->zone)
375 icaltimezone_convert_time (&tt_start, zone, priv->zone);
376 } else
377 if (priv->zone)
378 tt_start = icaltime_from_timet_with_zone (comp_data->instance_start, tt_start.is_date, priv->zone);
381 if (!icaltime_is_valid_time (tt_start) || icaltime_is_null_time (tt_start))
382 return NULL;
384 comp_data->dtstart = g_new0 (ECellDateEditValue, 1);
385 comp_data->dtstart->tt = tt_start;
387 if (got_zone)
388 comp_data->dtstart->zone = zone;
389 else
390 comp_data->dtstart->zone = NULL;
393 return e_cal_model_copy_cell_date_value (comp_data->dtstart);
396 static ECellDateEditValue *
397 get_datetime_from_utc (ECalModel *model,
398 ECalModelComponent *comp_data,
399 icalproperty_kind propkind,
400 struct icaltimetype (*get_value) (const icalproperty *prop),
401 ECellDateEditValue **buffer)
403 g_return_val_if_fail (buffer != NULL, NULL);
405 if (!*buffer) {
406 ECalModelPrivate *priv;
407 struct icaltimetype tt_value;
408 icalproperty *prop;
409 ECellDateEditValue *res;
411 priv = model->priv;
413 prop = icalcomponent_get_first_property (comp_data->icalcomp, propkind);
414 if (!prop)
415 return NULL;
417 tt_value = get_value (prop);
419 /* these are always in UTC, thus convert to default zone, if any and done */
420 if (priv->zone)
421 icaltimezone_convert_time (&tt_value, icaltimezone_get_utc_timezone (), priv->zone);
423 if (!icaltime_is_valid_time (tt_value) || icaltime_is_null_time (tt_value))
424 return NULL;
426 res = g_new0 (ECellDateEditValue, 1);
427 res->tt = tt_value;
428 res->zone = NULL;
430 *buffer = res;
433 return e_cal_model_copy_cell_date_value (*buffer);
436 static gpointer
437 get_summary (ECalModelComponent *comp_data)
439 icalproperty *prop;
441 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_SUMMARY_PROPERTY);
442 if (prop)
443 return g_strdup (icalproperty_get_summary (prop));
445 return g_strdup ("");
448 static gchar *
449 get_uid (ECalModelComponent *comp_data)
451 return (gchar *) icalcomponent_get_uid (comp_data->icalcomp);
454 static gchar *
455 get_source_description (ESourceRegistry *registry,
456 ECalModelComponent *comp_data)
458 if (!registry || !comp_data || !comp_data->client)
459 return NULL;
461 return e_util_get_source_full_name (registry, e_client_get_source (E_CLIENT (comp_data->client)));
464 static void
465 set_categories (ECalModelComponent *comp_data,
466 const gchar *value)
468 icalproperty *prop;
470 /* remove all categories first */
471 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CATEGORIES_PROPERTY);
472 while (prop) {
473 icalproperty *to_remove = prop;
474 prop = icalcomponent_get_next_property (comp_data->icalcomp, ICAL_CATEGORIES_PROPERTY);
476 icalcomponent_remove_property (comp_data->icalcomp, to_remove);
477 icalproperty_free (to_remove);
480 if (comp_data->priv->categories_str)
481 g_string_free (comp_data->priv->categories_str, TRUE);
482 comp_data->priv->categories_str = NULL;
484 /* then set a new value; no need to populate categories_str,
485 * it'll be populated on demand (in the get_categories() function)
487 if (value && *value) {
488 prop = icalproperty_new_categories (value);
489 icalcomponent_add_property (comp_data->icalcomp, prop);
493 static void
494 set_classification (ECalModelComponent *comp_data,
495 const gchar *value)
497 icalproperty *prop;
499 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CLASS_PROPERTY);
500 if (!value || !(*value)) {
501 if (prop) {
502 icalcomponent_remove_property (comp_data->icalcomp, prop);
503 icalproperty_free (prop);
505 } else {
506 icalproperty_class ical_class;
508 if (!g_ascii_strcasecmp (value, "PUBLIC"))
509 ical_class = ICAL_CLASS_PUBLIC;
510 else if (!g_ascii_strcasecmp (value, "PRIVATE"))
511 ical_class = ICAL_CLASS_PRIVATE;
512 else if (!g_ascii_strcasecmp (value, "CONFIDENTIAL"))
513 ical_class = ICAL_CLASS_CONFIDENTIAL;
514 else
515 ical_class = ICAL_CLASS_NONE;
517 if (!prop) {
518 prop = icalproperty_new_class (ical_class);
519 icalcomponent_add_property (comp_data->icalcomp, prop);
520 } else
521 icalproperty_set_class (prop, ical_class);
525 static void
526 set_description (ECalModelComponent *comp_data,
527 const gchar *value)
529 icalproperty *prop;
531 /* remove old description(s) */
532 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DESCRIPTION_PROPERTY);
533 while (prop) {
534 icalproperty *next;
536 next = icalcomponent_get_next_property (comp_data->icalcomp, ICAL_DESCRIPTION_PROPERTY);
538 icalcomponent_remove_property (comp_data->icalcomp, prop);
539 icalproperty_free (prop);
541 prop = next;
544 /* now add the new description */
545 if (!value || !(*value))
546 return;
548 prop = icalproperty_new_description (value);
549 icalcomponent_add_property (comp_data->icalcomp, prop);
552 static void
553 set_dtstart (ECalModel *model,
554 ECalModelComponent *comp_data,
555 gconstpointer value)
557 e_cal_model_update_comp_time (
558 model, comp_data, value,
559 ICAL_DTSTART_PROPERTY,
560 icalproperty_set_dtstart,
561 icalproperty_new_dtstart);
564 static void
565 set_summary (ECalModelComponent *comp_data,
566 const gchar *value)
568 icalproperty *prop;
570 prop = icalcomponent_get_first_property (
571 comp_data->icalcomp, ICAL_SUMMARY_PROPERTY);
573 if (string_is_empty (value)) {
574 if (prop) {
575 icalcomponent_remove_property (comp_data->icalcomp, prop);
576 icalproperty_free (prop);
578 } else {
579 if (prop)
580 icalproperty_set_summary (prop, value);
581 else {
582 prop = icalproperty_new_summary (value);
583 icalcomponent_add_property (comp_data->icalcomp, prop);
588 static void
589 datetime_to_zone (ECalClient *client,
590 struct icaltimetype *tt,
591 icaltimezone *tt_zone,
592 const gchar *tzid)
594 icaltimezone *from, *to;
595 const gchar *tt_tzid = NULL;
597 g_return_if_fail (tt != NULL);
599 if (tt_zone)
600 tt_tzid = icaltimezone_get_tzid (tt_zone);
602 if (tt_tzid == NULL || tzid == NULL ||
603 tt_tzid == tzid || g_str_equal (tt_tzid, tzid))
604 return;
606 from = tt_zone;
607 to = icaltimezone_get_builtin_timezone_from_tzid (tzid);
608 if (!to) {
609 /* do not check failure here, maybe the zone is not available there */
610 e_cal_client_get_timezone_sync (client, tzid, &to, NULL, NULL);
613 icaltimezone_convert_time (tt, from, to);
616 static void
617 cal_model_set_data_model (ECalModel *model,
618 ECalDataModel *data_model)
620 g_return_if_fail (E_IS_CAL_DATA_MODEL (data_model));
621 g_return_if_fail (model->priv->data_model == NULL);
623 /* Be aware of a circular dependency, once this @model is subscribed to
624 the @data_model, then the @data_model increases reference count
625 of the @model.
627 model->priv->data_model = g_object_ref (data_model);
630 static void
631 cal_model_set_registry (ECalModel *model,
632 ESourceRegistry *registry)
634 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
635 g_return_if_fail (model->priv->registry == NULL);
637 model->priv->registry = g_object_ref (registry);
640 static void
641 cal_model_set_shell (ECalModel *model,
642 EShell *shell)
644 EClientCache *client_cache;
646 g_return_if_fail (E_IS_SHELL (shell));
647 g_return_if_fail (model->priv->shell == NULL);
649 model->priv->shell = g_object_ref (shell);
651 client_cache = e_shell_get_client_cache (shell);
653 g_return_if_fail (E_IS_CLIENT_CACHE (client_cache));
654 g_return_if_fail (model->priv->client_cache == NULL);
656 model->priv->client_cache = g_object_ref (client_cache);
659 static void
660 cal_model_set_property (GObject *object,
661 guint property_id,
662 const GValue *value,
663 GParamSpec *pspec)
665 switch (property_id) {
666 case PROP_COMPRESS_WEEKEND:
667 e_cal_model_set_compress_weekend (
668 E_CAL_MODEL (object),
669 g_value_get_boolean (value));
670 return;
672 case PROP_CONFIRM_DELETE:
673 e_cal_model_set_confirm_delete (
674 E_CAL_MODEL (object),
675 g_value_get_boolean (value));
676 return;
678 case PROP_DATA_MODEL:
679 cal_model_set_data_model (
680 E_CAL_MODEL (object),
681 g_value_get_object (value));
682 return;
684 case PROP_DEFAULT_SOURCE_UID:
685 e_cal_model_set_default_source_uid (
686 E_CAL_MODEL (object),
687 g_value_get_string (value));
688 return;
690 case PROP_DEFAULT_REMINDER_INTERVAL:
691 e_cal_model_set_default_reminder_interval (
692 E_CAL_MODEL (object),
693 g_value_get_int (value));
694 return;
696 case PROP_DEFAULT_REMINDER_UNITS:
697 e_cal_model_set_default_reminder_units (
698 E_CAL_MODEL (object),
699 g_value_get_enum (value));
700 return;
702 case PROP_REGISTRY:
703 cal_model_set_registry (
704 E_CAL_MODEL (object),
705 g_value_get_object (value));
706 return;
708 case PROP_SHELL:
709 cal_model_set_shell (
710 E_CAL_MODEL (object),
711 g_value_get_object (value));
712 return;
714 case PROP_TIMEZONE:
715 e_cal_model_set_timezone (
716 E_CAL_MODEL (object),
717 g_value_get_pointer (value));
718 return;
720 case PROP_USE_24_HOUR_FORMAT:
721 e_cal_model_set_use_24_hour_format (
722 E_CAL_MODEL (object),
723 g_value_get_boolean (value));
724 return;
726 case PROP_USE_DEFAULT_REMINDER:
727 e_cal_model_set_use_default_reminder (
728 E_CAL_MODEL (object),
729 g_value_get_boolean (value));
730 return;
732 case PROP_WEEK_START_DAY:
733 e_cal_model_set_week_start_day (
734 E_CAL_MODEL (object),
735 g_value_get_enum (value));
736 return;
738 case PROP_WORK_DAY_MONDAY:
739 e_cal_model_set_work_day (
740 E_CAL_MODEL (object),
741 G_DATE_MONDAY,
742 g_value_get_boolean (value));
743 return;
745 case PROP_WORK_DAY_TUESDAY:
746 e_cal_model_set_work_day (
747 E_CAL_MODEL (object),
748 G_DATE_TUESDAY,
749 g_value_get_boolean (value));
750 return;
752 case PROP_WORK_DAY_WEDNESDAY:
753 e_cal_model_set_work_day (
754 E_CAL_MODEL (object),
755 G_DATE_WEDNESDAY,
756 g_value_get_boolean (value));
757 return;
759 case PROP_WORK_DAY_THURSDAY:
760 e_cal_model_set_work_day (
761 E_CAL_MODEL (object),
762 G_DATE_THURSDAY,
763 g_value_get_boolean (value));
764 return;
766 case PROP_WORK_DAY_FRIDAY:
767 e_cal_model_set_work_day (
768 E_CAL_MODEL (object),
769 G_DATE_FRIDAY,
770 g_value_get_boolean (value));
771 return;
773 case PROP_WORK_DAY_SATURDAY:
774 e_cal_model_set_work_day (
775 E_CAL_MODEL (object),
776 G_DATE_SATURDAY,
777 g_value_get_boolean (value));
778 return;
780 case PROP_WORK_DAY_SUNDAY:
781 e_cal_model_set_work_day (
782 E_CAL_MODEL (object),
783 G_DATE_SUNDAY,
784 g_value_get_boolean (value));
785 return;
787 case PROP_WORK_DAY_END_HOUR:
788 e_cal_model_set_work_day_end_hour (
789 E_CAL_MODEL (object),
790 g_value_get_int (value));
791 return;
793 case PROP_WORK_DAY_END_MINUTE:
794 e_cal_model_set_work_day_end_minute (
795 E_CAL_MODEL (object),
796 g_value_get_int (value));
797 return;
799 case PROP_WORK_DAY_START_HOUR:
800 e_cal_model_set_work_day_start_hour (
801 E_CAL_MODEL (object),
802 g_value_get_int (value));
803 return;
805 case PROP_WORK_DAY_START_MINUTE:
806 e_cal_model_set_work_day_start_minute (
807 E_CAL_MODEL (object),
808 g_value_get_int (value));
809 return;
811 case PROP_WORK_DAY_START_MON:
812 e_cal_model_set_work_day_start_mon (
813 E_CAL_MODEL (object),
814 g_value_get_int (value));
815 return;
817 case PROP_WORK_DAY_END_MON:
818 e_cal_model_set_work_day_end_mon (
819 E_CAL_MODEL (object),
820 g_value_get_int (value));
821 return;
823 case PROP_WORK_DAY_START_TUE:
824 e_cal_model_set_work_day_start_tue (
825 E_CAL_MODEL (object),
826 g_value_get_int (value));
827 return;
829 case PROP_WORK_DAY_END_TUE:
830 e_cal_model_set_work_day_end_tue (
831 E_CAL_MODEL (object),
832 g_value_get_int (value));
833 return;
835 case PROP_WORK_DAY_START_WED:
836 e_cal_model_set_work_day_start_wed (
837 E_CAL_MODEL (object),
838 g_value_get_int (value));
839 return;
841 case PROP_WORK_DAY_END_WED:
842 e_cal_model_set_work_day_end_wed (
843 E_CAL_MODEL (object),
844 g_value_get_int (value));
845 return;
847 case PROP_WORK_DAY_START_THU:
848 e_cal_model_set_work_day_start_thu (
849 E_CAL_MODEL (object),
850 g_value_get_int (value));
851 return;
853 case PROP_WORK_DAY_END_THU:
854 e_cal_model_set_work_day_end_thu (
855 E_CAL_MODEL (object),
856 g_value_get_int (value));
857 return;
859 case PROP_WORK_DAY_START_FRI:
860 e_cal_model_set_work_day_start_fri (
861 E_CAL_MODEL (object),
862 g_value_get_int (value));
863 return;
865 case PROP_WORK_DAY_END_FRI:
866 e_cal_model_set_work_day_end_fri (
867 E_CAL_MODEL (object),
868 g_value_get_int (value));
869 return;
871 case PROP_WORK_DAY_START_SAT:
872 e_cal_model_set_work_day_start_sat (
873 E_CAL_MODEL (object),
874 g_value_get_int (value));
875 return;
877 case PROP_WORK_DAY_END_SAT:
878 e_cal_model_set_work_day_end_sat (
879 E_CAL_MODEL (object),
880 g_value_get_int (value));
881 return;
883 case PROP_WORK_DAY_START_SUN:
884 e_cal_model_set_work_day_start_sun (
885 E_CAL_MODEL (object),
886 g_value_get_int (value));
887 return;
889 case PROP_WORK_DAY_END_SUN:
890 e_cal_model_set_work_day_end_sun (
891 E_CAL_MODEL (object),
892 g_value_get_int (value));
893 return;
896 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
899 static void
900 cal_model_get_property (GObject *object,
901 guint property_id,
902 GValue *value,
903 GParamSpec *pspec)
905 switch (property_id) {
906 case PROP_CLIENT_CACHE:
907 g_value_set_object (
908 value,
909 e_cal_model_get_client_cache (
910 E_CAL_MODEL (object)));
911 return;
913 case PROP_COMPRESS_WEEKEND:
914 g_value_set_boolean (
915 value,
916 e_cal_model_get_compress_weekend (
917 E_CAL_MODEL (object)));
918 return;
920 case PROP_CONFIRM_DELETE:
921 g_value_set_boolean (
922 value,
923 e_cal_model_get_confirm_delete (
924 E_CAL_MODEL (object)));
925 return;
927 case PROP_DATA_MODEL:
928 g_value_set_object (
929 value,
930 e_cal_model_get_data_model (
931 E_CAL_MODEL (object)));
932 return;
934 case PROP_DEFAULT_SOURCE_UID:
935 g_value_set_string (
936 value,
937 e_cal_model_get_default_source_uid (
938 E_CAL_MODEL (object)));
939 return;
941 case PROP_DEFAULT_REMINDER_INTERVAL:
942 g_value_set_int (
943 value,
944 e_cal_model_get_default_reminder_interval (
945 E_CAL_MODEL (object)));
946 return;
948 case PROP_DEFAULT_REMINDER_UNITS:
949 g_value_set_enum (
950 value,
951 e_cal_model_get_default_reminder_units (
952 E_CAL_MODEL (object)));
953 return;
955 case PROP_REGISTRY:
956 g_value_set_object (
957 value,
958 e_cal_model_get_registry (
959 E_CAL_MODEL (object)));
960 return;
962 case PROP_SHELL:
963 g_value_set_object (
964 value,
965 e_cal_model_get_shell (
966 E_CAL_MODEL (object)));
967 return;
969 case PROP_TIMEZONE:
970 g_value_set_pointer (
971 value,
972 e_cal_model_get_timezone (
973 E_CAL_MODEL (object)));
974 return;
976 case PROP_USE_24_HOUR_FORMAT:
977 g_value_set_boolean (
978 value,
979 e_cal_model_get_use_24_hour_format (
980 E_CAL_MODEL (object)));
981 return;
983 case PROP_USE_DEFAULT_REMINDER:
984 g_value_set_boolean (
985 value,
986 e_cal_model_get_use_default_reminder (
987 E_CAL_MODEL (object)));
988 return;
990 case PROP_WEEK_START_DAY:
991 g_value_set_enum (
992 value,
993 e_cal_model_get_week_start_day (
994 E_CAL_MODEL (object)));
995 return;
997 case PROP_WORK_DAY_MONDAY:
998 g_value_set_boolean (
999 value,
1000 e_cal_model_get_work_day (
1001 E_CAL_MODEL (object), G_DATE_MONDAY));
1002 return;
1004 case PROP_WORK_DAY_TUESDAY:
1005 g_value_set_boolean (
1006 value,
1007 e_cal_model_get_work_day (
1008 E_CAL_MODEL (object), G_DATE_TUESDAY));
1009 return;
1011 case PROP_WORK_DAY_WEDNESDAY:
1012 g_value_set_boolean (
1013 value,
1014 e_cal_model_get_work_day (
1015 E_CAL_MODEL (object), G_DATE_WEDNESDAY));
1016 return;
1018 case PROP_WORK_DAY_THURSDAY:
1019 g_value_set_boolean (
1020 value,
1021 e_cal_model_get_work_day (
1022 E_CAL_MODEL (object), G_DATE_THURSDAY));
1023 return;
1025 case PROP_WORK_DAY_FRIDAY:
1026 g_value_set_boolean (
1027 value,
1028 e_cal_model_get_work_day (
1029 E_CAL_MODEL (object), G_DATE_FRIDAY));
1030 return;
1032 case PROP_WORK_DAY_SATURDAY:
1033 g_value_set_boolean (
1034 value,
1035 e_cal_model_get_work_day (
1036 E_CAL_MODEL (object), G_DATE_SATURDAY));
1037 return;
1039 case PROP_WORK_DAY_SUNDAY:
1040 g_value_set_boolean (
1041 value,
1042 e_cal_model_get_work_day (
1043 E_CAL_MODEL (object), G_DATE_SUNDAY));
1044 return;
1046 case PROP_WORK_DAY_END_HOUR:
1047 g_value_set_int (
1048 value,
1049 e_cal_model_get_work_day_end_hour (
1050 E_CAL_MODEL (object)));
1051 return;
1053 case PROP_WORK_DAY_END_MINUTE:
1054 g_value_set_int (
1055 value,
1056 e_cal_model_get_work_day_end_minute (
1057 E_CAL_MODEL (object)));
1058 return;
1060 case PROP_WORK_DAY_START_HOUR:
1061 g_value_set_int (
1062 value,
1063 e_cal_model_get_work_day_start_hour (
1064 E_CAL_MODEL (object)));
1065 return;
1067 case PROP_WORK_DAY_START_MINUTE:
1068 g_value_set_int (
1069 value,
1070 e_cal_model_get_work_day_start_minute (
1071 E_CAL_MODEL (object)));
1072 return;
1074 case PROP_WORK_DAY_START_MON:
1075 g_value_set_int (
1076 value,
1077 e_cal_model_get_work_day_start_mon (
1078 E_CAL_MODEL (object)));
1079 return;
1081 case PROP_WORK_DAY_END_MON:
1082 g_value_set_int (
1083 value,
1084 e_cal_model_get_work_day_end_mon (
1085 E_CAL_MODEL (object)));
1086 return;
1088 case PROP_WORK_DAY_START_TUE:
1089 g_value_set_int (
1090 value,
1091 e_cal_model_get_work_day_start_tue (
1092 E_CAL_MODEL (object)));
1093 return;
1095 case PROP_WORK_DAY_END_TUE:
1096 g_value_set_int (
1097 value,
1098 e_cal_model_get_work_day_end_tue (
1099 E_CAL_MODEL (object)));
1100 return;
1102 case PROP_WORK_DAY_START_WED:
1103 g_value_set_int (
1104 value,
1105 e_cal_model_get_work_day_start_wed (
1106 E_CAL_MODEL (object)));
1107 return;
1109 case PROP_WORK_DAY_END_WED:
1110 g_value_set_int (
1111 value,
1112 e_cal_model_get_work_day_end_wed (
1113 E_CAL_MODEL (object)));
1114 return;
1116 case PROP_WORK_DAY_START_THU:
1117 g_value_set_int (
1118 value,
1119 e_cal_model_get_work_day_start_thu (
1120 E_CAL_MODEL (object)));
1121 return;
1123 case PROP_WORK_DAY_END_THU:
1124 g_value_set_int (
1125 value,
1126 e_cal_model_get_work_day_end_thu (
1127 E_CAL_MODEL (object)));
1128 return;
1130 case PROP_WORK_DAY_START_FRI:
1131 g_value_set_int (
1132 value,
1133 e_cal_model_get_work_day_start_fri (
1134 E_CAL_MODEL (object)));
1135 return;
1137 case PROP_WORK_DAY_END_FRI:
1138 g_value_set_int (
1139 value,
1140 e_cal_model_get_work_day_end_fri (
1141 E_CAL_MODEL (object)));
1142 return;
1144 case PROP_WORK_DAY_START_SAT:
1145 g_value_set_int (
1146 value,
1147 e_cal_model_get_work_day_start_sat (
1148 E_CAL_MODEL (object)));
1149 return;
1151 case PROP_WORK_DAY_END_SAT:
1152 g_value_set_int (
1153 value,
1154 e_cal_model_get_work_day_end_sat (
1155 E_CAL_MODEL (object)));
1156 return;
1158 case PROP_WORK_DAY_START_SUN:
1159 g_value_set_int (
1160 value,
1161 e_cal_model_get_work_day_start_sun (
1162 E_CAL_MODEL (object)));
1163 return;
1165 case PROP_WORK_DAY_END_SUN:
1166 g_value_set_int (
1167 value,
1168 e_cal_model_get_work_day_end_sun (
1169 E_CAL_MODEL (object)));
1170 return;
1173 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1176 static void
1177 cal_model_constructed (GObject *object)
1179 e_extensible_load_extensions (E_EXTENSIBLE (object));
1181 /* Chain up to parent's constructed() method. */
1182 G_OBJECT_CLASS (e_cal_model_parent_class)->constructed (object);
1185 static void
1186 cal_model_dispose (GObject *object)
1188 ECalModelPrivate *priv;
1190 priv = E_CAL_MODEL_GET_PRIVATE (object);
1192 g_clear_object (&priv->data_model);
1193 g_clear_object (&priv->registry);
1194 g_clear_object (&priv->shell);
1195 g_clear_object (&priv->client_cache);
1197 g_free (priv->default_source_uid);
1198 priv->default_source_uid = NULL;
1200 /* Chain up to parent's dispose() method. */
1201 G_OBJECT_CLASS (e_cal_model_parent_class)->dispose (object);
1204 static void
1205 cal_model_finalize (GObject *object)
1207 ECalModelPrivate *priv;
1208 gint ii;
1210 priv = E_CAL_MODEL_GET_PRIVATE (object);
1212 g_free (priv->default_category);
1214 for (ii = 0; ii < priv->objects->len; ii++) {
1215 ECalModelComponent *comp_data;
1217 comp_data = g_ptr_array_index (priv->objects, ii);
1218 if (comp_data == NULL) {
1219 g_warning ("comp_data is null\n");
1220 continue;
1222 g_object_unref (comp_data);
1224 g_ptr_array_free (priv->objects, TRUE);
1226 /* Chain up to parent's finalize() method. */
1227 G_OBJECT_CLASS (e_cal_model_parent_class)->finalize (object);
1230 static const gchar *
1231 cal_model_get_color_for_component (ECalModel *model,
1232 ECalModelComponent *comp_data)
1234 ESource *source;
1235 ESourceSelectable *extension;
1236 const gchar *color_spec;
1237 const gchar *extension_name;
1238 const gchar *uid;
1239 gint i, first_empty = 0;
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 switch (e_cal_client_get_source_type (comp_data->client)) {
1257 case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
1258 extension_name = E_SOURCE_EXTENSION_CALENDAR;
1259 break;
1260 case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
1261 extension_name = E_SOURCE_EXTENSION_TASK_LIST;
1262 break;
1263 case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
1264 extension_name = E_SOURCE_EXTENSION_MEMO_LIST;
1265 break;
1266 default:
1267 g_return_val_if_reached (NULL);
1270 source = e_client_get_source (E_CLIENT (comp_data->client));
1271 extension = e_source_get_extension (source, extension_name);
1272 color_spec = e_source_selectable_get_color (extension);
1274 if (color_spec != NULL) {
1275 g_free (comp_data->color);
1276 comp_data->color = g_strdup (color_spec);
1277 return comp_data->color;
1280 uid = e_source_get_uid (source);
1282 for (i = 0; i < G_N_ELEMENTS (assigned_colors); i++) {
1283 GList *l;
1285 if (assigned_colors[i].uids == NULL) {
1286 first_empty = i;
1287 continue;
1290 for (l = assigned_colors[i].uids; l != NULL; l = l->next)
1291 if (g_strcmp0 (l->data, uid) == 0)
1292 return assigned_colors[i].color;
1295 /* return the first unused color */
1296 assigned_colors[first_empty].uids = g_list_append (
1297 assigned_colors[first_empty].uids, g_strdup (uid));
1299 return assigned_colors[first_empty].color;
1302 static gint
1303 cal_model_column_count (ETableModel *etm)
1305 return E_CAL_MODEL_FIELD_LAST;
1308 static gint
1309 cal_model_row_count (ETableModel *etm)
1311 ECalModelPrivate *priv;
1312 ECalModel *model = (ECalModel *) etm;
1314 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
1316 priv = model->priv;
1318 return priv->objects->len;
1321 static const gchar *
1322 cal_model_kind_to_extension_name (ECalModel *model)
1324 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1326 switch (model->priv->kind) {
1327 case ICAL_VEVENT_COMPONENT:
1328 return E_SOURCE_EXTENSION_CALENDAR;
1329 case ICAL_VJOURNAL_COMPONENT:
1330 return E_SOURCE_EXTENSION_MEMO_LIST;
1331 case ICAL_VTODO_COMPONENT:
1332 return E_SOURCE_EXTENSION_TASK_LIST;
1333 default:
1334 g_warn_if_reached ();
1335 break;
1338 return NULL;
1341 typedef struct {
1342 ECalModel *model;
1343 ETableModel *table_model;
1344 GHashTable *values;
1345 gboolean success;
1346 } CreateComponentData;
1348 static void
1349 create_component_data_free (gpointer ptr)
1351 CreateComponentData *ccd = ptr;
1353 if (ccd) {
1354 GHashTableIter iter;
1355 gpointer key, value;
1357 g_hash_table_iter_init (&iter, ccd->values);
1358 while (g_hash_table_iter_next (&iter, &key, &value)) {
1359 gint column = GPOINTER_TO_INT (key);
1361 e_table_model_free_value (ccd->table_model, column, value);
1364 if (ccd->success)
1365 g_signal_emit (ccd->model, signals[ROW_APPENDED], 0);
1367 g_clear_object (&ccd->model);
1368 g_clear_object (&ccd->table_model);
1369 g_hash_table_destroy (ccd->values);
1370 g_free (ccd);
1374 static void
1375 cal_model_create_component_from_values_thread (EAlertSinkThreadJobData *job_data,
1376 gpointer user_data,
1377 GCancellable *cancellable,
1378 GError **error)
1380 CreateComponentData *ccd = user_data;
1381 EClientCache *client_cache;
1382 ESourceRegistry *registry;
1383 ESource *source;
1384 EClient *client;
1385 ECalModelComponent *comp_data;
1386 icalproperty *prop;
1387 const gchar *source_uid;
1388 gchar *display_name;
1389 GError *local_error = NULL;
1391 g_return_if_fail (ccd != NULL);
1393 source_uid = e_cal_model_get_default_source_uid (ccd->model);
1394 g_return_if_fail (source_uid != NULL);
1396 client_cache = e_cal_model_get_client_cache (ccd->model);
1397 registry = e_cal_model_get_registry (ccd->model);
1399 source = e_source_registry_ref_source (registry, source_uid);
1400 if (!source) {
1401 g_set_error (&local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
1402 _("Source with UID “%s” not found"), source_uid);
1403 e_alert_sink_thread_job_set_alert_arg_0 (job_data, source_uid);
1404 return;
1407 display_name = e_util_get_source_full_name (registry, source);
1408 e_alert_sink_thread_job_set_alert_arg_0 (job_data, display_name);
1409 g_free (display_name);
1411 client = e_client_cache_get_client_sync (client_cache, source,
1412 cal_model_kind_to_extension_name (ccd->model), (guint32) -1, cancellable, &local_error);
1413 g_clear_object (&source);
1415 if (!client) {
1416 e_util_propagate_open_source_job_error (job_data,
1417 cal_model_kind_to_extension_name (ccd->model), local_error, error);
1418 return;
1421 comp_data = g_object_new (E_TYPE_CAL_MODEL_COMPONENT, NULL);
1422 comp_data->client = g_object_ref (client);
1423 comp_data->icalcomp = e_cal_model_create_component_with_defaults_sync (ccd->model, comp_data->client, FALSE, cancellable, error);
1425 if (comp_data->icalcomp) {
1426 ECalModelClass *model_class;
1427 gchar *uid = NULL;
1428 gpointer dtstart;
1430 /* set values for our fields */
1431 set_categories (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_CATEGORIES));
1432 set_classification (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_CLASSIFICATION));
1433 set_description (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_DESCRIPTION));
1434 set_summary (comp_data, e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_SUMMARY));
1436 dtstart = e_cal_model_util_get_value (ccd->values, E_CAL_MODEL_FIELD_DTSTART);
1437 if (dtstart) {
1438 set_dtstart (ccd->model, comp_data, dtstart);
1439 } else if (ccd->model->priv->get_default_time) {
1440 time_t tt = ccd->model->priv->get_default_time (ccd->model, ccd->model->priv->get_default_time_user_data);
1442 if (tt > 0) {
1443 /* Store Memo DTSTART as date, not as date-time */
1444 struct icaltimetype itt = icaltime_from_timet_with_zone (tt,
1445 icalcomponent_isa (comp_data->icalcomp) == ICAL_VJOURNAL_COMPONENT, e_cal_model_get_timezone (ccd->model));
1446 icalproperty *prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DTSTART_PROPERTY);
1448 if (prop) {
1449 icalproperty_set_dtstart (prop, itt);
1450 } else {
1451 prop = icalproperty_new_dtstart (itt);
1452 icalcomponent_add_property (comp_data->icalcomp, prop);
1457 /* call the class' method for filling the component */
1458 model_class = E_CAL_MODEL_GET_CLASS (ccd->model);
1459 if (model_class->fill_component_from_values != NULL) {
1460 model_class->fill_component_from_values (ccd->model, comp_data, ccd->values);
1463 prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CLASS_PROPERTY);
1464 if (!prop || icalproperty_get_class (prop) == ICAL_CLASS_NONE) {
1465 icalproperty_class ical_class = ICAL_CLASS_PUBLIC;
1466 GSettings *settings;
1468 settings = e_util_ref_settings ("org.gnome.evolution.calendar");
1469 if (g_settings_get_boolean (settings, "classify-private"))
1470 ical_class = ICAL_CLASS_PRIVATE;
1471 g_object_unref (settings);
1473 if (!prop) {
1474 prop = icalproperty_new_class (ical_class);
1475 icalcomponent_add_property (comp_data->icalcomp, prop);
1476 } else
1477 icalproperty_set_class (prop, ical_class);
1480 ccd->success = e_cal_client_create_object_sync (comp_data->client, comp_data->icalcomp, &uid, cancellable, error);
1482 g_free (uid);
1485 g_object_unref (comp_data);
1486 g_object_unref (client);
1489 static void
1490 cal_model_append_row (ETableModel *etm,
1491 ETableModel *source,
1492 gint row)
1494 ECalModelClass *model_class;
1495 ECalModel *model = (ECalModel *) etm;
1496 GHashTable *values;
1497 GCancellable *cancellable;
1498 CreateComponentData *ccd;
1499 const gchar *description;
1500 const gchar *alert_ident;
1502 g_return_if_fail (E_IS_CAL_MODEL (model));
1503 g_return_if_fail (E_IS_TABLE_MODEL (source));
1505 switch (e_cal_model_get_component_kind (model)) {
1506 case ICAL_VEVENT_COMPONENT:
1507 description = _("Creating an event");
1508 alert_ident = "calendar:failed-create-event";
1509 break;
1510 case ICAL_VJOURNAL_COMPONENT:
1511 description = _("Creating a memo");
1512 alert_ident = "calendar:failed-create-memo";
1513 break;
1514 case ICAL_VTODO_COMPONENT:
1515 description = _("Creating a task");
1516 alert_ident = "calendar:failed-create-task";
1517 break;
1518 default:
1519 g_warn_if_reached ();
1520 return;
1523 values = g_hash_table_new (g_direct_hash, g_direct_equal);
1525 /* store values for our fields */
1526 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_CATEGORIES, row);
1527 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_CLASSIFICATION, row);
1528 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_DESCRIPTION, row);
1529 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_SUMMARY, row);
1530 e_cal_model_util_set_value (values, source, E_CAL_MODEL_FIELD_DTSTART, row);
1532 /* call the class' method to store other values */
1533 model_class = E_CAL_MODEL_GET_CLASS (model);
1534 if (model_class->store_values_from_model != NULL) {
1535 model_class->store_values_from_model (model, source, row, values);
1538 ccd = g_new0 (CreateComponentData, 1);
1539 ccd->model = g_object_ref (model);
1540 ccd->table_model = g_object_ref (source);
1541 ccd->values = values;
1542 ccd->success = FALSE;
1544 cancellable = e_cal_data_model_submit_thread_job (model->priv->data_model, description,
1545 alert_ident, NULL, cal_model_create_component_from_values_thread,
1546 ccd, create_component_data_free);
1548 g_clear_object (&cancellable);
1551 static gpointer
1552 cal_model_value_at (ETableModel *etm,
1553 gint col,
1554 gint row)
1556 ECalModelPrivate *priv;
1557 ECalModelComponent *comp_data;
1558 ECalModel *model = (ECalModel *) etm;
1559 ESourceRegistry *registry;
1561 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1563 priv = model->priv;
1565 registry = e_cal_model_get_registry (model);
1567 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
1568 g_return_val_if_fail (row >= 0 && row < priv->objects->len, NULL);
1570 comp_data = g_ptr_array_index (priv->objects, row);
1571 g_return_val_if_fail (comp_data != NULL, NULL);
1572 g_return_val_if_fail (comp_data->icalcomp != NULL, NULL);
1574 switch (col) {
1575 case E_CAL_MODEL_FIELD_CATEGORIES :
1576 return get_categories (comp_data);
1577 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1578 return get_classification (comp_data);
1579 case E_CAL_MODEL_FIELD_COLOR :
1580 return (gpointer) get_color (model, comp_data);
1581 case E_CAL_MODEL_FIELD_COMPONENT :
1582 return comp_data->icalcomp;
1583 case E_CAL_MODEL_FIELD_DESCRIPTION :
1584 return get_description (comp_data);
1585 case E_CAL_MODEL_FIELD_DTSTART :
1586 return (gpointer) get_dtstart (model, comp_data);
1587 case E_CAL_MODEL_FIELD_CREATED :
1588 return (gpointer) get_datetime_from_utc (
1589 model, comp_data, ICAL_CREATED_PROPERTY,
1590 icalproperty_get_created, &comp_data->created);
1591 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1592 return (gpointer) get_datetime_from_utc (
1593 model, comp_data, ICAL_LASTMODIFIED_PROPERTY,
1594 icalproperty_get_lastmodified, &comp_data->lastmodified);
1595 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1596 return GINT_TO_POINTER (
1597 icalcomponent_get_first_component (
1598 comp_data->icalcomp,
1599 ICAL_VALARM_COMPONENT) != NULL);
1600 case E_CAL_MODEL_FIELD_ICON :
1602 ECalComponent *comp;
1603 icalcomponent *icalcomp;
1604 gint retval = 0;
1606 comp = e_cal_component_new ();
1607 icalcomp = icalcomponent_new_clone (comp_data->icalcomp);
1608 if (e_cal_component_set_icalcomponent (comp, icalcomp)) {
1609 if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_JOURNAL) {
1610 g_object_unref (comp);
1611 return GINT_TO_POINTER (retval);
1614 if (e_cal_component_has_recurrences (comp))
1615 retval = 1;
1616 else if (itip_organizer_is_user (registry, comp, comp_data->client))
1617 retval = 3;
1618 else {
1619 GSList *attendees = NULL, *sl;
1621 e_cal_component_get_attendee_list (comp, &attendees);
1622 for (sl = attendees; sl != NULL; sl = sl->next) {
1623 ECalComponentAttendee *ca = sl->data;
1624 const gchar *text;
1626 text = itip_strip_mailto (ca->value);
1627 if (itip_address_is_user (registry, text)) {
1628 if (ca->delto != NULL)
1629 retval = 3;
1630 else
1631 retval = 2;
1632 break;
1636 e_cal_component_free_attendee_list (attendees);
1638 } else
1639 icalcomponent_free (icalcomp);
1641 g_object_unref (comp);
1643 return GINT_TO_POINTER (retval);
1645 case E_CAL_MODEL_FIELD_SUMMARY :
1646 return get_summary (comp_data);
1647 case E_CAL_MODEL_FIELD_UID :
1648 return get_uid (comp_data);
1649 case E_CAL_MODEL_FIELD_SOURCE:
1650 return get_source_description (registry, comp_data);
1653 return (gpointer) "";
1656 static void
1657 cal_model_set_value_at (ETableModel *etm,
1658 gint col,
1659 gint row,
1660 gconstpointer value)
1662 ECalModelPrivate *priv;
1663 ECalModelComponent *comp_data;
1664 ECalModel *model = (ECalModel *) etm;
1665 ECalObjModType mod = E_CAL_OBJ_MOD_ALL;
1667 g_return_if_fail (E_IS_CAL_MODEL (model));
1669 priv = model->priv;
1671 g_return_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST);
1672 g_return_if_fail (row >= 0 && row < priv->objects->len);
1674 comp_data = g_ptr_array_index (priv->objects, row);
1675 g_return_if_fail (comp_data != NULL);
1677 switch (col) {
1678 case E_CAL_MODEL_FIELD_CATEGORIES :
1679 set_categories (comp_data, value);
1680 break;
1681 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1682 set_classification (comp_data, value);
1683 break;
1684 case E_CAL_MODEL_FIELD_DESCRIPTION :
1685 set_description (comp_data, value);
1686 break;
1687 case E_CAL_MODEL_FIELD_DTSTART :
1688 set_dtstart (model, comp_data, value);
1689 break;
1690 case E_CAL_MODEL_FIELD_SUMMARY :
1691 set_summary (comp_data, value);
1692 break;
1695 if (!e_cal_dialogs_recur_icalcomp (comp_data->client, comp_data->icalcomp, &mod, NULL, FALSE))
1696 return;
1698 e_cal_ops_modify_component (model, comp_data->client, comp_data->icalcomp, mod, E_CAL_OPS_SEND_FLAG_DONT_SEND);
1701 static gboolean
1702 cal_model_is_cell_editable (ETableModel *etm,
1703 gint col,
1704 gint row)
1706 ECalModelPrivate *priv;
1707 ECalModel *model = (ECalModel *) etm;
1709 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
1711 priv = model->priv;
1713 g_return_val_if_fail (col >= 0 && col <= E_CAL_MODEL_FIELD_LAST, FALSE);
1714 g_return_val_if_fail (row >= -1 || (row >= 0 && row < priv->objects->len), FALSE);
1716 if (!e_cal_model_test_row_editable (E_CAL_MODEL (etm), row))
1717 return FALSE;
1719 switch (col) {
1720 case E_CAL_MODEL_FIELD_CATEGORIES :
1721 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1722 case E_CAL_MODEL_FIELD_DESCRIPTION :
1723 case E_CAL_MODEL_FIELD_DTSTART :
1724 case E_CAL_MODEL_FIELD_SUMMARY :
1725 return TRUE;
1728 return FALSE;
1731 static gpointer
1732 cal_model_duplicate_value (ETableModel *etm,
1733 gint col,
1734 gconstpointer value)
1736 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
1738 switch (col) {
1739 case E_CAL_MODEL_FIELD_CATEGORIES :
1740 case E_CAL_MODEL_FIELD_DESCRIPTION :
1741 case E_CAL_MODEL_FIELD_SUMMARY :
1742 case E_CAL_MODEL_FIELD_SOURCE:
1743 return g_strdup (value);
1744 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1745 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1746 case E_CAL_MODEL_FIELD_ICON :
1747 case E_CAL_MODEL_FIELD_COLOR :
1748 return (gpointer) value;
1749 case E_CAL_MODEL_FIELD_COMPONENT :
1750 return icalcomponent_new_clone ((icalcomponent *) value);
1751 case E_CAL_MODEL_FIELD_DTSTART :
1752 case E_CAL_MODEL_FIELD_CREATED :
1753 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1754 return e_cal_model_copy_cell_date_value (value);
1757 return NULL;
1760 static void
1761 cal_model_free_value (ETableModel *etm,
1762 gint col,
1763 gpointer value)
1765 g_return_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST);
1767 switch (col) {
1768 case E_CAL_MODEL_FIELD_CATEGORIES :
1769 case E_CAL_MODEL_FIELD_DESCRIPTION :
1770 case E_CAL_MODEL_FIELD_SUMMARY :
1771 case E_CAL_MODEL_FIELD_SOURCE:
1772 if (value)
1773 g_free (value);
1774 break;
1775 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1776 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1777 case E_CAL_MODEL_FIELD_ICON :
1778 case E_CAL_MODEL_FIELD_COLOR :
1779 break;
1780 case E_CAL_MODEL_FIELD_DTSTART:
1781 case E_CAL_MODEL_FIELD_CREATED :
1782 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1783 if (value)
1784 g_free (value);
1785 break;
1786 case E_CAL_MODEL_FIELD_COMPONENT :
1787 if (value)
1788 icalcomponent_free ((icalcomponent *) value);
1789 break;
1793 static gpointer
1794 cal_model_initialize_value (ETableModel *etm,
1795 gint col)
1797 ECalModelPrivate *priv;
1798 ECalModel *model = (ECalModel *) etm;
1800 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
1801 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
1803 priv = model->priv;
1805 switch (col) {
1806 case E_CAL_MODEL_FIELD_CATEGORIES :
1807 return g_strdup (priv->default_category ? priv->default_category:"");
1808 case E_CAL_MODEL_FIELD_DESCRIPTION :
1809 case E_CAL_MODEL_FIELD_SUMMARY :
1810 case E_CAL_MODEL_FIELD_SOURCE:
1811 return g_strdup ("");
1812 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1813 case E_CAL_MODEL_FIELD_DTSTART :
1814 case E_CAL_MODEL_FIELD_CREATED :
1815 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1816 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1817 case E_CAL_MODEL_FIELD_ICON :
1818 case E_CAL_MODEL_FIELD_COLOR :
1819 case E_CAL_MODEL_FIELD_COMPONENT :
1820 return NULL;
1823 return NULL;
1826 static gboolean
1827 cal_model_value_is_empty (ETableModel *etm,
1828 gint col,
1829 gconstpointer value)
1831 ECalModelPrivate *priv;
1832 ECalModel *model = (ECalModel *) etm;
1834 g_return_val_if_fail (E_IS_CAL_MODEL (model), TRUE);
1835 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, TRUE);
1837 priv = model->priv;
1839 switch (col) {
1840 case E_CAL_MODEL_FIELD_CATEGORIES :
1841 /* This could be a hack or not. If the categories field only
1842 * contains the default category, then it possibly means that
1843 * the user has not entered anything at all in the click-to-add;
1844 * the category is in the value because we put it there in
1845 * ecm_initialize_value().
1847 if (priv->default_category && value && strcmp (priv->default_category, value) == 0)
1848 return TRUE;
1849 else
1850 return string_is_empty (value);
1851 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1852 case E_CAL_MODEL_FIELD_DESCRIPTION :
1853 case E_CAL_MODEL_FIELD_SUMMARY :
1854 case E_CAL_MODEL_FIELD_SOURCE:
1855 return string_is_empty (value);
1856 case E_CAL_MODEL_FIELD_DTSTART :
1857 case E_CAL_MODEL_FIELD_CREATED :
1858 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1859 return value ? FALSE : TRUE;
1860 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1861 case E_CAL_MODEL_FIELD_ICON :
1862 case E_CAL_MODEL_FIELD_COLOR :
1863 case E_CAL_MODEL_FIELD_COMPONENT :
1864 return TRUE;
1867 return TRUE;
1870 static gchar *
1871 cal_model_value_to_string (ETableModel *etm,
1872 gint col,
1873 gconstpointer value)
1875 g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, g_strdup (""));
1877 switch (col) {
1878 case E_CAL_MODEL_FIELD_CATEGORIES :
1879 case E_CAL_MODEL_FIELD_CLASSIFICATION :
1880 case E_CAL_MODEL_FIELD_DESCRIPTION :
1881 case E_CAL_MODEL_FIELD_SUMMARY :
1882 case E_CAL_MODEL_FIELD_SOURCE:
1883 return g_strdup (value);
1884 case E_CAL_MODEL_FIELD_DTSTART :
1885 case E_CAL_MODEL_FIELD_CREATED :
1886 case E_CAL_MODEL_FIELD_LASTMODIFIED :
1887 return e_cal_model_date_value_to_string (E_CAL_MODEL (etm), value);
1888 case E_CAL_MODEL_FIELD_ICON :
1889 if (GPOINTER_TO_INT (value) == 0)
1890 return g_strdup (_("Normal"));
1891 else if (GPOINTER_TO_INT (value) == 1)
1892 return g_strdup (_("Recurring"));
1893 else
1894 return g_strdup (_("Assigned"));
1895 case E_CAL_MODEL_FIELD_HAS_ALARMS :
1896 return g_strdup (value ? _("Yes") : _("No"));
1897 case E_CAL_MODEL_FIELD_COLOR :
1898 case E_CAL_MODEL_FIELD_COMPONENT :
1899 return g_strdup ("");
1902 return g_strdup ("");
1905 static gint
1906 e_cal_model_get_component_index (ECalModel *model,
1907 ECalClient *client,
1908 const ECalComponentId *id)
1910 gint ii;
1912 for (ii = 0; ii < model->priv->objects->len; ii++) {
1913 ECalModelComponent *comp_data = g_ptr_array_index (model->priv->objects, ii);
1915 if (comp_data) {
1916 const gchar *uid;
1917 gchar *rid = NULL;
1918 struct icaltimetype icalrid;
1919 gboolean has_rid = (id->rid && *id->rid);
1921 uid = icalcomponent_get_uid (comp_data->icalcomp);
1922 icalrid = icalcomponent_get_recurrenceid (comp_data->icalcomp);
1923 if (!icaltime_is_null_time (icalrid))
1924 rid = icaltime_as_ical_string_r (icalrid);
1926 if (uid && *uid) {
1927 if ((!client || comp_data->client == client) && strcmp (id->uid, uid) == 0) {
1928 if (has_rid) {
1929 if (!(rid && *rid && strcmp (rid, id->rid) == 0)) {
1930 g_free (rid);
1931 continue;
1934 g_free (rid);
1935 return ii;
1939 g_free (rid);
1943 return -1;
1946 static void
1947 cal_model_data_subscriber_component_added_or_modified (ECalDataModelSubscriber *subscriber,
1948 ECalClient *client,
1949 ECalComponent *comp,
1950 gboolean is_added)
1952 ECalModel *model;
1953 ECalModelComponent *comp_data;
1954 ETableModel *table_model;
1955 ECalComponentId *id;
1956 icalcomponent *icalcomp;
1957 gint index;
1959 model = E_CAL_MODEL (subscriber);
1961 id = e_cal_component_get_id (comp);
1963 index = e_cal_model_get_component_index (model, client, id);
1965 e_cal_component_free_id (id);
1967 if (index < 0 && !is_added)
1968 return;
1970 table_model = E_TABLE_MODEL (model);
1971 icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
1973 if (index < 0) {
1974 e_table_model_pre_change (table_model);
1976 comp_data = g_object_new (E_TYPE_CAL_MODEL_COMPONENT, NULL);
1977 comp_data->is_new_component = FALSE;
1978 comp_data->client = g_object_ref (client);
1979 comp_data->icalcomp = icalcomp;
1980 e_cal_model_set_instance_times (comp_data, model->priv->zone);
1981 g_ptr_array_add (model->priv->objects, comp_data);
1983 e_table_model_row_inserted (table_model, model->priv->objects->len - 1);
1984 } else {
1985 e_table_model_pre_change (table_model);
1987 comp_data = g_ptr_array_index (model->priv->objects, index);
1988 e_cal_model_component_set_icalcomponent (comp_data, model, icalcomp);
1990 e_table_model_row_changed (table_model, index);
1994 static void
1995 e_cal_model_data_subscriber_component_added (ECalDataModelSubscriber *subscriber,
1996 ECalClient *client,
1997 ECalComponent *comp)
1999 cal_model_data_subscriber_component_added_or_modified (subscriber, client, comp, TRUE);
2002 static void
2003 e_cal_model_data_subscriber_component_modified (ECalDataModelSubscriber *subscriber,
2004 ECalClient *client,
2005 ECalComponent *comp)
2007 cal_model_data_subscriber_component_added_or_modified (subscriber, client, comp, FALSE);
2010 static void
2011 e_cal_model_data_subscriber_component_removed (ECalDataModelSubscriber *subscriber,
2012 ECalClient *client,
2013 const gchar *uid,
2014 const gchar *rid)
2016 ECalModel *model;
2017 ECalModelComponent *comp_data;
2018 ETableModel *table_model;
2019 ECalComponentId id;
2020 GSList *link;
2021 gint index;
2023 model = E_CAL_MODEL (subscriber);
2025 id.uid = (gchar *) uid;
2026 id.rid = (gchar *) rid;
2028 index = e_cal_model_get_component_index (model, client, &id);
2030 if (index < 0)
2031 return;
2033 table_model = E_TABLE_MODEL (model);
2034 e_table_model_pre_change (table_model);
2036 comp_data = g_ptr_array_remove_index (model->priv->objects, index);
2037 if (!comp_data) {
2038 e_table_model_no_change (table_model);
2039 return;
2042 link = g_slist_append (NULL, comp_data);
2043 g_signal_emit (model, signals[COMPS_DELETED], 0, link);
2045 g_slist_free (link);
2046 g_object_unref (comp_data);
2048 e_table_model_row_deleted (table_model, index);
2051 static void
2052 e_cal_model_data_subscriber_freeze (ECalDataModelSubscriber *subscriber)
2054 /* No freeze/thaw, the ETableModel doesn't notify about changes when frozen */
2056 /* ETableModel *table_model = E_TABLE_MODEL (subscriber);
2057 e_table_model_freeze (table_model); */
2060 static void
2061 e_cal_model_data_subscriber_thaw (ECalDataModelSubscriber *subscriber)
2063 /* No freeze/thaw, the ETableModel doesn't notify about changes when frozen */
2065 /* ETableModel *table_model = E_TABLE_MODEL (subscriber);
2066 e_table_model_thaw (table_model); */
2069 static void
2070 e_cal_model_class_init (ECalModelClass *class)
2072 GObjectClass *object_class;
2074 g_type_class_add_private (class, sizeof (ECalModelPrivate));
2076 object_class = G_OBJECT_CLASS (class);
2077 object_class->set_property = cal_model_set_property;
2078 object_class->get_property = cal_model_get_property;
2079 object_class->constructed = cal_model_constructed;
2080 object_class->dispose = cal_model_dispose;
2081 object_class->finalize = cal_model_finalize;
2083 class->get_color_for_component = cal_model_get_color_for_component;
2085 g_object_class_install_property (
2086 object_class,
2087 PROP_DATA_MODEL,
2088 g_param_spec_object (
2089 "data-model",
2090 "Calendar Data Model",
2091 NULL,
2092 E_TYPE_CAL_DATA_MODEL,
2093 G_PARAM_READWRITE |
2094 G_PARAM_CONSTRUCT_ONLY));
2096 g_object_class_install_property (
2097 object_class,
2098 PROP_CLIENT_CACHE,
2099 g_param_spec_object (
2100 "client-cache",
2101 "Client Cache",
2102 NULL,
2103 E_TYPE_CLIENT_CACHE,
2104 G_PARAM_READABLE));
2106 g_object_class_install_property (
2107 object_class,
2108 PROP_COMPRESS_WEEKEND,
2109 g_param_spec_boolean (
2110 "compress-weekend",
2111 "Compress Weekend",
2112 NULL,
2113 FALSE,
2114 G_PARAM_READWRITE));
2116 g_object_class_install_property (
2117 object_class,
2118 PROP_CONFIRM_DELETE,
2119 g_param_spec_boolean (
2120 "confirm-delete",
2121 "Confirm Delete",
2122 NULL,
2123 TRUE,
2124 G_PARAM_READWRITE));
2126 g_object_class_install_property (
2127 object_class,
2128 PROP_DEFAULT_REMINDER_INTERVAL,
2129 g_param_spec_int (
2130 "default-reminder-interval",
2131 "Default Reminder Interval",
2132 NULL,
2133 G_MININT,
2134 G_MAXINT,
2136 G_PARAM_READWRITE));
2138 g_object_class_install_property (
2139 object_class,
2140 PROP_DEFAULT_REMINDER_UNITS,
2141 g_param_spec_enum (
2142 "default-reminder-units",
2143 "Default Reminder Units",
2144 NULL,
2145 E_TYPE_DURATION_TYPE,
2146 E_DURATION_MINUTES,
2147 G_PARAM_READWRITE));
2149 g_object_class_install_property (
2150 object_class,
2151 PROP_DEFAULT_SOURCE_UID,
2152 g_param_spec_string (
2153 "default-source-uid",
2154 "Default source UID of an ECalClient",
2155 NULL,
2156 NULL,
2157 G_PARAM_READWRITE));
2159 g_object_class_install_property (
2160 object_class,
2161 PROP_REGISTRY,
2162 g_param_spec_object (
2163 "registry",
2164 "Registry",
2165 "Data source registry",
2166 E_TYPE_SOURCE_REGISTRY,
2167 G_PARAM_READWRITE |
2168 G_PARAM_CONSTRUCT_ONLY));
2170 g_object_class_install_property (
2171 object_class,
2172 PROP_SHELL,
2173 g_param_spec_object (
2174 "shell",
2175 "Shell",
2176 "EShell",
2177 E_TYPE_SHELL,
2178 G_PARAM_READWRITE |
2179 G_PARAM_CONSTRUCT_ONLY));
2181 g_object_class_install_property (
2182 object_class,
2183 PROP_TIMEZONE,
2184 g_param_spec_pointer (
2185 "timezone",
2186 "Time Zone",
2187 NULL,
2188 G_PARAM_READWRITE));
2190 g_object_class_install_property (
2191 object_class,
2192 PROP_USE_24_HOUR_FORMAT,
2193 g_param_spec_boolean (
2194 "use-24-hour-format",
2195 "Use 24-Hour Format",
2196 NULL,
2197 TRUE,
2198 G_PARAM_READWRITE));
2200 g_object_class_install_property (
2201 object_class,
2202 PROP_USE_DEFAULT_REMINDER,
2203 g_param_spec_boolean (
2204 "use-default-reminder",
2205 "Use Default Reminder",
2206 NULL,
2207 FALSE,
2208 G_PARAM_READWRITE));
2210 g_object_class_install_property (
2211 object_class,
2212 PROP_WEEK_START_DAY,
2213 g_param_spec_enum (
2214 "week-start-day",
2215 "Week Start Day",
2216 NULL,
2217 E_TYPE_DATE_WEEKDAY,
2218 G_DATE_MONDAY,
2219 G_PARAM_READWRITE |
2220 G_PARAM_CONSTRUCT));
2222 g_object_class_install_property (
2223 object_class,
2224 PROP_WORK_DAY_MONDAY,
2225 g_param_spec_boolean (
2226 "work-day-monday",
2227 "Work Day: Monday",
2228 "Whether Monday is a work day",
2229 TRUE,
2230 G_PARAM_READWRITE |
2231 G_PARAM_CONSTRUCT |
2232 G_PARAM_STATIC_STRINGS));
2234 g_object_class_install_property (
2235 object_class,
2236 PROP_WORK_DAY_TUESDAY,
2237 g_param_spec_boolean (
2238 "work-day-tuesday",
2239 "Work Day: Tuesday",
2240 "Whether Tuesday is a work day",
2241 TRUE,
2242 G_PARAM_READWRITE |
2243 G_PARAM_CONSTRUCT |
2244 G_PARAM_STATIC_STRINGS));
2246 g_object_class_install_property (
2247 object_class,
2248 PROP_WORK_DAY_WEDNESDAY,
2249 g_param_spec_boolean (
2250 "work-day-wednesday",
2251 "Work Day: Wednesday",
2252 "Whether Wednesday is a work day",
2253 TRUE,
2254 G_PARAM_READWRITE |
2255 G_PARAM_CONSTRUCT |
2256 G_PARAM_STATIC_STRINGS));
2258 g_object_class_install_property (
2259 object_class,
2260 PROP_WORK_DAY_THURSDAY,
2261 g_param_spec_boolean (
2262 "work-day-thursday",
2263 "Work Day: Thursday",
2264 "Whether Thursday is a work day",
2265 TRUE,
2266 G_PARAM_READWRITE |
2267 G_PARAM_CONSTRUCT |
2268 G_PARAM_STATIC_STRINGS));
2270 g_object_class_install_property (
2271 object_class,
2272 PROP_WORK_DAY_FRIDAY,
2273 g_param_spec_boolean (
2274 "work-day-friday",
2275 "Work Day: Friday",
2276 "Whether Friday is a work day",
2277 TRUE,
2278 G_PARAM_READWRITE |
2279 G_PARAM_CONSTRUCT |
2280 G_PARAM_STATIC_STRINGS));
2282 g_object_class_install_property (
2283 object_class,
2284 PROP_WORK_DAY_SATURDAY,
2285 g_param_spec_boolean (
2286 "work-day-saturday",
2287 "Work Day: Saturday",
2288 "Whether Saturday is a work day",
2289 TRUE,
2290 G_PARAM_READWRITE |
2291 G_PARAM_CONSTRUCT |
2292 G_PARAM_STATIC_STRINGS));
2294 g_object_class_install_property (
2295 object_class,
2296 PROP_WORK_DAY_SUNDAY,
2297 g_param_spec_boolean (
2298 "work-day-sunday",
2299 "Work Day: Sunday",
2300 "Whether Sunday is a work day",
2301 TRUE,
2302 G_PARAM_READWRITE |
2303 G_PARAM_CONSTRUCT |
2304 G_PARAM_STATIC_STRINGS));
2306 g_object_class_install_property (
2307 object_class,
2308 PROP_WORK_DAY_END_HOUR,
2309 g_param_spec_int (
2310 "work-day-end-hour",
2311 "Work Day End Hour",
2312 NULL,
2316 G_PARAM_READWRITE));
2318 g_object_class_install_property (
2319 object_class,
2320 PROP_WORK_DAY_END_MINUTE,
2321 g_param_spec_int (
2322 "work-day-end-minute",
2323 "Work Day End Minute",
2324 NULL,
2328 G_PARAM_READWRITE));
2330 g_object_class_install_property (
2331 object_class,
2332 PROP_WORK_DAY_START_HOUR,
2333 g_param_spec_int (
2334 "work-day-start-hour",
2335 "Work Day Start Hour",
2336 NULL,
2340 G_PARAM_READWRITE));
2342 g_object_class_install_property (
2343 object_class,
2344 PROP_WORK_DAY_START_MINUTE,
2345 g_param_spec_int (
2346 "work-day-start-minute",
2347 "Work Day Start Minute",
2348 NULL,
2352 G_PARAM_READWRITE));
2354 g_object_class_install_property (
2355 object_class,
2356 PROP_WORK_DAY_START_MON,
2357 g_param_spec_int (
2358 "work-day-start-mon",
2359 "Work Day Start for Monday",
2360 NULL,
2362 2359,
2364 G_PARAM_READWRITE));
2366 g_object_class_install_property (
2367 object_class,
2368 PROP_WORK_DAY_END_MON,
2369 g_param_spec_int (
2370 "work-day-end-mon",
2371 "Work Day End for Monday",
2372 NULL,
2374 2359,
2376 G_PARAM_READWRITE));
2378 g_object_class_install_property (
2379 object_class,
2380 PROP_WORK_DAY_START_TUE,
2381 g_param_spec_int (
2382 "work-day-start-tue",
2383 "Work Day Start for Tuesday",
2384 NULL,
2386 2359,
2388 G_PARAM_READWRITE));
2390 g_object_class_install_property (
2391 object_class,
2392 PROP_WORK_DAY_END_TUE,
2393 g_param_spec_int (
2394 "work-day-end-tue",
2395 "Work Day End for Tuesday",
2396 NULL,
2398 2359,
2400 G_PARAM_READWRITE));
2402 g_object_class_install_property (
2403 object_class,
2404 PROP_WORK_DAY_START_WED,
2405 g_param_spec_int (
2406 "work-day-start-wed",
2407 "Work Day Start for Wednesday",
2408 NULL,
2410 2359,
2412 G_PARAM_READWRITE));
2414 g_object_class_install_property (
2415 object_class,
2416 PROP_WORK_DAY_END_WED,
2417 g_param_spec_int (
2418 "work-day-end-wed",
2419 "Work Day End for Wednesday",
2420 NULL,
2422 2359,
2424 G_PARAM_READWRITE));
2426 g_object_class_install_property (
2427 object_class,
2428 PROP_WORK_DAY_START_THU,
2429 g_param_spec_int (
2430 "work-day-start-thu",
2431 "Work Day Start for Thursday",
2432 NULL,
2434 2359,
2436 G_PARAM_READWRITE));
2438 g_object_class_install_property (
2439 object_class,
2440 PROP_WORK_DAY_END_THU,
2441 g_param_spec_int (
2442 "work-day-end-thu",
2443 "Work Day End for Thursday",
2444 NULL,
2446 2359,
2448 G_PARAM_READWRITE));
2450 g_object_class_install_property (
2451 object_class,
2452 PROP_WORK_DAY_START_FRI,
2453 g_param_spec_int (
2454 "work-day-start-fri",
2455 "Work Day Start for Friday",
2456 NULL,
2458 2359,
2460 G_PARAM_READWRITE));
2462 g_object_class_install_property (
2463 object_class,
2464 PROP_WORK_DAY_END_FRI,
2465 g_param_spec_int (
2466 "work-day-end-fri",
2467 "Work Day End for Friday",
2468 NULL,
2470 2359,
2472 G_PARAM_READWRITE));
2474 g_object_class_install_property (
2475 object_class,
2476 PROP_WORK_DAY_START_SAT,
2477 g_param_spec_int (
2478 "work-day-start-sat",
2479 "Work Day Start for Saturday",
2480 NULL,
2482 2359,
2484 G_PARAM_READWRITE));
2486 g_object_class_install_property (
2487 object_class,
2488 PROP_WORK_DAY_END_SAT,
2489 g_param_spec_int (
2490 "work-day-end-sat",
2491 "Work Day End for Saturday",
2492 NULL,
2494 2359,
2496 G_PARAM_READWRITE));
2498 g_object_class_install_property (
2499 object_class,
2500 PROP_WORK_DAY_START_SUN,
2501 g_param_spec_int (
2502 "work-day-start-sun",
2503 "Work Day Start for Sunday",
2504 NULL,
2506 2359,
2508 G_PARAM_READWRITE));
2510 g_object_class_install_property (
2511 object_class,
2512 PROP_WORK_DAY_END_SUN,
2513 g_param_spec_int (
2514 "work-day-end-sun",
2515 "Work Day End for Sunday",
2516 NULL,
2518 2359,
2520 G_PARAM_READWRITE));
2522 signals[TIME_RANGE_CHANGED] = g_signal_new (
2523 "time_range_changed",
2524 G_TYPE_FROM_CLASS (class),
2525 G_SIGNAL_RUN_LAST,
2526 G_STRUCT_OFFSET (ECalModelClass, time_range_changed),
2527 NULL, NULL,
2528 e_marshal_VOID__INT64_INT64,
2529 G_TYPE_NONE, 2,
2530 G_TYPE_INT64,
2531 G_TYPE_INT64);
2533 signals[ROW_APPENDED] = g_signal_new (
2534 "row_appended",
2535 G_TYPE_FROM_CLASS (class),
2536 G_SIGNAL_RUN_LAST,
2537 G_STRUCT_OFFSET (ECalModelClass, row_appended),
2538 NULL, NULL,
2539 g_cclosure_marshal_VOID__VOID,
2540 G_TYPE_NONE, 0);
2542 signals[COMPS_DELETED] = g_signal_new (
2543 "comps_deleted",
2544 G_TYPE_FROM_CLASS (class),
2545 G_SIGNAL_RUN_LAST,
2546 G_STRUCT_OFFSET (ECalModelClass, comps_deleted),
2547 NULL, NULL,
2548 g_cclosure_marshal_VOID__POINTER,
2549 G_TYPE_NONE, 1,
2550 G_TYPE_POINTER);
2552 signals[TIMEZONE_CHANGED] = g_signal_new (
2553 "timezone-changed",
2554 G_TYPE_FROM_CLASS (class),
2555 G_SIGNAL_RUN_LAST,
2556 G_STRUCT_OFFSET (ECalModelClass, timezone_changed),
2557 NULL, NULL,
2558 e_marshal_VOID__POINTER_POINTER,
2559 G_TYPE_NONE, 2,
2560 G_TYPE_POINTER,
2561 G_TYPE_POINTER);
2563 signals[OBJECT_CREATED] = g_signal_new (
2564 "object-created",
2565 G_TYPE_FROM_CLASS (class),
2566 G_SIGNAL_RUN_LAST,
2567 G_STRUCT_OFFSET (ECalModelClass, object_created),
2568 NULL, NULL,
2569 g_cclosure_marshal_VOID__OBJECT,
2570 G_TYPE_NONE, 1, E_TYPE_CAL_CLIENT);
2573 static void
2574 e_cal_model_table_model_init (ETableModelInterface *iface)
2576 iface->column_count = cal_model_column_count;
2577 iface->row_count = cal_model_row_count;
2578 iface->append_row = cal_model_append_row;
2580 iface->value_at = cal_model_value_at;
2581 iface->set_value_at = cal_model_set_value_at;
2582 iface->is_cell_editable = cal_model_is_cell_editable;
2584 iface->duplicate_value = cal_model_duplicate_value;
2585 iface->free_value = cal_model_free_value;
2586 iface->initialize_value = cal_model_initialize_value;
2587 iface->value_is_empty = cal_model_value_is_empty;
2588 iface->value_to_string = cal_model_value_to_string;
2591 static void
2592 e_cal_model_cal_data_model_subscriber_init (ECalDataModelSubscriberInterface *iface)
2594 iface->component_added = e_cal_model_data_subscriber_component_added;
2595 iface->component_modified = e_cal_model_data_subscriber_component_modified;
2596 iface->component_removed = e_cal_model_data_subscriber_component_removed;
2597 iface->freeze = e_cal_model_data_subscriber_freeze;
2598 iface->thaw = e_cal_model_data_subscriber_thaw;
2601 static void
2602 e_cal_model_init (ECalModel *model)
2604 model->priv = E_CAL_MODEL_GET_PRIVATE (model);
2606 /* match none by default */
2607 model->priv->start = (time_t) -1;
2608 model->priv->end = (time_t) -1;
2610 model->priv->objects = g_ptr_array_new ();
2611 model->priv->kind = ICAL_NO_COMPONENT;
2613 model->priv->use_24_hour_format = TRUE;
2616 /* updates time in a component, and keeps the timezone used in it, if exists */
2617 void
2618 e_cal_model_update_comp_time (ECalModel *model,
2619 ECalModelComponent *comp_data,
2620 gconstpointer time_value,
2621 icalproperty_kind kind,
2622 void (*set_func) (icalproperty *prop,
2623 struct icaltimetype v),
2624 icalproperty * (*new_func) (struct icaltimetype v))
2626 ECellDateEditValue *dv = (ECellDateEditValue *) time_value;
2627 icalproperty *prop;
2628 icalparameter *param;
2629 icaltimezone *model_zone;
2630 struct icaltimetype tt;
2632 g_return_if_fail (model != NULL);
2633 g_return_if_fail (comp_data != NULL);
2634 g_return_if_fail (set_func != NULL);
2635 g_return_if_fail (new_func != NULL);
2637 prop = icalcomponent_get_first_property (comp_data->icalcomp, kind);
2638 if (prop)
2639 param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
2640 else
2641 param = NULL;
2643 /* If we are setting the property to NULL (i.e. removing it), then
2644 * we remove it if it exists. */
2645 if (!dv) {
2646 if (prop) {
2647 icalcomponent_remove_property (comp_data->icalcomp, prop);
2648 icalproperty_free (prop);
2651 return;
2654 model_zone = e_cal_model_get_timezone (model);
2655 tt = dv->tt;
2656 datetime_to_zone (comp_data->client, &tt, model_zone, param ? icalparameter_get_tzid (param) : NULL);
2658 if (prop) {
2659 set_func (prop, tt);
2660 } else {
2661 prop = new_func (tt);
2662 icalcomponent_add_property (comp_data->icalcomp, prop);
2665 if (param) {
2666 const gchar *tzid = icalparameter_get_tzid (param);
2668 /* If the TZID is set to "UTC", we don't want to save the TZID. */
2669 if (!tzid || !*tzid || !strcmp (tzid, "UTC")) {
2670 icalproperty_remove_parameter_by_kind (prop, ICAL_TZID_PARAMETER);
2672 } else if (model_zone) {
2673 const gchar *tzid = icaltimezone_get_tzid (model_zone);
2675 if (tzid && *tzid) {
2676 param = icalparameter_new_tzid (tzid);
2677 icalproperty_add_parameter (prop, param);
2683 * e_cal_model_test_row_editable
2684 * @model: an #ECalModel
2685 * @row: Row of our interest. -1 is editable only when default client is
2686 * editable.
2688 * Checks if component at @row is editable or not. It doesn't check bounds
2689 * for @row.
2691 * Returns: Whether @row is editable or not.
2693 gboolean
2694 e_cal_model_test_row_editable (ECalModel *model,
2695 gint row)
2697 gboolean readonly = FALSE;
2698 ECalClient *client = NULL;
2700 if (row != -1) {
2701 ECalModelComponent *comp_data;
2703 comp_data = e_cal_model_get_component_at (model, row);
2705 if (comp_data != NULL && comp_data->client != NULL)
2706 client = g_object_ref (comp_data->client);
2708 readonly = (client == NULL);
2709 } else {
2710 const gchar *source_uid;
2712 source_uid = e_cal_model_get_default_source_uid (model);
2714 /* if the source cannot be opened, then expect the client being writable;
2715 there will be shown an error if not, when saving changes anyway */
2716 readonly = source_uid == NULL;
2718 if (source_uid != NULL) {
2719 ESourceRegistry *registry = e_cal_model_get_registry (model);
2720 EClientCache *client_cache = e_cal_model_get_client_cache (model);
2721 ESource *source;
2723 source = e_source_registry_ref_source (registry, source_uid);
2724 if (source) {
2725 EClient *e_client;
2727 e_client = e_client_cache_ref_cached_client (client_cache, source,
2728 cal_model_kind_to_extension_name (model));
2729 if (e_client) {
2730 client = E_CAL_CLIENT (e_client);
2731 } else {
2732 const gchar *parent_uid = e_source_get_parent (source);
2734 /* There are couple known to be always read-only */
2735 readonly = g_strcmp0 (parent_uid, "webcal-stub") == 0 ||
2736 g_strcmp0 (parent_uid, "weather-stub") == 0 ||
2737 g_strcmp0 (parent_uid, "contacts-stub") == 0;
2741 g_clear_object (&source);
2745 if (!readonly && client)
2746 readonly = e_client_is_readonly (E_CLIENT (client));
2748 g_clear_object (&client);
2750 return !readonly;
2753 ESourceRegistry *
2754 e_cal_model_get_registry (ECalModel *model)
2756 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2758 return model->priv->registry;
2761 EShell *
2762 e_cal_model_get_shell (ECalModel *model)
2764 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2766 return model->priv->shell;
2769 ECalDataModel *
2770 e_cal_model_get_data_model (ECalModel *model)
2772 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2774 return model->priv->data_model;
2777 EClientCache *
2778 e_cal_model_get_client_cache (ECalModel *model)
2780 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2782 return model->priv->client_cache;
2785 gboolean
2786 e_cal_model_get_confirm_delete (ECalModel *model)
2788 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2790 return model->priv->confirm_delete;
2793 void
2794 e_cal_model_set_confirm_delete (ECalModel *model,
2795 gboolean confirm_delete)
2797 g_return_if_fail (E_IS_CAL_MODEL (model));
2799 if (model->priv->confirm_delete == confirm_delete)
2800 return;
2802 model->priv->confirm_delete = confirm_delete;
2804 g_object_notify (G_OBJECT (model), "confirm-delete");
2807 icalcomponent_kind
2808 e_cal_model_get_component_kind (ECalModel *model)
2810 g_return_val_if_fail (E_IS_CAL_MODEL (model), ICAL_NO_COMPONENT);
2812 return model->priv->kind;
2815 void
2816 e_cal_model_set_component_kind (ECalModel *model,
2817 icalcomponent_kind kind)
2819 g_return_if_fail (E_IS_CAL_MODEL (model));
2821 model->priv->kind = kind;
2824 icaltimezone *
2825 e_cal_model_get_timezone (ECalModel *model)
2827 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
2829 return model->priv->zone;
2832 void
2833 e_cal_model_set_timezone (ECalModel *model,
2834 icaltimezone *zone)
2836 icaltimezone *old_zone;
2837 g_return_if_fail (E_IS_CAL_MODEL (model));
2839 if (model->priv->zone == zone)
2840 return;
2842 e_table_model_pre_change (E_TABLE_MODEL (model));
2843 old_zone = model->priv->zone;
2844 model->priv->zone = zone;
2846 /* the timezone affects the times shown for date fields,
2847 * so we need to redisplay everything */
2848 e_table_model_changed (E_TABLE_MODEL (model));
2850 g_object_notify (G_OBJECT (model), "timezone");
2851 g_signal_emit (
2852 model, signals[TIMEZONE_CHANGED], 0,
2853 old_zone, zone);
2856 gboolean
2857 e_cal_model_get_compress_weekend (ECalModel *model)
2859 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2861 return model->priv->compress_weekend;
2864 void
2865 e_cal_model_set_compress_weekend (ECalModel *model,
2866 gboolean compress_weekend)
2868 g_return_if_fail (E_IS_CAL_MODEL (model));
2870 if (model->priv->compress_weekend == compress_weekend)
2871 return;
2873 model->priv->compress_weekend = compress_weekend;
2875 g_object_notify (G_OBJECT (model), "compress-weekend");
2878 void
2879 e_cal_model_set_default_category (ECalModel *model,
2880 const gchar *default_category)
2882 g_return_if_fail (E_IS_CAL_MODEL (model));
2884 g_free (model->priv->default_category);
2885 model->priv->default_category = g_strdup (default_category);
2888 gint
2889 e_cal_model_get_default_reminder_interval (ECalModel *model)
2891 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
2893 return model->priv->default_reminder_interval;
2896 void
2897 e_cal_model_set_default_reminder_interval (ECalModel *model,
2898 gint default_reminder_interval)
2900 g_return_if_fail (E_IS_CAL_MODEL (model));
2902 if (model->priv->default_reminder_interval == default_reminder_interval)
2903 return;
2905 model->priv->default_reminder_interval = default_reminder_interval;
2907 g_object_notify (G_OBJECT (model), "default-reminder-interval");
2910 EDurationType
2911 e_cal_model_get_default_reminder_units (ECalModel *model)
2913 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
2915 return model->priv->default_reminder_units;
2918 void
2919 e_cal_model_set_default_reminder_units (ECalModel *model,
2920 EDurationType default_reminder_units)
2922 g_return_if_fail (E_IS_CAL_MODEL (model));
2924 if (model->priv->default_reminder_units == default_reminder_units)
2925 return;
2927 model->priv->default_reminder_units = default_reminder_units;
2929 g_object_notify (G_OBJECT (model), "default-reminder-units");
2932 gboolean
2933 e_cal_model_get_use_24_hour_format (ECalModel *model)
2935 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2937 return model->priv->use_24_hour_format;
2940 void
2941 e_cal_model_set_use_24_hour_format (ECalModel *model,
2942 gboolean use_24_hour_format)
2944 g_return_if_fail (E_IS_CAL_MODEL (model));
2946 if (model->priv->use_24_hour_format == use_24_hour_format)
2947 return;
2949 e_table_model_pre_change (E_TABLE_MODEL (model));
2950 model->priv->use_24_hour_format = use_24_hour_format;
2952 /* Get the views to redraw themselves. */
2953 e_table_model_changed (E_TABLE_MODEL (model));
2955 g_object_notify (G_OBJECT (model), "use-24-hour-format");
2958 gboolean
2959 e_cal_model_get_use_default_reminder (ECalModel *model)
2961 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
2963 return model->priv->use_default_reminder;
2966 void
2967 e_cal_model_set_use_default_reminder (ECalModel *model,
2968 gboolean use_default_reminder)
2970 g_return_if_fail (E_IS_CAL_MODEL (model));
2972 if (model->priv->use_default_reminder == use_default_reminder)
2973 return;
2975 model->priv->use_default_reminder = use_default_reminder;
2977 g_object_notify (G_OBJECT (model), "use-default-reminder");
2980 GDateWeekday
2981 e_cal_model_get_week_start_day (ECalModel *model)
2983 g_return_val_if_fail (E_IS_CAL_MODEL (model), G_DATE_BAD_WEEKDAY);
2985 return model->priv->week_start_day;
2988 void
2989 e_cal_model_set_week_start_day (ECalModel *model,
2990 GDateWeekday week_start_day)
2992 g_return_if_fail (E_IS_CAL_MODEL (model));
2993 g_return_if_fail (g_date_valid_weekday (week_start_day));
2995 if (model->priv->week_start_day == week_start_day)
2996 return;
2998 model->priv->week_start_day = week_start_day;
3000 g_object_notify (G_OBJECT (model), "week-start-day");
3003 gboolean
3004 e_cal_model_get_work_day (ECalModel *model,
3005 GDateWeekday weekday)
3007 g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
3008 g_return_val_if_fail (g_date_valid_weekday (weekday), FALSE);
3010 return model->priv->work_days[weekday];
3013 void
3014 e_cal_model_set_work_day (ECalModel *model,
3015 GDateWeekday weekday,
3016 gboolean work_day)
3018 const gchar *property_name = NULL;
3020 g_return_if_fail (E_IS_CAL_MODEL (model));
3021 g_return_if_fail (g_date_valid_weekday (weekday));
3023 if (work_day == model->priv->work_days[weekday])
3024 return;
3026 model->priv->work_days[weekday] = work_day;
3028 switch (weekday) {
3029 case G_DATE_MONDAY:
3030 property_name = "work-day-monday";
3031 break;
3032 case G_DATE_TUESDAY:
3033 property_name = "work-day-tuesday";
3034 break;
3035 case G_DATE_WEDNESDAY:
3036 property_name = "work-day-wednesday";
3037 break;
3038 case G_DATE_THURSDAY:
3039 property_name = "work-day-thursday";
3040 break;
3041 case G_DATE_FRIDAY:
3042 property_name = "work-day-friday";
3043 break;
3044 case G_DATE_SATURDAY:
3045 property_name = "work-day-saturday";
3046 break;
3047 case G_DATE_SUNDAY:
3048 property_name = "work-day-sunday";
3049 break;
3050 default:
3051 g_warn_if_reached ();
3054 g_object_notify (G_OBJECT (model), property_name);
3058 * e_cal_model_get_work_day_first:
3059 * @model: an #ECalModel
3061 * Returns the first work day with respect to #ECalModel:work-week-start.
3062 * If no work days are set, the function returns %G_DATE_BAD_WEEKDAY.
3064 * Returns: first work day of the week, or %G_DATE_BAD_WEEKDAY
3066 GDateWeekday
3067 e_cal_model_get_work_day_first (ECalModel *model)
3069 GDateWeekday weekday;
3070 gint ii;
3072 g_return_val_if_fail (E_IS_CAL_MODEL (model), G_DATE_BAD_WEEKDAY);
3074 weekday = e_cal_model_get_week_start_day (model);
3076 for (ii = 0; ii < 7; ii++) {
3077 if (e_cal_model_get_work_day (model, weekday))
3078 return weekday;
3079 weekday = e_weekday_get_next (weekday);
3082 return G_DATE_BAD_WEEKDAY;
3086 * e_cal_model_get_work_day_last:
3087 * @model: an #ECalModel
3089 * Returns the last work day with respect to #ECalModel:work-week-start.
3090 * If no work days are set, the function returns %G_DATE_BAD_WEEKDAY.
3092 * Returns: last work day of the week, or %G_DATE_BAD_WEEKDAY
3094 GDateWeekday
3095 e_cal_model_get_work_day_last (ECalModel *model)
3097 GDateWeekday weekday;
3098 gint ii;
3100 g_return_val_if_fail (E_IS_CAL_MODEL (model), G_DATE_BAD_WEEKDAY);
3102 weekday = e_cal_model_get_week_start_day (model);
3104 for (ii = 0; ii < 7; ii++) {
3105 weekday = e_weekday_get_prev (weekday);
3106 if (e_cal_model_get_work_day (model, weekday))
3107 return weekday;
3110 return G_DATE_BAD_WEEKDAY;
3113 gint
3114 e_cal_model_get_work_day_end_hour (ECalModel *model)
3116 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3118 return model->priv->work_day_end_hour;
3121 void
3122 e_cal_model_set_work_day_end_hour (ECalModel *model,
3123 gint work_day_end_hour)
3125 g_return_if_fail (E_IS_CAL_MODEL (model));
3127 if (model->priv->work_day_end_hour == work_day_end_hour)
3128 return;
3130 model->priv->work_day_end_hour = work_day_end_hour;
3132 g_object_notify (G_OBJECT (model), "work-day-end-hour");
3135 gint
3136 e_cal_model_get_work_day_end_minute (ECalModel *model)
3138 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3140 return model->priv->work_day_end_minute;
3143 void
3144 e_cal_model_set_work_day_end_minute (ECalModel *model,
3145 gint work_day_end_minute)
3147 g_return_if_fail (E_IS_CAL_MODEL (model));
3149 if (model->priv->work_day_end_minute == work_day_end_minute)
3150 return;
3152 model->priv->work_day_end_minute = work_day_end_minute;
3154 g_object_notify (G_OBJECT (model), "work-day-end-minute");
3157 gint
3158 e_cal_model_get_work_day_start_hour (ECalModel *model)
3160 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3162 return model->priv->work_day_start_hour;
3165 void
3166 e_cal_model_set_work_day_start_hour (ECalModel *model,
3167 gint work_day_start_hour)
3169 g_return_if_fail (E_IS_CAL_MODEL (model));
3171 if (model->priv->work_day_start_hour == work_day_start_hour)
3172 return;
3174 model->priv->work_day_start_hour = work_day_start_hour;
3176 g_object_notify (G_OBJECT (model), "work-day-start-hour");
3179 gint
3180 e_cal_model_get_work_day_start_minute (ECalModel *model)
3182 g_return_val_if_fail (E_IS_CAL_MODEL (model), 0);
3184 return model->priv->work_day_start_minute;
3187 void
3188 e_cal_model_set_work_day_start_minute (ECalModel *model,
3189 gint work_day_start_minute)
3191 g_return_if_fail (E_IS_CAL_MODEL (model));
3193 if (model->priv->work_day_start_minute == work_day_start_minute)
3194 return;
3196 model->priv->work_day_start_minute = work_day_start_minute;
3198 g_object_notify (G_OBJECT (model), "work-day-start-minute");
3201 gint
3202 e_cal_model_get_work_day_start_mon (ECalModel *model)
3204 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3206 return model->priv->work_day_start_mon;
3209 void
3210 e_cal_model_set_work_day_start_mon (ECalModel *model,
3211 gint work_day_start)
3213 g_return_if_fail (E_IS_CAL_MODEL (model));
3215 if (model->priv->work_day_start_mon == work_day_start)
3216 return;
3218 model->priv->work_day_start_mon = work_day_start;
3220 g_object_notify (G_OBJECT (model), "work-day-start-mon");
3223 gint
3224 e_cal_model_get_work_day_end_mon (ECalModel *model)
3226 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3228 return model->priv->work_day_end_mon;
3231 void
3232 e_cal_model_set_work_day_end_mon (ECalModel *model,
3233 gint work_day_end)
3235 g_return_if_fail (E_IS_CAL_MODEL (model));
3237 if (model->priv->work_day_end_mon == work_day_end)
3238 return;
3240 model->priv->work_day_end_mon = work_day_end;
3242 g_object_notify (G_OBJECT (model), "work-day-end-mon");
3245 gint
3246 e_cal_model_get_work_day_start_tue (ECalModel *model)
3248 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3250 return model->priv->work_day_start_tue;
3253 void
3254 e_cal_model_set_work_day_start_tue (ECalModel *model,
3255 gint work_day_start)
3257 g_return_if_fail (E_IS_CAL_MODEL (model));
3259 if (model->priv->work_day_start_tue == work_day_start)
3260 return;
3262 model->priv->work_day_start_tue = work_day_start;
3264 g_object_notify (G_OBJECT (model), "work-day-start-tue");
3267 gint
3268 e_cal_model_get_work_day_end_tue (ECalModel *model)
3270 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3272 return model->priv->work_day_end_tue;
3275 void
3276 e_cal_model_set_work_day_end_tue (ECalModel *model,
3277 gint work_day_end)
3279 g_return_if_fail (E_IS_CAL_MODEL (model));
3281 if (model->priv->work_day_end_tue == work_day_end)
3282 return;
3284 model->priv->work_day_end_tue = work_day_end;
3286 g_object_notify (G_OBJECT (model), "work-day-end-tue");
3289 gint
3290 e_cal_model_get_work_day_start_wed (ECalModel *model)
3292 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3294 return model->priv->work_day_start_wed;
3297 void
3298 e_cal_model_set_work_day_start_wed (ECalModel *model,
3299 gint work_day_start)
3301 g_return_if_fail (E_IS_CAL_MODEL (model));
3303 if (model->priv->work_day_start_wed == work_day_start)
3304 return;
3306 model->priv->work_day_start_wed = work_day_start;
3308 g_object_notify (G_OBJECT (model), "work-day-start-wed");
3311 gint
3312 e_cal_model_get_work_day_end_wed (ECalModel *model)
3314 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3316 return model->priv->work_day_end_wed;
3319 void
3320 e_cal_model_set_work_day_end_wed (ECalModel *model,
3321 gint work_day_end)
3323 g_return_if_fail (E_IS_CAL_MODEL (model));
3325 if (model->priv->work_day_end_wed == work_day_end)
3326 return;
3328 model->priv->work_day_end_wed = work_day_end;
3330 g_object_notify (G_OBJECT (model), "work-day-end-wed");
3333 gint
3334 e_cal_model_get_work_day_start_thu (ECalModel *model)
3336 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3338 return model->priv->work_day_start_thu;
3341 void
3342 e_cal_model_set_work_day_start_thu (ECalModel *model,
3343 gint work_day_start)
3345 g_return_if_fail (E_IS_CAL_MODEL (model));
3347 if (model->priv->work_day_start_thu == work_day_start)
3348 return;
3350 model->priv->work_day_start_thu = work_day_start;
3352 g_object_notify (G_OBJECT (model), "work-day-start-thu");
3355 gint
3356 e_cal_model_get_work_day_end_thu (ECalModel *model)
3358 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3360 return model->priv->work_day_end_thu;
3363 void
3364 e_cal_model_set_work_day_end_thu (ECalModel *model,
3365 gint work_day_end)
3367 g_return_if_fail (E_IS_CAL_MODEL (model));
3369 if (model->priv->work_day_end_thu == work_day_end)
3370 return;
3372 model->priv->work_day_end_thu = work_day_end;
3374 g_object_notify (G_OBJECT (model), "work-day-end-thu");
3377 gint
3378 e_cal_model_get_work_day_start_fri (ECalModel *model)
3380 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3382 return model->priv->work_day_start_fri;
3385 void
3386 e_cal_model_set_work_day_start_fri (ECalModel *model,
3387 gint work_day_start)
3389 g_return_if_fail (E_IS_CAL_MODEL (model));
3391 if (model->priv->work_day_start_fri == work_day_start)
3392 return;
3394 model->priv->work_day_start_fri = work_day_start;
3396 g_object_notify (G_OBJECT (model), "work-day-start-fri");
3399 gint
3400 e_cal_model_get_work_day_end_fri (ECalModel *model)
3402 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3404 return model->priv->work_day_end_fri;
3407 void
3408 e_cal_model_set_work_day_end_fri (ECalModel *model,
3409 gint work_day_end)
3411 g_return_if_fail (E_IS_CAL_MODEL (model));
3413 if (model->priv->work_day_end_fri == work_day_end)
3414 return;
3416 model->priv->work_day_end_fri = work_day_end;
3418 g_object_notify (G_OBJECT (model), "work-day-end-fri");
3421 gint
3422 e_cal_model_get_work_day_start_sat (ECalModel *model)
3424 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3426 return model->priv->work_day_start_sat;
3429 void
3430 e_cal_model_set_work_day_start_sat (ECalModel *model,
3431 gint work_day_start)
3433 g_return_if_fail (E_IS_CAL_MODEL (model));
3435 if (model->priv->work_day_start_sat == work_day_start)
3436 return;
3438 model->priv->work_day_start_sat = work_day_start;
3440 g_object_notify (G_OBJECT (model), "work-day-start-sat");
3443 gint
3444 e_cal_model_get_work_day_end_sat (ECalModel *model)
3446 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3448 return model->priv->work_day_end_sat;
3451 void
3452 e_cal_model_set_work_day_end_sat (ECalModel *model,
3453 gint work_day_end)
3455 g_return_if_fail (E_IS_CAL_MODEL (model));
3457 if (model->priv->work_day_end_sat == work_day_end)
3458 return;
3460 model->priv->work_day_end_sat = work_day_end;
3462 g_object_notify (G_OBJECT (model), "work-day-end-sat");
3465 gint
3466 e_cal_model_get_work_day_start_sun (ECalModel *model)
3468 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3470 return model->priv->work_day_start_sun;
3473 void
3474 e_cal_model_set_work_day_start_sun (ECalModel *model,
3475 gint work_day_start)
3477 g_return_if_fail (E_IS_CAL_MODEL (model));
3479 if (model->priv->work_day_start_sun == work_day_start)
3480 return;
3482 model->priv->work_day_start_sun = work_day_start;
3484 g_object_notify (G_OBJECT (model), "work-day-start-sun");
3487 gint
3488 e_cal_model_get_work_day_end_sun (ECalModel *model)
3490 g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
3492 return model->priv->work_day_end_sun;
3495 void
3496 e_cal_model_set_work_day_end_sun (ECalModel *model,
3497 gint work_day_end)
3499 g_return_if_fail (E_IS_CAL_MODEL (model));
3501 if (model->priv->work_day_end_sun == work_day_end)
3502 return;
3504 model->priv->work_day_end_sun = work_day_end;
3506 g_object_notify (G_OBJECT (model), "work-day-end-sun");
3509 void
3510 e_cal_model_get_work_day_range_for (ECalModel *model,
3511 GDateWeekday weekday,
3512 gint *start_hour,
3513 gint *start_minute,
3514 gint *end_hour,
3515 gint *end_minute)
3517 gint start_adept = -1, end_adept = -1;
3519 g_return_if_fail (E_IS_CAL_MODEL (model));
3520 g_return_if_fail (start_hour != NULL);
3521 g_return_if_fail (start_minute != NULL);
3522 g_return_if_fail (end_hour != NULL);
3523 g_return_if_fail (end_minute != NULL);
3525 switch (weekday) {
3526 case G_DATE_MONDAY:
3527 start_adept = e_cal_model_get_work_day_start_mon (model);
3528 end_adept = e_cal_model_get_work_day_end_mon (model);
3529 break;
3530 case G_DATE_TUESDAY:
3531 start_adept = e_cal_model_get_work_day_start_tue (model);
3532 end_adept = e_cal_model_get_work_day_end_tue (model);
3533 break;
3534 case G_DATE_WEDNESDAY:
3535 start_adept = e_cal_model_get_work_day_start_wed (model);
3536 end_adept = e_cal_model_get_work_day_end_wed (model);
3537 break;
3538 case G_DATE_THURSDAY:
3539 start_adept = e_cal_model_get_work_day_start_thu (model);
3540 end_adept = e_cal_model_get_work_day_end_thu (model);
3541 break;
3542 case G_DATE_FRIDAY:
3543 start_adept = e_cal_model_get_work_day_start_fri (model);
3544 end_adept = e_cal_model_get_work_day_end_fri (model);
3545 break;
3546 case G_DATE_SATURDAY:
3547 start_adept = e_cal_model_get_work_day_start_sat (model);
3548 end_adept = e_cal_model_get_work_day_end_sat (model);
3549 break;
3550 case G_DATE_SUNDAY:
3551 start_adept = e_cal_model_get_work_day_start_sun (model);
3552 end_adept = e_cal_model_get_work_day_end_sun (model);
3553 break;
3554 default:
3555 break;
3558 if (start_adept > 0 && (start_adept / 100) >= 0 && (start_adept / 100) <= 23 &&
3559 (start_adept % 100) >= 0 && (start_adept % 100) <= 59) {
3560 *start_hour = start_adept / 100;
3561 *start_minute = start_adept % 100;
3562 } else {
3563 *start_hour = e_cal_model_get_work_day_start_hour (model);
3564 *start_minute = e_cal_model_get_work_day_start_minute (model);
3567 if (end_adept > 0 && (end_adept / 100) >= 0 && (end_adept / 100) <= 23 &&
3568 (end_adept % 100) >= 0 && (end_adept % 100) <= 59) {
3569 *end_hour = end_adept / 100;
3570 *end_minute = end_adept % 100;
3571 } else {
3572 *end_hour = e_cal_model_get_work_day_end_hour (model);
3573 *end_minute = e_cal_model_get_work_day_end_minute (model);
3577 const gchar *
3578 e_cal_model_get_default_source_uid (ECalModel *model)
3580 g_return_val_if_fail (model != NULL, NULL);
3581 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3583 if (model->priv->default_source_uid && !*model->priv->default_source_uid)
3584 return NULL;
3586 return model->priv->default_source_uid;
3589 void
3590 e_cal_model_set_default_source_uid (ECalModel *model,
3591 const gchar *source_uid)
3593 g_return_if_fail (E_IS_CAL_MODEL (model));
3595 if (g_strcmp0 (model->priv->default_source_uid, source_uid) == 0)
3596 return;
3598 g_free (model->priv->default_source_uid);
3599 model->priv->default_source_uid = g_strdup (source_uid);
3601 g_object_notify (G_OBJECT (model), "default-source-uid");
3604 static ECalModelComponent *
3605 search_by_id_and_client (ECalModelPrivate *priv,
3606 ECalClient *client,
3607 const ECalComponentId *id)
3609 gint i;
3611 for (i = 0; i < priv->objects->len; i++) {
3612 ECalModelComponent *comp_data = g_ptr_array_index (priv->objects, i);
3614 if (comp_data) {
3615 const gchar *uid;
3616 gchar *rid = NULL;
3617 struct icaltimetype icalrid;
3618 gboolean has_rid = (id->rid && *id->rid);
3620 uid = icalcomponent_get_uid (comp_data->icalcomp);
3621 icalrid = icalcomponent_get_recurrenceid (comp_data->icalcomp);
3622 if (!icaltime_is_null_time (icalrid))
3623 rid = icaltime_as_ical_string_r (icalrid);
3625 if (uid && *uid) {
3626 if ((!client || comp_data->client == client) && !strcmp (id->uid, uid)) {
3627 if (has_rid) {
3628 if (!(rid && *rid && !strcmp (rid, id->rid))) {
3629 g_free (rid);
3630 continue;
3633 g_free (rid);
3634 return comp_data;
3638 g_free (rid);
3642 return NULL;
3645 void
3646 e_cal_model_remove_all_objects (ECalModel *model)
3648 ECalModelComponent *comp_data;
3649 ETableModel *table_model;
3650 GSList *link;
3651 gint index;
3653 table_model = E_TABLE_MODEL (model);
3654 for (index = model->priv->objects->len - 1; index >= 0; index--) {
3655 e_table_model_pre_change (table_model);
3657 comp_data = g_ptr_array_remove_index (model->priv->objects, index);
3658 if (!comp_data) {
3659 e_table_model_no_change (table_model);
3660 continue;
3663 link = g_slist_append (NULL, comp_data);
3664 g_signal_emit (model, signals[COMPS_DELETED], 0, link);
3666 g_slist_free (link);
3667 g_object_unref (comp_data);
3669 e_table_model_row_deleted (table_model, index);
3673 void
3674 e_cal_model_get_time_range (ECalModel *model,
3675 time_t *start,
3676 time_t *end)
3678 ECalModelPrivate *priv;
3680 g_return_if_fail (model != NULL);
3681 g_return_if_fail (E_IS_CAL_MODEL (model));
3683 priv = model->priv;
3685 if (start)
3686 *start = priv->start;
3688 if (end)
3689 *end = priv->end;
3692 void
3693 e_cal_model_set_time_range (ECalModel *model,
3694 time_t start,
3695 time_t end)
3697 ECalModelPrivate *priv;
3698 ECalDataModelSubscriber *subscriber;
3700 g_return_if_fail (model != NULL);
3701 g_return_if_fail (E_IS_CAL_MODEL (model));
3702 g_return_if_fail (start >= 0 && end >= 0);
3703 g_return_if_fail (start <= end);
3705 priv = model->priv;
3707 if (start != (time_t) 0 && end != (time_t) 0) {
3708 end = time_day_end_with_zone (end, priv->zone) - 1;
3711 if (priv->start == start && priv->end == end)
3712 return;
3714 subscriber = E_CAL_DATA_MODEL_SUBSCRIBER (model);
3715 priv->start = start;
3716 priv->end = end;
3718 g_signal_emit (model, signals[TIME_RANGE_CHANGED], 0, (gint64) start, (gint64) end);
3720 e_cal_data_model_unsubscribe (model->priv->data_model, subscriber);
3721 e_cal_model_remove_all_objects (model);
3722 e_cal_data_model_subscribe (model->priv->data_model, subscriber, start, end);
3726 * e_cal_model_create_component_with_defaults_sync
3728 icalcomponent *
3729 e_cal_model_create_component_with_defaults_sync (ECalModel *model,
3730 ECalClient *client,
3731 gboolean all_day,
3732 GCancellable *cancellable,
3733 GError **error)
3735 ECalComponent *comp = NULL;
3736 icalcomponent *icalcomp;
3738 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3740 if (client) {
3741 switch (model->priv->kind) {
3742 case ICAL_VEVENT_COMPONENT :
3743 comp = cal_comp_event_new_with_defaults_sync (
3744 client, all_day,
3745 e_cal_model_get_use_default_reminder (model),
3746 e_cal_model_get_default_reminder_interval (model),
3747 e_cal_model_get_default_reminder_units (model),
3748 cancellable, error);
3749 break;
3750 case ICAL_VTODO_COMPONENT :
3751 comp = cal_comp_task_new_with_defaults_sync (client, cancellable, error);
3752 break;
3753 case ICAL_VJOURNAL_COMPONENT :
3754 comp = cal_comp_memo_new_with_defaults_sync (client, cancellable, error);
3755 break;
3756 default:
3757 g_warn_if_reached ();
3758 return NULL;
3762 if (comp) {
3763 icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
3764 g_object_unref (comp);
3765 } else {
3766 icalcomp = icalcomponent_new (model->priv->kind);
3769 /* make sure the component has a UID */
3770 if (!icalcomponent_get_uid (icalcomp)) {
3771 gchar *uid;
3773 uid = e_util_generate_uid ();
3774 icalcomponent_set_uid (icalcomp, uid);
3776 g_free (uid);
3779 return icalcomp;
3783 * Returns information about attendees in the component.
3784 * If there are no attendees, the function returns NULL.
3786 * The information is like "Status: Accepted: X Declined: Y ...".
3788 * Free returned pointer with g_free.
3790 gchar *
3791 e_cal_model_get_attendees_status_info (ECalModel *model,
3792 ECalComponent *comp,
3793 ECalClient *cal_client)
3795 struct _values {
3796 icalparameter_partstat status;
3797 const gchar *caption;
3798 gint count;
3799 } values[] = {
3800 { ICAL_PARTSTAT_ACCEPTED, N_("Accepted"), 0 },
3801 { ICAL_PARTSTAT_DECLINED, N_("Declined"), 0 },
3802 { ICAL_PARTSTAT_TENTATIVE, N_("Tentative"), 0 },
3803 { ICAL_PARTSTAT_DELEGATED, N_("Delegated"), 0 },
3804 { ICAL_PARTSTAT_NEEDSACTION, N_("Needs action"), 0 },
3805 { ICAL_PARTSTAT_NONE, N_("Other"), 0 },
3806 { ICAL_PARTSTAT_X, NULL, -1 }
3809 ESourceRegistry *registry;
3810 GSList *attendees = NULL, *a;
3811 gboolean have = FALSE;
3812 gchar *res = NULL;
3813 gint i;
3815 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3817 registry = e_cal_model_get_registry (model);
3819 if (!comp || !e_cal_component_has_attendees (comp) ||
3820 !itip_organizer_is_user_ex (registry, comp, cal_client, TRUE))
3821 return NULL;
3823 e_cal_component_get_attendee_list (comp, &attendees);
3825 for (a = attendees; a; a = a->next) {
3826 ECalComponentAttendee *att = a->data;
3828 if (att && att->cutype == ICAL_CUTYPE_INDIVIDUAL &&
3829 (att->role == ICAL_ROLE_CHAIR ||
3830 att->role == ICAL_ROLE_REQPARTICIPANT ||
3831 att->role == ICAL_ROLE_OPTPARTICIPANT)) {
3832 have = TRUE;
3834 for (i = 0; values[i].count != -1; i++) {
3835 if (att->status == values[i].status || values[i].status == ICAL_PARTSTAT_NONE) {
3836 values[i].count++;
3837 break;
3843 if (have) {
3844 GString *str = g_string_new ("");
3846 for (i = 0; values[i].count != -1; i++) {
3847 if (values[i].count > 0) {
3848 if (str->str && *str->str)
3849 g_string_append (str, " ");
3851 g_string_append_printf (str, "%s: %d", _(values[i].caption), values[i].count);
3855 g_string_prepend (str, ": ");
3857 /* To Translators: 'Status' here means the state of the attendees, the resulting string will be in a form:
3858 * Status: Accepted: X Declined: Y ... */
3859 g_string_prepend (str, _("Status"));
3861 res = g_string_free (str, FALSE);
3864 if (attendees)
3865 e_cal_component_free_attendee_list (attendees);
3867 return res;
3871 * e_cal_model_get_color_for_component
3873 const gchar *
3874 e_cal_model_get_color_for_component (ECalModel *model,
3875 ECalModelComponent *comp_data)
3877 ECalModelClass *model_class;
3878 const gchar *color = NULL;
3880 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3881 g_return_val_if_fail (comp_data != NULL, NULL);
3883 model_class = (ECalModelClass *) G_OBJECT_GET_CLASS (model);
3884 if (model_class->get_color_for_component != NULL)
3885 color = model_class->get_color_for_component (model, comp_data);
3887 if (!color)
3888 color = cal_model_get_color_for_component (model, comp_data);
3890 return color;
3893 gboolean
3894 e_cal_model_get_rgba_for_component (ECalModel *model,
3895 ECalModelComponent *comp_data,
3896 GdkRGBA *rgba)
3898 const gchar *color;
3900 color = e_cal_model_get_color_for_component (model, comp_data);
3901 if (!color)
3902 return FALSE;
3904 return gdk_rgba_parse (rgba, color);
3908 * e_cal_model_get_rgb_color_for_component:
3910 * Deprecated: 3.20: Use e_cal_model_get_rgba_for_component() instead
3912 gboolean
3913 e_cal_model_get_rgb_color_for_component (ECalModel *model,
3914 ECalModelComponent *comp_data,
3915 gdouble *red,
3916 gdouble *green,
3917 gdouble *blue)
3919 GdkRGBA rgba;
3921 if (!e_cal_model_get_rgba_for_component (model, comp_data, &rgba))
3922 return FALSE;
3924 if (red)
3925 *red = rgba.red;
3926 if (green)
3927 *green = rgba.green;
3928 if (blue)
3929 *blue = rgba.blue;
3931 return TRUE;
3935 * e_cal_model_get_component_at
3937 ECalModelComponent *
3938 e_cal_model_get_component_at (ECalModel *model,
3939 gint row)
3941 ECalModelPrivate *priv;
3943 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3945 priv = model->priv;
3947 g_return_val_if_fail (row >= 0 && row < priv->objects->len, NULL);
3949 return g_ptr_array_index (priv->objects, row);
3952 ECalModelComponent *
3953 e_cal_model_get_component_for_client_and_uid (ECalModel *model,
3954 ECalClient *client,
3955 const ECalComponentId *id)
3957 ECalModelPrivate *priv;
3959 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
3961 priv = model->priv;
3963 return search_by_id_and_client (priv, client, id);
3967 * e_cal_model_date_value_to_string
3969 gchar *
3970 e_cal_model_date_value_to_string (ECalModel *model,
3971 gconstpointer value)
3973 ECalModelPrivate *priv;
3974 ECellDateEditValue *dv = (ECellDateEditValue *) value;
3975 struct icaltimetype tt;
3976 struct tm tmp_tm;
3977 gchar buffer[64];
3979 g_return_val_if_fail (E_IS_CAL_MODEL (model), g_strdup (""));
3981 priv = model->priv;
3983 if (!dv)
3984 return g_strdup ("");
3986 /* We currently convert all the dates to the current timezone. */
3987 tt = dv->tt;
3988 icaltimezone_convert_time (&tt, dv->zone, priv->zone);
3990 tmp_tm.tm_year = tt.year - 1900;
3991 tmp_tm.tm_mon = tt.month - 1;
3992 tmp_tm.tm_mday = tt.day;
3993 tmp_tm.tm_hour = tt.hour;
3994 tmp_tm.tm_min = tt.minute;
3995 tmp_tm.tm_sec = tt.second;
3996 tmp_tm.tm_isdst = -1;
3998 tmp_tm.tm_wday = time_day_of_week (tt.day, tt.month - 1, tt.year);
4000 memset (buffer, 0, sizeof (buffer));
4001 e_time_format_date_and_time (&tmp_tm, priv->use_24_hour_format,
4002 TRUE, FALSE,
4003 buffer, sizeof (buffer));
4004 return g_strdup (buffer);
4007 typedef struct _GenerateInstacesData {
4008 ECalModelGenerateInstancesData mdata;
4009 ECalRecurInstanceFn cb;
4010 ECalClient *client;
4011 icaltimezone *zone;
4012 } GenerateInstancesData;
4014 static gboolean
4015 ecm_generate_instances_cb (ECalComponent *comp,
4016 time_t instance_start,
4017 time_t instance_end,
4018 gpointer user_data)
4020 GenerateInstancesData *gid = user_data;
4022 g_return_val_if_fail (gid != NULL, FALSE);
4023 g_return_val_if_fail (gid->mdata.comp_data != NULL, FALSE);
4025 cal_comp_get_instance_times (gid->mdata.comp_data->client, e_cal_component_get_icalcomponent (comp),
4026 gid->zone, &instance_start, NULL, &instance_end, NULL, NULL);
4028 return gid->cb (comp, instance_start, instance_end, &gid->mdata);
4032 * e_cal_model_generate_instances_sync
4034 * cb function is not called with cb_data, but with ECalModelGenerateInstancesData which contains cb_data
4036 void
4037 e_cal_model_generate_instances_sync (ECalModel *model,
4038 time_t start,
4039 time_t end,
4040 ECalRecurInstanceFn cb,
4041 gpointer cb_data)
4043 GenerateInstancesData gid;
4044 gint i, n;
4046 g_return_if_fail (cb != NULL);
4048 gid.mdata.cb_data = cb_data;
4049 gid.cb = cb;
4050 gid.zone = model->priv->zone;
4052 n = e_table_model_row_count (E_TABLE_MODEL (model));
4053 for (i = 0; i < n; i++) {
4054 ECalModelComponent *comp_data = e_cal_model_get_component_at (model, i);
4056 if (comp_data->instance_start < end && comp_data->instance_end > start) {
4057 gid.mdata.comp_data = comp_data;
4059 e_cal_client_generate_instances_for_object_sync (comp_data->client, comp_data->icalcomp, start, end,
4060 ecm_generate_instances_cb, &gid);
4066 * e_cal_model_get_object_array
4068 GPtrArray *
4069 e_cal_model_get_object_array (ECalModel *model)
4071 g_return_val_if_fail (model != NULL, NULL);
4072 g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
4073 g_return_val_if_fail (model->priv != NULL, NULL);
4075 return model->priv->objects;
4078 void
4079 e_cal_model_set_instance_times (ECalModelComponent *comp_data,
4080 const icaltimezone *zone)
4082 if (icalcomponent_isa (comp_data->icalcomp) == ICAL_VEVENT_COMPONENT) {
4083 struct icaltimetype start_time, end_time;
4085 start_time = icalcomponent_get_dtstart (comp_data->icalcomp);
4086 end_time = icalcomponent_get_dtend (comp_data->icalcomp);
4088 if (start_time.is_date && icaltime_is_null_time (end_time)) {
4089 /* If end_time is null and it's an all day event,
4090 * just make start_time = end_time so that end_time
4091 * will be a valid date
4093 end_time = start_time;
4094 icaltime_adjust (&end_time, 1, 0, 0, 0);
4095 icalcomponent_set_dtend (comp_data->icalcomp, end_time);
4096 } else if (start_time.is_date && end_time.is_date &&
4097 (icaltime_compare_date_only (start_time, end_time) == 0)) {
4098 /* If both DTSTART and DTEND are DATE values, and they are the
4099 * same day, we add 1 day to DTEND. This means that most
4100 * events created with the old Evolution behavior will still
4101 * work OK. */
4102 icaltime_adjust (&end_time, 1, 0, 0, 0);
4103 icalcomponent_set_dtend (comp_data->icalcomp, end_time);
4107 cal_comp_get_instance_times (comp_data->client, comp_data->icalcomp, zone,
4108 &comp_data->instance_start, NULL, &comp_data->instance_end, NULL, NULL);
4112 * e_cal_model_set_default_time_func:
4113 * This function will be used when creating new item from the "click-to-add",
4114 * when user didn't fill a start date there.
4116 void
4117 e_cal_model_set_default_time_func (ECalModel *model,
4118 ECalModelDefaultTimeFunc func,
4119 gpointer user_data)
4121 g_return_if_fail (E_IS_CAL_MODEL (model));
4123 model->priv->get_default_time = func;
4124 model->priv->get_default_time_user_data = user_data;
4127 void
4128 e_cal_model_modify_component (ECalModel *model,
4129 ECalModelComponent *comp_data,
4130 ECalObjModType mod)
4132 g_return_if_fail (E_IS_CAL_MODEL (model));
4133 g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data));
4135 e_cal_ops_modify_component (model, comp_data->client, comp_data->icalcomp, mod, E_CAL_OPS_SEND_FLAG_ASK);
4138 void
4139 e_cal_model_util_set_value (GHashTable *values,
4140 ETableModel *table_model,
4141 gint column,
4142 gint row)
4144 gpointer value;
4146 g_return_if_fail (values != NULL);
4148 value = e_table_model_value_at (table_model, column, row);
4150 g_hash_table_insert (values, GINT_TO_POINTER (column),
4151 e_table_model_duplicate_value (table_model, column, value));
4154 gpointer
4155 e_cal_model_util_get_value (GHashTable *values,
4156 gint column)
4158 g_return_val_if_fail (values != NULL, NULL);
4160 return g_hash_table_lookup (values, GINT_TO_POINTER (column));
4163 void
4164 e_cal_model_emit_object_created (ECalModel *model,
4165 ECalClient *where)
4167 g_return_if_fail (E_IS_CAL_MODEL (model));
4168 g_return_if_fail (E_IS_CAL_CLIENT (where));
4170 g_signal_emit (model, signals[OBJECT_CREATED], 0, where);
4174 ECellDateEditValue *
4175 e_cal_model_copy_cell_date_value (const ECellDateEditValue *value)
4177 ECellDateEditValue *copy;
4179 if (!value)
4180 return NULL;
4183 copy = g_new0 (ECellDateEditValue, 1);
4184 copy->tt = value->tt;
4185 copy->zone = value->zone;
4187 return copy;