aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog107
-rw-r--r--calendar/cal-client/cal-client.c86
-rw-r--r--calendar/cal-client/cal-client.h5
-rw-r--r--calendar/cal-client/cal-query.c25
-rw-r--r--calendar/cal-client/cal-query.h18
-rw-r--r--calendar/conduits/calendar/calendar-conduit.c20
-rw-r--r--calendar/conduits/todo/todo-conduit.c20
-rw-r--r--calendar/gui/Makefile.am6
-rw-r--r--calendar/gui/calendar-model.c15
-rw-r--r--calendar/gui/comp-editor-factory.c10
-rw-r--r--calendar/gui/comp-util.c27
-rw-r--r--calendar/gui/dialogs/comp-editor.c16
-rw-r--r--calendar/gui/e-cal-model-calendar.c447
-rw-r--r--calendar/gui/e-cal-model-calendar.h58
-rw-r--r--calendar/gui/e-cal-model-tasks.c904
-rw-r--r--calendar/gui/e-cal-model-tasks.h64
-rw-r--r--calendar/gui/e-cal-model.c1303
-rw-r--r--calendar/gui/e-cal-model.h95
-rw-r--r--calendar/gui/e-day-view.c14
-rw-r--r--calendar/gui/e-itip-control.c79
-rw-r--r--calendar/gui/e-week-view.c14
-rw-r--r--calendar/gui/gnome-cal.c26
22 files changed, 3242 insertions, 117 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index b24f477cc5..6d3099d53a 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,13 +1,120 @@
+2003-08-06 Rodrigo Moya <rodrigo@ximian.com>
+
+ * gui/e-cal-model.[ch]: removed 'create_component_with_defaults'
+ virtual method.
+ (e_cal_component_create_component_with_defaults):
+ (e_cal_component_get_color_for_component): new functions.
+
+2003-08-06 Rodrigo Moya <rodrigo@ximian.com>
+
+ * gui/e-cal-model.[ch] (e_cal_model_set_query): new function.
+ (e_cal_model_remove_all_clients): implemented.
+ (remove_client): also remove all objects belonging to the
+ client being removed.
+
+2003-08-06 Rodrigo Moya <rodrigo@ximian.com>
+
+ * gui/e-cal-model.c (get_dtstart, set_dtstart): implemented.
+ (ecm_value_at, ecm_set_value_at, ecm_duplicate_value,
+ ecm_free_value, ecm_value_to_string): added case for DTSTART
+ field.
+ (free_comp_data): free also the other date values in the
+ ECalModelComponent struct.
+ (e_cal_model_date_value_to_string): new function.
+
+ * gui/e-cal-model.h: added new prototypes.
+
+ * gui/e-cal-model-calendar.[ch]: new ECalModel-based class for
+ containing events.
+
+ * gui/e-cal-model-tasks.c (ecmt_value_to_string): implemented
+ the case for date fields.
+
+2003-08-05 Rodrigo Moya <rodrigo@ximian.com>
+
+ * cal-client/cal-client.c (generate_instances_obj_updated_cb): fixed
+ parameters in call to cal_client_get_object().
+ (get_objects_atomatically): same.
+
+ * gui/e-cal-model.[ch]: added "get_color_for_component" virtual method.
+ (get_color): new function to return the color. It calls the virtual
+ method of the current class.
+ (ecm_value_at): return a value for the color and icon columns.
+ (e_cal_model_class_init): initialize virtual methods.
+
+ * gui/e-cal-model-tasks.c (ecmt_get_color_for_component): implemented
+ new class' virtual method.
+
2003-08-05 Jack Jia <jack.jia@sun.com>
* gui/dialogs/event-page.glade: changed one of the "Con_fidential" to
"Co_nfidential" since we already have "File" using the same 'F' key.
+2003-08-05 Rodrigo Moya <rodrigo@ximian.com>
+
+ * cal-client_/cal-client.c (cal_client_get_default_object): use
+ correctly the pointer to pointer.
+
+ * gui/e-week-view.c (query_obj_updated_cb): fixed the call to
+ cal_client_get_object().
+
+2003-08-04 Rodrigo Moya <rodrigo@ximian.com>
+
+ * cal-client/cal-client.[ch] (cal_client_get_default_object):
+ (cal_client_get_object): use icalcomponent instead of CalComponent.
+
+ * gui/e-cal-model.c (get_dtstart): implemented.
+ (query_obj_updated_cb):
+ (query_obj_removed_cb):
+ (query_done_cb):
+ (query_eval_error_cb): implemented missing functions.
+
+ * gui/calendar-model.c:
+ * gui/comp-editor-factory.c:
+ * gui/comp-util.c:
+ * gui/e-day-view.c:
+ * gui/e-itip-control.c:
+ * gui/e-week-view.c:
+ * gui/gnome-cal.c:
+ * gui/dialogs/comp-editor.c:
+ * conduits/todo/todo-conduit.c:
+ * conduits/calendar/calendar-conduit.c: adapted to changes
+ in CalClient API.
+
+2003-08-04 Rodrigo Moya <rodrigo@ximian.com>
+
+ * cal-client/cal-query.[ch] (cal_query_new): added a 'CalClient'
+ argument to this function.
+ (cal_query_get_client): new function.
+
+ * cal-client/cal-client.c (cal_client_get_query): added new parameter
+ in call to cal_query_new ().
+
+2003-08-01 Lorenzo Gil <lgs@sicem.biz>
+
+ * gui/e-alarm-list.c: added the include <config.h> line at the
+ beginning to enable gettext.
+
+2003-08-01 Rodrigo Moya <rodrigo@ximian.com>
+
+ * gui/e-cal-model.[ch] (e_cal_model_get_component_at): new function.
+ (ecm_append_row): use the client from the source model.
+ (e_cal_model_get_timezone, e_cal_model_set_timezone): new functions.
+
+ * gui/e-cal-model-tasks.[ch]: new class for the tasks model.
+
2003-08-01 Lorenzo Gil <lgs@sicem.biz>
* gui/e-alarm-list.c: added the include <config.h> line at the
beginning to enable gettext.
+2003-07-31 Rodrigo Moya <rodrigo@ximian.com>
+
+ * gui/e-cal-model.[ch]: new class, based on CalendarModel to be
+ an abstract class for calendar models.
+
+ * gui/Makefile.am: added new files to build.
+
2003-07-30 Rodrigo Moya <rodrigo@ximian.com>
* cal-client/cal-client-multi.[ch]:
diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c
index 0854d75b61..740d8f4062 100644
--- a/calendar/cal-client/cal-client.c
+++ b/calendar/cal-client/cal-client.c
@@ -1354,13 +1354,12 @@ struct _CalClientGetTimezonesData {
};
CalClientGetStatus
-cal_client_get_default_object (CalClient *client, CalObjType type, CalComponent **comp)
+cal_client_get_default_object (CalClient *client, CalObjType type, icalcomponent **icalcomp)
{
CalClientPrivate *priv;
CORBA_Environment ev;
GNOME_Evolution_Calendar_CalObj comp_str;
CalClientGetStatus retval;
- icalcomponent *icalcomp;
CalClientGetTimezonesData cb_data;
g_return_val_if_fail (client != NULL, CAL_CLIENT_GET_NOT_FOUND);
@@ -1369,10 +1368,10 @@ cal_client_get_default_object (CalClient *client, CalObjType type, CalComponent
priv = client->priv;
g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_GET_NOT_FOUND);
- g_return_val_if_fail (comp != NULL, CAL_CLIENT_GET_NOT_FOUND);
+ g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_GET_NOT_FOUND);
retval = CAL_CLIENT_GET_NOT_FOUND;
- *comp = NULL;
+ *icalcomp = NULL;
CORBA_exception_init (&ev);
comp_str = GNOME_Evolution_Calendar_Cal_getDefaultObject (priv->cal, type, &ev);
@@ -1380,24 +1379,14 @@ cal_client_get_default_object (CalClient *client, CalObjType type, CalComponent
if (BONOBO_USER_EX (&ev, ex_GNOME_Evolution_Calendar_Cal_NotFound))
goto out;
else if (BONOBO_EX (&ev)) {
- g_message ("cal_client_get_object(): could not get the object");
+ g_message ("cal_client_get_default_object(): could not get the object");
goto out;
}
- icalcomp = icalparser_parse_string (comp_str);
+ *icalcomp = icalparser_parse_string (comp_str);
CORBA_free (comp_str);
- if (!icalcomp) {
- retval = CAL_CLIENT_GET_SYNTAX_ERROR;
- goto out;
- }
-
- *comp = cal_component_new ();
- if (!cal_component_set_icalcomponent (*comp, icalcomp)) {
- icalcomponent_free (icalcomp);
- g_object_unref (*comp);
- *comp = NULL;
-
+ if (!*icalcomp) {
retval = CAL_CLIENT_GET_SYNTAX_ERROR;
goto out;
}
@@ -1411,7 +1400,7 @@ cal_client_get_default_object (CalClient *client, CalObjType type, CalComponent
resize pending, which leads to an assert failure and an abort. */
cb_data.client = client;
cb_data.status = CAL_CLIENT_GET_SUCCESS;
- icalcomponent_foreach_tzid (icalcomp,
+ icalcomponent_foreach_tzid (*icalcomp,
cal_client_get_object_timezones_cb,
&cb_data);
@@ -1427,7 +1416,7 @@ cal_client_get_default_object (CalClient *client, CalObjType type, CalComponent
* cal_client_get_object:
* @client: A calendar client.
* @uid: Unique identifier for a calendar component.
- * @comp: Return value for the calendar component object.
+ * @icalcomp: Return value for the calendar component object.
*
* Queries a calendar for a calendar component object based on its unique
* identifier.
@@ -1435,13 +1424,12 @@ cal_client_get_default_object (CalClient *client, CalObjType type, CalComponent
* Return value: Result code based on the status of the operation.
**/
CalClientGetStatus
-cal_client_get_object (CalClient *client, const char *uid, CalComponent **comp)
+cal_client_get_object (CalClient *client, const char *uid, icalcomponent **icalcomp)
{
CalClientPrivate *priv;
CORBA_Environment ev;
GNOME_Evolution_Calendar_CalObj comp_str;
CalClientGetStatus retval;
- icalcomponent *icalcomp;
CalClientGetTimezonesData cb_data;
g_return_val_if_fail (client != NULL, CAL_CLIENT_GET_NOT_FOUND);
@@ -1451,10 +1439,10 @@ cal_client_get_object (CalClient *client, const char *uid, CalComponent **comp)
g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, CAL_CLIENT_GET_NOT_FOUND);
g_return_val_if_fail (uid != NULL, CAL_CLIENT_GET_NOT_FOUND);
- g_return_val_if_fail (comp != NULL, CAL_CLIENT_GET_NOT_FOUND);
+ g_return_val_if_fail (icalcomp != NULL, CAL_CLIENT_GET_NOT_FOUND);
retval = CAL_CLIENT_GET_NOT_FOUND;
- *comp = NULL;
+ *icalcomp = NULL;
CORBA_exception_init (&ev);
comp_str = GNOME_Evolution_Calendar_Cal_getObject (priv->cal, (char *) uid, &ev);
@@ -1466,20 +1454,10 @@ cal_client_get_object (CalClient *client, const char *uid, CalComponent **comp)
goto out;
}
- icalcomp = icalparser_parse_string (comp_str);
+ *icalcomp = icalparser_parse_string (comp_str);
CORBA_free (comp_str);
- if (!icalcomp) {
- retval = CAL_CLIENT_GET_SYNTAX_ERROR;
- goto out;
- }
-
- *comp = cal_component_new ();
- if (!cal_component_set_icalcomponent (*comp, icalcomp)) {
- icalcomponent_free (icalcomp);
- g_object_unref (G_OBJECT (*comp));
- *comp = NULL;
-
+ if (!*icalcomp) {
retval = CAL_CLIENT_GET_SYNTAX_ERROR;
goto out;
}
@@ -1493,7 +1471,7 @@ cal_client_get_object (CalClient *client, const char *uid, CalComponent **comp)
resize pending, which leads to an assert failure and an abort. */
cb_data.client = client;
cb_data.status = CAL_CLIENT_GET_SUCCESS;
- icalcomponent_foreach_tzid (icalcomp,
+ icalcomponent_foreach_tzid (*icalcomp,
cal_client_get_object_timezones_cb,
&cb_data);
@@ -1936,6 +1914,7 @@ generate_instances_obj_updated_cb (CalClient *client, const char *uid, gpointer
{
GHashTable *uid_comp_hash;
CalComponent *comp;
+ icalcomponent *icalcomp;
CalClientGetStatus status;
const char *comp_uid;
@@ -1953,13 +1932,19 @@ generate_instances_obj_updated_cb (CalClient *client, const char *uid, gpointer
g_hash_table_remove (uid_comp_hash, uid);
g_object_unref (G_OBJECT (comp));
- status = cal_client_get_object (client, uid, &comp);
+ status = cal_client_get_object (client, uid, &icalcomp);
switch (status) {
case CAL_CLIENT_GET_SUCCESS:
- /* The hash key comes from the component's internal data */
- cal_component_get_uid (comp, &comp_uid);
- g_hash_table_insert (uid_comp_hash, (char *) comp_uid, comp);
+ comp = cal_component_new ();
+ if (cal_component_set_icalcomponent (comp, icalcomp)) {
+ /* The hash key comes from the component's internal data */
+ cal_component_get_uid (comp, &comp_uid);
+ g_hash_table_insert (uid_comp_hash, (char *) comp_uid, comp);
+ } else {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ }
break;
case CAL_CLIENT_GET_NOT_FOUND:
@@ -2037,21 +2022,28 @@ get_objects_atomically (CalClient *client, CalObjType type, time_t start, time_t
for (l = uids; l; l = l->next) {
CalComponent *comp;
+ icalcomponent *icalcomp;
CalClientGetStatus status;
char *uid;
const char *comp_uid;
uid = l->data;
- status = cal_client_get_object (client, uid, &comp);
+ status = cal_client_get_object (client, uid, &icalcomp);
switch (status) {
case CAL_CLIENT_GET_SUCCESS:
- /* The hash key comes from the component's internal data
- * instead of the duped UID from the list of UIDS.
- */
- cal_component_get_uid (comp, &comp_uid);
- g_hash_table_insert (uid_comp_hash, (char *) comp_uid, comp);
+ comp = cal_component_new ();
+ if (cal_component_set_icalcomponent (comp, icalcomp)) {
+ /* The hash key comes from the component's internal data
+ * instead of the duped UID from the list of UIDS.
+ */
+ cal_component_get_uid (comp, &comp_uid);
+ g_hash_table_insert (uid_comp_hash, (char *) comp_uid, comp);
+ } else {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ }
break;
case CAL_CLIENT_GET_NOT_FOUND:
@@ -2912,7 +2904,7 @@ cal_client_get_query (CalClient *client, const char *sexp)
g_return_val_if_fail (sexp != NULL, NULL);
- return cal_query_new (priv->cal, sexp);
+ return cal_query_new (client, priv->cal, sexp);
}
diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h
index 556049f831..baf2072868 100644
--- a/calendar/cal-client/cal-client.h
+++ b/calendar/cal-client/cal-client.h
@@ -40,7 +40,6 @@ G_BEGIN_DECLS
#define CAL_CLIENT_SET_MODE_STATUS_ENUM_TYPE (cal_client_set_mode_status_enum_get_type ())
#define CAL_MODE_ENUM_TYPE (cal_mode_enum_get_type ())
-typedef struct _CalClient CalClient;
typedef struct _CalClientClass CalClientClass;
typedef struct _CalClientPrivate CalClientPrivate;
@@ -169,11 +168,11 @@ int cal_client_get_n_objects (CalClient *client, CalObjType type);
CalClientGetStatus cal_client_get_default_object (CalClient *client,
CalObjType type,
- CalComponent **comp);
+ icalcomponent **icalcomp);
CalClientGetStatus cal_client_get_object (CalClient *client,
const char *uid,
- CalComponent **comp);
+ icalcomponent **icalcomp);
CalClientGetStatus cal_client_get_timezone (CalClient *client,
const char *tzid,
diff --git a/calendar/cal-client/cal-query.c b/calendar/cal-client/cal-query.c
index 77b18af1ff..914af5db28 100644
--- a/calendar/cal-client/cal-query.c
+++ b/calendar/cal-client/cal-query.c
@@ -37,6 +37,9 @@ struct _CalQueryPrivate {
/* Handle to the query in the server */
GNOME_Evolution_Calendar_Query corba_query;
+
+ /* The CalClient associated with this query */
+ CalClient *client;
};
@@ -366,6 +369,7 @@ cal_query_construct (CalQuery *query,
/**
* cal_query_new:
+ * @client: Client from which the query is being created.
* @cal: Handle to an open calendar.
* @sexp: S-expression that defines the query.
*
@@ -375,7 +379,8 @@ cal_query_construct (CalQuery *query,
* Return value: A newly-created query object, or NULL if the request failed.
**/
CalQuery *
-cal_query_new (GNOME_Evolution_Calendar_Cal cal,
+cal_query_new (CalClient *client,
+ GNOME_Evolution_Calendar_Cal cal,
const char *sexp)
{
CalQuery *query;
@@ -387,5 +392,23 @@ cal_query_new (GNOME_Evolution_Calendar_Cal cal,
return NULL;
}
+ query->priv->client = client;
+
return query;
}
+
+/**
+ * cal_query_get_client
+ * @query: A #CalQuery object.
+ *
+ * Get the #CalClient associated with this query.
+ *
+ * Returns: the associated client.
+ */
+CalClient *
+cal_query_get_client (CalQuery *query)
+{
+ g_return_val_if_fail (IS_CAL_QUERY (query), NULL);
+
+ return query->priv->client;
+}
diff --git a/calendar/cal-client/cal-query.h b/calendar/cal-client/cal-query.h
index 9464e7ae6e..77429035fa 100644
--- a/calendar/cal-client/cal-query.h
+++ b/calendar/cal-client/cal-query.h
@@ -27,6 +27,8 @@
G_BEGIN_DECLS
+typedef struct _CalClient CalClient;
+
#define CAL_QUERY_TYPE (cal_query_get_type ())
@@ -66,16 +68,18 @@ typedef struct {
void (* eval_error) (CalQuery *query, const char *error_str);
} CalQueryClass;
-GType cal_query_get_type (void);
+GType cal_query_get_type (void);
-GType cal_query_done_status_enum_get_type (void);
+GType cal_query_done_status_enum_get_type (void);
-CalQuery *cal_query_construct (CalQuery *query,
- GNOME_Evolution_Calendar_Cal cal,
- const char *sexp);
+CalQuery *cal_query_construct (CalQuery *query,
+ GNOME_Evolution_Calendar_Cal cal,
+ const char *sexp);
-CalQuery *cal_query_new (GNOME_Evolution_Calendar_Cal cal,
- const char *sexp);
+CalQuery *cal_query_new (CalClient *client,
+ GNOME_Evolution_Calendar_Cal cal,
+ const char *sexp);
+CalClient *cal_query_get_client (CalQuery *query);
diff --git a/calendar/conduits/calendar/calendar-conduit.c b/calendar/conduits/calendar/calendar-conduit.c
index 0171ea4b70..1893e6b34c 100644
--- a/calendar/conduits/calendar/calendar-conduit.c
+++ b/calendar/conduits/calendar/calendar-conduit.c
@@ -1006,13 +1006,21 @@ local_record_from_uid (ECalLocalRecord *local,
ECalConduitContext *ctxt)
{
CalComponent *comp;
+ icalcomponent *icalcomp;
CalClientGetStatus status;
g_assert(local!=NULL);
- status = cal_client_get_object (ctxt->client, uid, &comp);
+ status = cal_client_get_object (ctxt->client, uid, &icalcomp);
if (status == CAL_CLIENT_GET_SUCCESS) {
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ return;
+ }
+
local_record_from_comp (local, comp, ctxt);
g_object_unref (comp);
} else if (status == CAL_CLIENT_GET_NOT_FOUND) {
@@ -1328,6 +1336,7 @@ pre_sync (GnomePilotConduit *conduit,
int len;
unsigned char *buf;
char *filename, *change_id;
+ icalcomponent *icalcomp;
gint num_records, add_records = 0, mod_records = 0, del_records = 0;
abs_conduit = GNOME_PILOT_CONDUIT_SYNC_ABS (conduit);
@@ -1355,9 +1364,16 @@ pre_sync (GnomePilotConduit *conduit,
cal_client_set_default_timezone (ctxt->client, ctxt->timezone);
/* Get the default component */
- if (cal_client_get_default_object (ctxt->client, CALOBJ_TYPE_EVENT, &ctxt->default_comp) != CAL_CLIENT_GET_SUCCESS)
+ if (cal_client_get_default_object (ctxt->client, CALOBJ_TYPE_EVENT, &icalcomp) != CAL_CLIENT_GET_SUCCESS)
return -1;
+ ctxt->default_comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (ctxt->default_comp, icalcomp)) {
+ g_object_unref (ctxt->default_comp);
+ icalcomponent_free (icalcomp);
+ return -1;
+ }
+
/* Load the uid <--> pilot id mapping */
filename = map_name (ctxt);
e_pilot_map_read (filename, &ctxt->map);
diff --git a/calendar/conduits/todo/todo-conduit.c b/calendar/conduits/todo/todo-conduit.c
index a27beffb9d..6868368129 100644
--- a/calendar/conduits/todo/todo-conduit.c
+++ b/calendar/conduits/todo/todo-conduit.c
@@ -675,13 +675,21 @@ local_record_from_uid (EToDoLocalRecord *local,
EToDoConduitContext *ctxt)
{
CalComponent *comp;
+ icalcomponent *icalcomp;
CalClientGetStatus status;
g_assert(local!=NULL);
- status = cal_client_get_object (ctxt->client, uid, &comp);
+ status = cal_client_get_object (ctxt->client, uid, &icalcomp);
if (status == CAL_CLIENT_GET_SUCCESS) {
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ return;
+ }
+
local_record_from_comp (local, comp, ctxt);
g_object_unref (comp);
} else if (status == CAL_CLIENT_GET_NOT_FOUND) {
@@ -869,6 +877,7 @@ pre_sync (GnomePilotConduit *conduit,
int len;
unsigned char *buf;
char *filename, *change_id;
+ icalcomponent *icalcomp;
gint num_records, add_records = 0, mod_records = 0, del_records = 0;
abs_conduit = GNOME_PILOT_CONDUIT_SYNC_ABS (conduit);
@@ -897,9 +906,16 @@ pre_sync (GnomePilotConduit *conduit,
cal_client_set_default_timezone (ctxt->client, ctxt->timezone);
/* Get the default component */
- if (cal_client_get_default_object (ctxt->client, CALOBJ_TYPE_TODO, &ctxt->default_comp) != CAL_CLIENT_GET_SUCCESS)
+ if (cal_client_get_default_object (ctxt->client, CALOBJ_TYPE_TODO, &icalcomp) != CAL_CLIENT_GET_SUCCESS)
return -1;
+ ctxt->default_comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (ctxt->default_comp, icalcomp)) {
+ g_object_unref (ctxt->default_comp);
+ icalcomponent_free (icalcomp);
+ return -1;
+ }
+
/* Load the uid <--> pilot id map */
filename = map_name (ctxt);
e_pilot_map_read (filename, &ctxt->map);
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index 09d1db57f8..d40c2da78c 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -114,6 +114,12 @@ libevolution_calendar_la_SOURCES = \
control-factory.h \
e-alarm-list.c \
e-alarm-list.h \
+ e-cal-model-calendar.c \
+ e-cal-model-calendar.h \
+ e-cal-model-tasks.c \
+ e-cal-model-tasks.h \
+ e-cal-model.c \
+ e-cal-model.h \
e-cal-view.c \
e-cal-view.h \
e-calendar-table.h \
diff --git a/calendar/gui/calendar-model.c b/calendar/gui/calendar-model.c
index 2724a0a19c..b5d0738729 100644
--- a/calendar/gui/calendar-model.c
+++ b/calendar/gui/calendar-model.c
@@ -1763,6 +1763,7 @@ query_obj_updated_cb (CalQuery *query, const char *uid,
CalendarModelPrivate *priv;
int orig_idx;
CalComponent *new_comp;
+ icalcomponent *icalcomp;
const char *new_comp_uid;
int *new_idx;
CalClientGetStatus status;
@@ -1775,10 +1776,22 @@ query_obj_updated_cb (CalQuery *query, const char *uid,
orig_idx = remove_object (model, uid);
- status = cal_client_get_object (priv->client, uid, &new_comp);
+ status = cal_client_get_object (priv->client, uid, &icalcomp);
switch (status) {
case CAL_CLIENT_GET_SUCCESS:
+ new_comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (new_comp, icalcomp)) {
+ g_object_unref (new_comp);
+ icalcomponent_free (icalcomp);
+
+ if (orig_idx != -1)
+ e_table_model_row_deleted (E_TABLE_MODEL (model), orig_idx);
+ else
+ e_table_model_no_change (E_TABLE_MODEL (model));
+ break;
+ }
+
/* Insert the object into the model */
cal_component_get_uid (new_comp, &new_comp_uid);
diff --git a/calendar/gui/comp-editor-factory.c b/calendar/gui/comp-editor-factory.c
index 6c40a0d644..af52c8f4e2 100644
--- a/calendar/gui/comp-editor-factory.c
+++ b/calendar/gui/comp-editor-factory.c
@@ -240,6 +240,7 @@ static void
edit_existing (OpenClient *oc, const char *uid)
{
CalComponent *comp;
+ icalcomponent *icalcomp;
CalClientGetStatus status;
CompEditor *editor;
CalComponentVType vtype;
@@ -248,11 +249,16 @@ edit_existing (OpenClient *oc, const char *uid)
/* Get the object */
- status = cal_client_get_object (oc->client, uid, &comp);
+ status = cal_client_get_object (oc->client, uid, &icalcomp);
switch (status) {
case CAL_CLIENT_GET_SUCCESS:
- /* see below */
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ return;
+ }
break;
case CAL_CLIENT_GET_NOT_FOUND:
diff --git a/calendar/gui/comp-util.c b/calendar/gui/comp-util.c
index fc3496be67..28bc66bd54 100644
--- a/calendar/gui/comp-util.c
+++ b/calendar/gui/comp-util.c
@@ -211,7 +211,7 @@ cal_comp_is_on_server (CalComponent *comp, CalClient *client)
{
const char *uid;
CalClientGetStatus status;
- CalComponent *server_comp;
+ icalcomponent *icalcomp;
g_return_val_if_fail (comp != NULL, FALSE);
g_return_val_if_fail (IS_CAL_COMPONENT (comp), FALSE);
@@ -226,11 +226,11 @@ cal_comp_is_on_server (CalComponent *comp, CalClient *client)
*/
cal_component_get_uid (comp, &uid);
- status = cal_client_get_object (client, uid, &server_comp);
+ status = cal_client_get_object (client, uid, &icalcomp);
switch (status) {
case CAL_CLIENT_GET_SUCCESS:
- g_object_unref (server_comp);
+ icalcomponent_free (icalcomp);
return TRUE;
case CAL_CLIENT_GET_SYNTAX_ERROR:
@@ -260,16 +260,23 @@ cal_comp_is_on_server (CalComponent *comp, CalClient *client)
CalComponent *
cal_comp_event_new_with_defaults (CalClient *client)
{
+ icalcomponent *icalcomp;
CalComponent *comp;
int interval;
CalUnits units;
CalComponentAlarm *alarm;
- icalcomponent *icalcomp;
icalproperty *icalprop;
CalAlarmTrigger trigger;
- if (cal_client_get_default_object (client, CALOBJ_TYPE_EVENT, &comp) != CAL_CLIENT_GET_SUCCESS)
+ if (cal_client_get_default_object (client, CALOBJ_TYPE_EVENT, &icalcomp) != CAL_CLIENT_GET_SUCCESS)
+ return NULL;
+
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
return NULL;
+ }
if (!calendar_config_get_use_default_reminder ())
return comp;
@@ -325,9 +332,17 @@ CalComponent *
cal_comp_task_new_with_defaults (CalClient *client)
{
CalComponent *comp;
+ icalcomponent *icalcomp;
- if (cal_client_get_default_object (client, CALOBJ_TYPE_TODO, &comp) != CAL_CLIENT_GET_SUCCESS)
+ if (cal_client_get_default_object (client, CALOBJ_TYPE_TODO, &icalcomp) != CAL_CLIENT_GET_SUCCESS)
return NULL;
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ return NULL;
+ }
+
return comp;
}
diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c
index 62612975d2..1b3afd118b 100644
--- a/calendar/gui/dialogs/comp-editor.c
+++ b/calendar/gui/dialogs/comp-editor.c
@@ -1450,9 +1450,21 @@ obj_updated_cb (CalClient *client, const char *uid, gpointer data)
if (!strcmp (uid, edit_uid) && !priv->updating) {
if (changed_component_dialog ((GtkWindow *) editor, priv->comp, FALSE, priv->changed)) {
- status = cal_client_get_object (priv->client, uid, &comp);
+ icalcomponent *icalcomp;
+
+ status = cal_client_get_object (priv->client, uid, &icalcomp);
if (status == CAL_CLIENT_GET_SUCCESS) {
- comp_editor_edit_comp (editor, comp);
+ comp = cal_component_new ();
+ if (cal_component_set_icalcomponent (comp, icalcomp))
+ comp_editor_edit_comp (editor, comp);
+ else {
+ GtkWidget *dlg;
+
+ dlg = gnome_error_dialog (_("Unable to obtain current version!"));
+ gnome_dialog_run_and_close (GNOME_DIALOG (dlg));
+ icalcomponent_free (icalcomp);
+ }
+
g_object_unref((comp));
} else {
GtkWidget *dlg;
diff --git a/calendar/gui/e-cal-model-calendar.c b/calendar/gui/e-cal-model-calendar.c
new file mode 100644
index 0000000000..246d1c5ca8
--- /dev/null
+++ b/calendar/gui/e-cal-model-calendar.c
@@ -0,0 +1,447 @@
+/* Evolution calendar - Data model for ETable
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Authors: Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <libgnome/gnome-i18n.h>
+#include <gal/util/e-util.h>
+#include "e-cal-model-calendar.h"
+#include "e-cell-date-edit-text.h"
+#include "misc.h"
+
+struct _ECalModelCalendarPrivate {
+};
+
+static void ecmc_class_init (ECalModelCalendarClass *klass);
+static void ecmc_init (ECalModelCalendar *model, ECalModelCalendarClass *klass);
+static void ecmc_finalize (GObject *object);
+static int ecmc_column_count (ETableModel *etm);
+static void *ecmc_value_at (ETableModel *etm, int col, int row);
+static void ecmc_set_value_at (ETableModel *etm, int col, int row, const void *value);
+static gboolean ecmc_is_cell_editable (ETableModel *etm, int col, int row);
+static void ecmc_append_row (ETableModel *etm, ETableModel *source, int row);
+static void *ecmc_duplicate_value (ETableModel *etm, int col, const void *value);
+static void ecmc_free_value (ETableModel *etm, int col, void *value);
+static void *ecmc_initialize_value (ETableModel *etm, int col);
+static gboolean ecmc_value_is_empty (ETableModel *etm, int col, const void *value);
+static char *ecmc_value_to_string (ETableModel *etm, int col, const void *value);
+
+static GObjectClass *parent_class = NULL;
+
+E_MAKE_TYPE (e_cal_model_calendar, "ECalModelCalendar", ECalModelCalendar, ecmc_class_init,
+ ecmc_init, E_TYPE_CAL_MODEL);
+
+static void
+ecmc_class_init (ECalModelCalendarClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ ETableModelClass *etm_class = E_TABLE_MODEL_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = ecmc_finalize;
+
+ etm_class->column_count = ecmc_column_count;
+ etm_class->value_at = ecmc_value_at;
+ etm_class->set_value_at = ecmc_set_value_at;
+ etm_class->is_cell_editable = ecmc_is_cell_editable;
+ etm_class->append_row = ecmc_append_row;
+ etm_class->duplicate_value = ecmc_duplicate_value;
+ etm_class->free_value = ecmc_free_value;
+ etm_class->initialize_value = ecmc_initialize_value;
+ etm_class->value_is_empty = ecmc_value_is_empty;
+ etm_class->value_to_string = ecmc_value_to_string;
+}
+
+static void
+ecmc_init (ECalModelCalendar *model, ECalModelCalendarClass *klass)
+{
+ ECalModelCalendarPrivate *priv;
+
+ priv = g_new0 (ECalModelCalendarPrivate, 1);
+ model->priv = priv;
+
+ e_cal_model_set_component_kind (E_CAL_MODEL (model), ICAL_VEVENT_COMPONENT);
+}
+
+static void
+ecmc_finalize (GObject *object)
+{
+ ECalModelCalendarPrivate *priv;
+ ECalModelCalendar *model = (ECalModelCalendar *) object;
+
+ g_return_if_fail (E_IS_CAL_MODEL_CALENDAR (model));
+
+ priv = model->priv;
+ if (priv) {
+ g_free (priv);
+ model->priv = NULL;
+ }
+
+ if (parent_class->finalize)
+ parent_class->finalize (object);
+}
+
+/* ETableModel methods */
+static int
+ecmc_column_count (ETableModel *etm)
+{
+ return E_CAL_MODEL_CALENDAR_FIELD_LAST;
+}
+
+static ECellDateEditValue *
+get_dtend (ECalModelComponent *comp_data)
+{
+ struct icaltimetype tt_end;
+
+ if (!comp_data->dtend) {
+ icaltimezone *zone;
+
+ tt_end = icalcomponent_get_dtend (comp_data->icalcomp);
+ if (!icaltime_is_valid_time (tt_end))
+ return NULL;
+
+ comp_data->dtend = g_new0 (ECellDateEditValue, 1);
+ comp_data->dtend->tt = tt_end;
+
+ /* FIXME: handle errors */
+ cal_client_get_timezone (comp_data->client,
+ icaltimezone_get_tzid (icaltimezone_get_builtin_timezone (tt_end.zone)),
+ &zone);
+ comp_data->dtend->zone = zone;
+ }
+
+ return comp_data->dtend;
+}
+
+static void *
+get_location (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_LOCATION_PROPERTY);
+ if (prop)
+ return (void *) icalproperty_get_location (prop);
+
+ return NULL;
+}
+
+static void *
+get_transparency (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_TRANSP_PROPERTY);
+ if (prop) {
+ const char *transp;
+
+ transp = icalproperty_get_transp (prop);
+ if (strcasecmp (transp, "TRANSPARENT") == 0)
+ return _("Free");
+ else if (strcasecmp (transp, "OPAQUE") == 0)
+ return _("Busy");
+ }
+
+ return NULL;
+}
+
+static void *
+ecmc_value_at (ETableModel *etm, int col, int row)
+{
+ ECalModelComponent *comp_data;
+ ECalModelCalendarPrivate *priv;
+ ECalModelCalendar *model = (ECalModelCalendar *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_CALENDAR (model), NULL);
+
+ priv = model->priv;
+
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, NULL);
+ g_return_val_if_fail (row >= 0 && row < e_table_model_row_count (etm), NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->value_at (etm, col, row);
+
+ comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
+ if (!comp_data)
+ return "";
+
+ switch (col) {
+ case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
+ return get_dtend (comp_data);
+ case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
+ return get_location (comp_data);
+ case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
+ return get_transparency (comp_data);
+ }
+
+ return "";
+}
+
+static void
+set_dtend (ECalModelComponent *comp_data, const void *value)
+{
+ icalproperty *prop;
+ ECellDateEditValue *dv = (ECellDateEditValue *) value;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DTEND_PROPERTY);
+ if (!dv) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else
+ icalcomponent_set_dtend (comp_data->icalcomp, dv->tt);
+}
+
+static void
+set_location (ECalModelComponent *comp_data, const void *value)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_LOCATION_PROPERTY);
+
+ if (string_is_empty (value)) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else {
+ if (prop)
+ icalproperty_set_location (prop, (const char *) value);
+ else {
+ prop = icalproperty_new_location ((const char *) value);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+ }
+}
+
+static void
+set_transparency (ECalModelComponent *comp_data, const void *value)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_TRANSP_PROPERTY);
+
+ if (string_is_empty (value)) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else {
+ const char *transp;
+
+ if (strcasecmp (value, "FREE"))
+ transp = "TRANSPARENT";
+ else if (strcasecmp (value, "OPAQUE"))
+ transp = "OPAQUE";
+ else {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+
+ return;
+ }
+
+ if (prop)
+ icalproperty_set_transp (prop, transp);
+ else {
+ prop = icalproperty_new_transp (transp);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+ }
+}
+
+static void
+ecmc_set_value_at (ETableModel *etm, int col, int row, const void *value)
+{
+ ECalModelComponent *comp_data;
+ ECalModelCalendar *model = (ECalModelCalendar *) etm;
+
+ g_return_if_fail (E_IS_CAL_MODEL_CALENDAR (model));
+ g_return_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST);
+ g_return_if_fail (row >= 0 && row < e_table_model_row_count (etm));
+
+ if (col < E_CAL_MODEL_FIELD_LAST) {
+ E_TABLE_MODEL_CLASS (parent_class)->set_value_at (etm, col, row, value);
+ return;
+ }
+
+ comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
+ if (!comp_data)
+ return;
+
+ switch (col) {
+ case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
+ set_dtend (comp_data, value);
+ break;
+ case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
+ set_location (comp_data, value);
+ break;
+ case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
+ set_transparency (comp_data, value);
+ break;
+ }
+
+ if (cal_client_update_objects (comp_data->client, comp_data->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
+ g_message ("ecmc_set_value_at(): Could not update the object!");
+}
+
+static gboolean
+ecmc_is_cell_editable (ETableModel *etm, int col, int row)
+{
+ ECalModelCalendar *model = (ECalModelCalendar *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_CALENDAR (model), FALSE);
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, FALSE);
+
+ /* FIXME: We can't check this as 'click-to-add' passes row 0. */
+ /* g_return_val_if_fail (row >= 0 && row < e_table_model_get_row_count (etm), FALSE); */
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->is_cell_editable (etm, col, row);
+
+ switch (col) {
+ case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
+ case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
+ case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ecmc_append_row (ETableModel *etm, ETableModel *source, gint row)
+{
+ ECalModelCalendar *model = (ECalModelCalendar *) etm;
+
+ g_return_if_fail (E_IS_CAL_MODEL_CALENDAR (model));
+
+ /* FIXME: how to chain to ecm_append_row? */
+}
+
+static void *
+ecmc_duplicate_value (ETableModel *etm, int col, const void *value)
+{
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->duplicate_value (etm, col, value);
+
+ switch (col) {
+ case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
+ /* FIXME */
+ break;
+ case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
+ case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
+ return g_strdup (value);
+ }
+
+ return NULL;
+}
+
+static void
+ecmc_free_value (ETableModel *etm, int col, void *value)
+{
+ g_return_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST);
+
+ if (col < E_CAL_MODEL_FIELD_LAST) {
+ E_TABLE_MODEL_CLASS (parent_class)->free_value (etm, col, value);
+ return;
+ }
+
+ switch (col) {
+ case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
+ case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
+ case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
+ if (value)
+ g_free (value);
+ break;
+ }
+}
+
+static void *
+ecmc_initialize_value (ETableModel *etm, int col)
+{
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->initialize_value (etm, col);
+
+ switch (col) {
+ case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
+ return NULL;
+ case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
+ case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
+ return g_strdup ("");
+ }
+
+ return NULL;
+}
+
+static gboolean
+ecmc_value_is_empty (ETableModel *etm, int col, const void *value)
+{
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, TRUE);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->value_is_empty (etm, col, value);
+
+ switch (col) {
+ case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
+ return value ? FALSE : TRUE;
+ case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
+ case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
+ return string_is_empty (value);
+ }
+
+ return TRUE;
+}
+
+static char *
+ecmc_value_to_string (ETableModel *etm, int col, const void *value)
+{
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_CALENDAR_FIELD_LAST, NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->value_to_string (etm, col, value);
+
+ switch (col) {
+ case E_CAL_MODEL_CALENDAR_FIELD_DTEND :
+ return e_cal_model_date_value_to_string (E_CAL_MODEL (etm), value);
+ case E_CAL_MODEL_CALENDAR_FIELD_LOCATION :
+ case E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY :
+ return g_strdup (value);
+ }
+
+ return NULL;
+}
+
+/**
+ * e_cal_model_calendar_new
+ */
+ECalModelCalendar *
+e_cal_model_calendar_new (void)
+{
+ return g_object_new (E_TYPE_CAL_MODEL_CALENDAR, NULL);
+}
diff --git a/calendar/gui/e-cal-model-calendar.h b/calendar/gui/e-cal-model-calendar.h
new file mode 100644
index 0000000000..6ddf312a27
--- /dev/null
+++ b/calendar/gui/e-cal-model-calendar.h
@@ -0,0 +1,58 @@
+/* Evolution calendar - Data model for ETable
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Authors: Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef E_CAL_MODEL_CALENDAR_H
+#define E_CAL_MODEL_CALENDAR_H
+
+#include "e-cal-model.h"
+
+G_BEGIN_DECLS
+
+#define E_TYPE_CAL_MODEL_CALENDAR (e_cal_model_calendar_get_type ())
+#define E_CAL_MODEL_CALENDAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CAL_MODEL_CALENDAR, ECalModelCalendar))
+#define E_CAL_MODEL_CALENDAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CAL_MODEL_CALENDAR, ECalModelCalendarClass))
+#define E_IS_CAL_MODEL_CALENDAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CAL_MODEL_CALENDAR))
+#define E_IS_CAL_MODEL_CALENDAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CAL_MODEL_CALENDAR))
+
+typedef struct _ECalModelCalendarPrivate ECalModelCalendarPrivate;
+
+typedef enum {
+ E_CAL_MODEL_CALENDAR_FIELD_DTEND = E_CAL_MODEL_FIELD_LAST,
+ E_CAL_MODEL_CALENDAR_FIELD_LOCATION,
+ E_CAL_MODEL_CALENDAR_FIELD_TRANSPARENCY,
+ E_CAL_MODEL_CALENDAR_FIELD_LAST
+} ECalModelCalendarField;
+
+typedef struct {
+ ECalModel model;
+ ECalModelCalendarPrivate *priv;
+} ECalModelCalendar;
+
+typedef struct {
+ ECalModelClass parent_class;
+} ECalModelCalendarClass;
+
+GType e_cal_model_calendar_get_type (void);
+ECalModelCalendar *e_cal_model_calendar_new (void);
+
+G_END_DECLS
+
+#endif
diff --git a/calendar/gui/e-cal-model-tasks.c b/calendar/gui/e-cal-model-tasks.c
new file mode 100644
index 0000000000..7c97f5ba01
--- /dev/null
+++ b/calendar/gui/e-cal-model-tasks.c
@@ -0,0 +1,904 @@
+/* Evolution calendar - Data model for ETable
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Authors: Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <math.h>
+#include <gtk/gtkmessagedialog.h>
+#include <libgnome/gnome-i18n.h>
+#include <gal/util/e-util.h>
+#include "e-cal-model-tasks.h"
+#include "e-cell-date-edit-text.h"
+#include "misc.h"
+
+struct _ECalModelTasksPrivate {
+};
+
+static void ecmt_class_init (ECalModelTasksClass *klass);
+static void ecmt_init (ECalModelTasks *model, ECalModelTasksClass *klass);
+static void ecmt_finalize (GObject *object);
+
+static int ecmt_column_count (ETableModel *etm);
+static void *ecmt_value_at (ETableModel *etm, int col, int row);
+static void ecmt_set_value_at (ETableModel *etm, int col, int row, const void *value);
+static gboolean ecmt_is_cell_editable (ETableModel *etm, int col, int row);
+static void ecmt_append_row (ETableModel *etm, ETableModel *source, int row);
+static void *ecmt_duplicate_value (ETableModel *etm, int col, const void *value);
+static void ecmt_free_value (ETableModel *etm, int col, void *value);
+static void *ecmt_initialize_value (ETableModel *etm, int col);
+static gboolean ecmt_value_is_empty (ETableModel *etm, int col, const void *value);
+static char *ecmt_value_to_string (ETableModel *etm, int col, const void *value);
+static const char *ecmt_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data);
+
+static GObjectClass *parent_class = NULL;
+
+E_MAKE_TYPE (e_cal_model_tasks, "ECalModelTasks", ECalModelTasks, ecmt_class_init,
+ ecmt_init, E_TYPE_CAL_MODEL);
+
+static void
+ecmt_class_init (ECalModelTasksClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ ETableModelClass *etm_class = E_TABLE_MODEL_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = ecmt_finalize;
+
+ etm_class->column_count = ecmt_column_count;
+ etm_class->value_at = ecmt_value_at;
+ etm_class->set_value_at = ecmt_set_value_at;
+ etm_class->is_cell_editable = ecmt_is_cell_editable;
+ etm_class->append_row = ecmt_append_row;
+ etm_class->duplicate_value = ecmt_duplicate_value;
+ etm_class->free_value = ecmt_free_value;
+ etm_class->initialize_value = ecmt_initialize_value;
+ etm_class->value_is_empty = ecmt_value_is_empty;
+ etm_class->value_to_string = ecmt_value_to_string;
+}
+
+static void
+ecmt_init (ECalModelTasks *model, ECalModelTasksClass *klass)
+{
+ ECalModelTasksPrivate *priv;
+
+ priv = g_new0 (ECalModelTasksPrivate, 1);
+ model->priv = priv;
+
+ e_cal_model_set_component_kind (E_CAL_MODEL (model), ICAL_VTODO_COMPONENT);
+}
+
+static void
+ecmt_finalize (GObject *object)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelTasks *model = (ECalModelTasks *) object;
+
+ g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
+
+ priv = model->priv;
+ if (priv) {
+ g_free (priv);
+ model->priv = NULL;
+ }
+
+ if (parent_class->finalize)
+ parent_class->finalize (object);
+}
+
+/* ETableModel methods */
+static int
+ecmt_column_count (ETableModel *etm)
+{
+ return E_CAL_MODEL_TASKS_FIELD_LAST;
+}
+
+/* This makes sure a task is marked as complete.
+ It makes sure the "Date Completed" property is set. If the completed_date
+ is not -1, then that is used, otherwise if the "Date Completed" property
+ is not already set it is set to the current time.
+ It makes sure the percent is set to 100, and that the status is "Completed".
+ Note that this doesn't update the component on the server. */
+static void
+ensure_task_complete (ECalModelComponent *comp_data, time_t completed_date)
+{
+ icalproperty *prop;
+ gboolean set_completed = TRUE;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
+
+ /* Date Completed. */
+ if (completed_date == -1) {
+ if (prop)
+ set_completed = FALSE;
+ else
+ completed_date = time (NULL);
+ }
+
+ if (set_completed) {
+ icaltimezone *utc_zone;
+ struct icaltimetype new_completed;
+
+ /* COMPLETED is stored in UTC. */
+ utc_zone = icaltimezone_get_utc_timezone ();
+ new_completed = icaltime_from_timet_with_zone (completed_date,
+ FALSE,
+ utc_zone);
+ if (prop)
+ icalproperty_set_completed (prop, new_completed);
+ else {
+ prop = icalproperty_new_completed (new_completed);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+ }
+
+ /* Percent. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (!prop)
+ icalcomponent_add_property (comp_data->icalcomp, icalproperty_new_percentcomplete (100));
+ else
+ icalproperty_set_percentcomplete (prop, 100);
+
+ /* Status. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
+ if (prop)
+ icalproperty_set_status (prop, ICAL_STATUS_COMPLETED);
+ else
+ icalcomponent_add_property (comp_data->icalcomp, icalproperty_new_status (ICAL_STATUS_COMPLETED));
+}
+
+
+/* This makes sure a task is marked as incomplete. It clears the
+ "Date Completed" property. If the percent is set to 100 it removes it,
+ and if the status is "Completed" it sets it to "Needs Action".
+ Note that this doesn't update the component on the client. */
+static void
+ensure_task_not_complete (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ /* Date Completed. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+
+ /* Percent. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+
+ /* Status. */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (prop)
+ icalproperty_set_status (prop, ICAL_STATUS_NEEDSACTION);
+}
+
+static ECellDateEditValue *
+get_completed (ECalModelComponent *comp_data)
+{
+ /* FIXME */
+
+ return NULL;
+}
+
+static char *
+get_geo (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+ struct icalgeotype geo;
+ static gchar buf[32];
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_GEO_PROPERTY);
+ if (prop) {
+ geo = icalproperty_get_geo (prop);
+ g_snprintf (buf, sizeof (buf), "%g %s, %g %s",
+ fabs (geo.lat),
+ geo.lat >= 0.0 ? _("N") : _("S"),
+ fabs (geo.lon),
+ geo.lon >= 0.0 ? _("E") : _("W"));
+ return buf;
+ }
+
+ return "";
+}
+
+static int
+get_percent (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (prop)
+ return icalproperty_get_percentcomplete (prop);
+
+ return 0;
+}
+
+static char *
+get_priority (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PRIORITY_PROPERTY);
+ if (prop)
+ return cal_util_priority_to_string (icalproperty_get_priority (prop));
+
+ return "";
+}
+
+static char *
+get_status (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
+ if (prop) {
+ switch (icalproperty_get_status (prop)) {
+ case ICAL_STATUS_NONE:
+ return "";
+ case ICAL_STATUS_NEEDSACTION:
+ return _("Not Started");
+ case ICAL_STATUS_INPROCESS:
+ return _("In Progress");
+ case ICAL_STATUS_COMPLETED:
+ return _("Completed");
+ case ICAL_STATUS_CANCELLED:
+ return _("Cancelled");
+ default:
+ g_assert_not_reached ();
+ return NULL;
+ }
+ }
+
+ return "";
+}
+
+static char *
+get_url (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_URL_PROPERTY);
+ if (prop)
+ return (char *) icalproperty_get_url (prop);
+
+ return "";
+}
+
+static gboolean
+is_complete (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_COMPLETED_PROPERTY);
+
+ return prop ? TRUE : FALSE;
+}
+
+typedef enum {
+ E_CAL_MODEL_TASKS_DUE_NEVER,
+ E_CAL_MODEL_TASKS_DUE_FUTURE,
+ E_CAL_MODEL_TASKS_DUE_TODAY,
+ E_CAL_MODEL_TASKS_DUE_OVERDUE,
+ E_CAL_MODEL_TASKS_DUE_COMPLETE
+} ECalModelTasksDueStatus;
+
+
+static ECalModelTasksDueStatus
+get_due_status (ECalModelTasks *model, ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ /* First, do we have a due date? */
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DUE_PROPERTY);
+ if (!prop)
+ return E_CAL_MODEL_TASKS_DUE_NEVER;
+ else {
+ struct icaltimetype now_tt, due_tt;
+ CalClientGetStatus status;
+ icaltimezone *zone;
+
+ /* Second, is it already completed? */
+ if (is_complete (comp_data))
+ return E_CAL_MODEL_TASKS_DUE_COMPLETE;
+
+ /* Third, are we overdue as of right now? */
+ due_tt = icalproperty_get_due (prop);
+ if (due_tt.is_date) {
+ int cmp;
+
+ now_tt = icaltime_current_time_with_zone (e_cal_model_get_timezone (E_CAL_MODEL (model)));
+ cmp = icaltime_compare_date_only (due_tt, now_tt);
+
+ if (cmp < 0)
+ return E_CAL_MODEL_TASKS_DUE_OVERDUE;
+ else if (cmp == 0)
+ return E_CAL_MODEL_TASKS_DUE_TODAY;
+ else
+ return E_CAL_MODEL_TASKS_DUE_FUTURE;
+ } else {
+ /* Get the current time in the same timezone as the DUE date.*/
+ status = cal_client_get_timezone (comp_data->client,
+ icaltimezone_get_tzid (icaltimezone_get_builtin_timezone (due_tt.zone)),
+ &zone);
+ if (status != CAL_CLIENT_GET_SUCCESS)
+ return E_CAL_MODEL_TASKS_DUE_FUTURE;
+
+ now_tt = icaltime_current_time_with_zone (zone);
+
+ if (icaltime_compare (due_tt, now_tt) <= 0)
+ return E_CAL_MODEL_TASKS_DUE_OVERDUE;
+ else
+ if (icaltime_compare_date_only (due_tt, now_tt) == 0)
+ return E_CAL_MODEL_TASKS_DUE_TODAY;
+ else
+ return E_CAL_MODEL_TASKS_DUE_FUTURE;
+ }
+ }
+
+ return E_CAL_MODEL_TASKS_DUE_NEVER;
+}
+
+static gboolean
+is_overdue (ECalModelTasks *model, ECalModelComponent *comp_data)
+{
+ switch (get_due_status (model, comp_data)) {
+ case E_CAL_MODEL_TASKS_DUE_NEVER:
+ case E_CAL_MODEL_TASKS_DUE_FUTURE:
+ case E_CAL_MODEL_TASKS_DUE_COMPLETE:
+ return FALSE;
+ case E_CAL_MODEL_TASKS_DUE_TODAY:
+ case E_CAL_MODEL_TASKS_DUE_OVERDUE:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void *
+ecmt_value_at (ETableModel *etm, int col, int row)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelComponent *comp_data;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
+
+ priv = model->priv;
+
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
+ g_return_val_if_fail (row >= 0 && row < e_table_model_row_count (etm), NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->value_at (etm, col, row);
+
+ comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
+ if (!comp_data)
+ return "";
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ return get_completed (comp_data);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ return GINT_TO_POINTER (is_complete (comp_data));
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ /* FIXME */
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ return get_geo (comp_data);
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return GINT_TO_POINTER (is_overdue (model, comp_data));
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ return GINT_TO_POINTER (get_percent (comp_data));
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ return get_priority (comp_data);
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ return get_status (comp_data);
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return get_url (comp_data);
+ }
+
+ return "";
+}
+
+static void
+set_completed (ECalModelTasks *model, ECalModelComponent *comp_data, const void *value)
+{
+ ECellDateEditValue *dv = (ECellDateEditValue *) value;
+
+ if (!dv)
+ ensure_task_not_complete (comp_data);
+ else {
+ time_t t;
+
+ if (dv->tt.is_date) {
+ /* if it's a date, it will be floating,
+ but completed needs a date time value */
+ dv->tt.is_date = FALSE;
+ t = icaltime_as_timet_with_zone (dv->tt, e_cal_model_get_timezone (E_CAL_MODEL (model)));
+ } else {
+ /* we assume that COMPLETED is entered in the current timezone,
+ even though it gets stored in UTC */
+ t = icaltime_as_timet_with_zone (dv->tt, dv->zone);
+ }
+
+ ensure_task_complete (comp_data, t);
+ }
+}
+
+static void
+set_complete (ECalModelComponent *comp_data, const void *value)
+{
+ gint state = GPOINTER_TO_INT (value);
+
+ if (state)
+ ensure_task_complete (comp_data, -1);
+ else
+ ensure_task_not_complete (comp_data);
+}
+
+/* FIXME: We need to set the "transient_for" property for the dialog, but the
+ * model doesn't know anything about the windows.
+ */
+static void
+show_geo_warning (void)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ _("The geographical position must be entered "
+ "in the format: \n\n45.436845,125.862501"));
+ gtk_widget_show (dialog);
+}
+
+static void
+set_geo (ECalModelComponent *comp_data, const char *value)
+{
+ double latitude, longitude;
+ int matched;
+ struct icalgeotype geo;
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_GEO_PROPERTY);
+
+ if (string_is_empty (value)) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else {
+ matched = sscanf (value, "%lg , %lg", &latitude, &longitude);
+ if (matched != 2)
+ show_geo_warning ();
+
+ geo.lat = latitude;
+ geo.lon = longitude;
+ if (prop)
+ icalproperty_set_geo (prop, geo);
+ else {
+ prop = icalproperty_new_geo (geo);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+
+ }
+}
+
+static void
+set_status (ECalModelComponent *comp_data, const char *value)
+{
+ icalproperty_status status;
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_STATUS_PROPERTY);
+
+ /* an empty string is the same as 'None' */
+ if (!value[0] || !g_strcasecmp (value, _("None")))
+ status = ICAL_STATUS_NONE;
+ else if (!g_strcasecmp (value, _("Not Started")))
+ status = ICAL_STATUS_NEEDSACTION;
+ else if (!g_strcasecmp (value, _("In Progress")))
+ status = ICAL_STATUS_INPROCESS;
+ else if (!g_strcasecmp (value, _("Completed")))
+ status = ICAL_STATUS_COMPLETED;
+ else if (!g_strcasecmp (value, _("Cancelled")))
+ status = ICAL_STATUS_CANCELLED;
+ else {
+ g_warning ("Invalid status: %s\n", value);
+ return;
+ }
+
+ if (prop)
+ icalproperty_set_status (prop, status);
+ else {
+ prop = icalproperty_new_status (status);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+
+/* if (status == ICAL_STATUS_NEEDSACTION) { */
+/* percent = 0; */
+/* cal_component_set_percent (comp, &percent); */
+/* cal_component_set_completed (comp, NULL); */
+/* } else if (status == ICAL_STATUS_INPROCESS) { */
+/* ensure_task_not_complete (comp); */
+/* percent = 50; */
+/* cal_component_set_percent (comp, &percent); */
+/* } else if (status == ICAL_STATUS_COMPLETED) { */
+/* ensure_task_complete (comp, -1); */
+/* } */
+}
+
+static void
+set_percent (ECalModelComponent *comp_data, const void *value)
+{
+ icalproperty *prop;
+ gint percent = GPOINTER_TO_INT (value);
+
+ g_return_if_fail (percent >= -1);
+ g_return_if_fail (percent <= 100);
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+
+ /* A value of -1 means it isn't set */
+ if (percent == -1) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ ensure_task_not_complete (comp_data);
+ } else {
+ if (prop)
+ icalproperty_set_percentcomplete (prop, percent);
+ else {
+ prop = icalproperty_new_percentcomplete (percent);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+
+ if (percent == 100)
+ ensure_task_complete (comp_data, -1);
+ else {
+ ensure_task_not_complete (comp_data);
+ if (percent > 0)
+ set_status (comp_data, _("In Progress"));
+ }
+ }
+
+}
+
+static void
+set_priority (ECalModelComponent *comp_data, const char *value)
+{
+ icalproperty *prop;
+ int priority;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_PRIORITY_PROPERTY);
+
+ priority = cal_util_priority_from_string (value);
+ if (priority == -1) {
+ g_warning ("Invalid priority");
+ priority = 0;
+ }
+
+ if (prop)
+ icalproperty_set_priority (prop, priority);
+ else {
+ prop = icalproperty_new_priority (priority);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+}
+
+static void
+set_url (ECalModelComponent *comp_data, const char *value)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_URL_PROPERTY);
+
+ if (string_is_empty (value)) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else {
+ if (prop)
+ icalproperty_set_url (prop, value);
+ else {
+ prop = icalproperty_new_url (value);
+ icalcomponent_add_property (comp_data->icalcomp, prop);
+ }
+ }
+}
+
+static void
+ecmt_set_value_at (ETableModel *etm, int col, int row, const void *value)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelComponent *comp_data;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
+
+ priv = model->priv;
+
+ g_return_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST);
+ g_return_if_fail (row >= 0 && row < e_table_model_row_count (etm));
+
+ if (col < E_CAL_MODEL_FIELD_LAST) {
+ E_TABLE_MODEL_CLASS (parent_class)->set_value_at (etm, col, row, value);
+ return;
+ }
+
+ comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row);
+ if (!comp_data)
+ return;
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ set_completed (model, comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ set_complete (comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ /* FIXME */
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ set_geo (comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ set_percent (comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ set_priority (comp_data, value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ set_url (comp_data, value);
+ break;
+ }
+
+ if (cal_client_update_objects (comp_data->client, comp_data->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
+ g_message ("ecmt_set_value_at(): Could not update the object!");
+}
+
+static gboolean
+ecmt_is_cell_editable (ETableModel *etm, int col, int row)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), FALSE);
+
+ priv = model->priv;
+
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, FALSE);
+
+ /* FIXME: We can't check this as 'click-to-add' passes row 0. */
+ /* g_return_val_if_fail (row >= 0 && row < e_table_model_get_row_count (etm), FALSE); */
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->is_cell_editable (etm, col, row);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ecmt_append_row (ETableModel *etm, ETableModel *source, gint row)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_if_fail (E_IS_CAL_MODEL_TASKS (model));
+
+ priv = model->priv;
+
+ /* FIXME: how to chain to ecm_append_row? */
+}
+
+static void *
+ecmt_duplicate_value (ETableModel *etm, int col, const void *value)
+{
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->duplicate_value (etm, col, value);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return g_strdup (value);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ /* FIXME */
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return (void *) value;
+ }
+
+ return NULL;
+}
+
+static void
+ecmt_free_value (ETableModel *etm, int col, void *value)
+{
+ g_return_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST);
+
+ if (col < E_CAL_MODEL_FIELD_LAST) {
+ E_TABLE_MODEL_CLASS (parent_class)->free_value (etm, col, value);
+ return;
+ }
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ if (value)
+ g_free (value);
+ break;
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ break;
+ }
+}
+
+static void *
+ecmt_initialize_value (ETableModel *etm, int col)
+{
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->initialize_value (etm, col);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return g_strdup ("");
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return NULL;
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ return GINT_TO_POINTER (-1);
+ }
+
+ return NULL;
+}
+
+static gboolean
+ecmt_value_is_empty (ETableModel *etm, int col, const void *value)
+{
+ ECalModelTasksPrivate *priv;
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), TRUE);
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, TRUE);
+
+ priv = model->priv;
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->value_is_empty (etm, col, value);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return string_is_empty (value);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ return value ? FALSE : TRUE;
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ return (GPOINTER_TO_INT (value) < 0) ? TRUE : FALSE;
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+static char *
+ecmt_value_to_string (ETableModel *etm, int col, const void *value)
+{
+ ECalModelTasks *model = (ECalModelTasks *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_TASKS_FIELD_LAST, NULL);
+
+ if (col < E_CAL_MODEL_FIELD_LAST)
+ return E_TABLE_MODEL_CLASS (parent_class)->value_to_string (etm, col, value);
+
+ switch (col) {
+ case E_CAL_MODEL_TASKS_FIELD_GEO :
+ case E_CAL_MODEL_TASKS_FIELD_PRIORITY :
+ case E_CAL_MODEL_TASKS_FIELD_STATUS :
+ case E_CAL_MODEL_TASKS_FIELD_URL :
+ return g_strdup (value);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETED :
+ case E_CAL_MODEL_TASKS_FIELD_DUE :
+ return e_cal_model_date_value_to_string (E_CAL_MODEL (model), value);
+ case E_CAL_MODEL_TASKS_FIELD_COMPLETE :
+ case E_CAL_MODEL_TASKS_FIELD_OVERDUE :
+ return value ? _("Yes") : _("No");
+ case E_CAL_MODEL_TASKS_FIELD_PERCENT :
+ if (GPOINTER_TO_INT (value) < 0)
+ return g_strdup ("N/A");
+ else
+ return g_strdup_printf ("%i%%", GPOINTER_TO_INT (value));
+ }
+
+ return NULL;
+}
+
+static const char *
+ecmt_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data)
+{
+ g_return_val_if_fail (E_IS_CAL_MODEL_TASKS (model), NULL);
+ g_return_val_if_fail (comp_data != NULL, NULL);
+
+ switch (get_due_status ((ECalModelTasks *) model, comp_data)) {
+ case E_CAL_MODEL_TASKS_DUE_NEVER:
+ case E_CAL_MODEL_TASKS_DUE_FUTURE:
+ case E_CAL_MODEL_TASKS_DUE_COMPLETE:
+ return NULL;
+ case E_CAL_MODEL_TASKS_DUE_TODAY:
+ return calendar_config_get_tasks_due_today_color ();
+ case E_CAL_MODEL_TASKS_DUE_OVERDUE:
+ return calendar_config_get_tasks_overdue_color ();
+ }
+
+ return NULL;
+}
+
+/**
+ * e_cal_model_tasks_new
+ */
+ECalModelTasks *
+e_cal_model_tasks_new (void)
+{
+ return g_object_new (E_TYPE_CAL_MODEL_TASKS, NULL);
+}
diff --git a/calendar/gui/e-cal-model-tasks.h b/calendar/gui/e-cal-model-tasks.h
new file mode 100644
index 0000000000..852484dcc6
--- /dev/null
+++ b/calendar/gui/e-cal-model-tasks.h
@@ -0,0 +1,64 @@
+/* Evolution calendar - Data model for ETable
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Authors: Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef E_CAL_MODEL_TASKS_H
+#define E_CAL_MODEL_TASKS_H
+
+#include "e-cal-model.h"
+
+G_BEGIN_DECLS
+
+#define E_TYPE_CAL_MODEL_TASKS (e_cal_model_tasks_get_type ())
+#define E_CAL_MODEL_TASKS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CAL_MODEL_TASKS, ECalModelTasks))
+#define E_CAL_MODEL_TASKS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CAL_MODEL_TASKS, ECalModelTasksClass))
+#define E_IS_CAL_MODEL_TASKS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CAL_MODEL_TASKS))
+#define E_IS_CAL_MODEL_TASKS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CAL_MODEL_TASKS))
+
+typedef struct _ECalModelTasksPrivate ECalModelTasksPrivate;
+
+typedef enum {
+ E_CAL_MODEL_TASKS_FIELD_COMPLETED = E_CAL_MODEL_FIELD_LAST,
+ E_CAL_MODEL_TASKS_FIELD_COMPLETE,
+ E_CAL_MODEL_TASKS_FIELD_DUE,
+ E_CAL_MODEL_TASKS_FIELD_GEO,
+ E_CAL_MODEL_TASKS_FIELD_OVERDUE,
+ E_CAL_MODEL_TASKS_FIELD_PERCENT,
+ E_CAL_MODEL_TASKS_FIELD_PRIORITY,
+ E_CAL_MODEL_TASKS_FIELD_STATUS,
+ E_CAL_MODEL_TASKS_FIELD_URL,
+ E_CAL_MODEL_TASKS_FIELD_LAST
+} ECalModelTasksField;
+
+typedef struct {
+ ECalModel model;
+ ECalModelTasksPrivate *priv;
+} ECalModelTasks;
+
+typedef struct {
+ ECalModelClass parent_class;
+} ECalModelTasksClass;
+
+GType e_cal_model_tasks_get_type (void);
+ECalModelTasks *e_cal_model_tasks_new (void);
+
+G_END_DECLS
+
+#endif
diff --git a/calendar/gui/e-cal-model.c b/calendar/gui/e-cal-model.c
new file mode 100644
index 0000000000..a184fabe48
--- /dev/null
+++ b/calendar/gui/e-cal-model.c
@@ -0,0 +1,1303 @@
+/* Evolution calendar - Data model for ETable
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Authors: Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <glib/garray.h>
+#include <libgnome/gnome-i18n.h>
+#include <gal/util/e-util.h>
+#include <e-util/e-time-utils.h>
+#include <cal-util/timeutil.h>
+#include "calendar-config.h"
+#include "e-cal-model.h"
+#include "itip-utils.h"
+#include "misc.h"
+
+typedef struct {
+ CalClient *client;
+ CalQuery *query;
+} ECalModelClient;
+
+struct _ECalModelPrivate {
+ /* The list of clients we are managing. Each element is of type ECalModelClient */
+ GList *clients;
+
+ /* Array for storing the objects. Each element is of type ECalModelComponent */
+ GPtrArray *objects;
+
+ icalcomponent_kind kind;
+ icaltimezone *zone;
+
+ /* The search regular expression */
+ gchar *sexp;
+
+ /* The default category */
+ gchar *default_category;
+
+ /* Addresses for determining icons */
+ EAccountList *accounts;
+};
+
+static void e_cal_model_class_init (ECalModelClass *klass);
+static void e_cal_model_init (ECalModel *model, ECalModelClass *klass);
+static void e_cal_model_finalize (GObject *object);
+
+static int ecm_column_count (ETableModel *etm);
+static int ecm_row_count (ETableModel *etm);
+static void *ecm_value_at (ETableModel *etm, int col, int row);
+static void ecm_set_value_at (ETableModel *etm, int col, int row, const void *value);
+static gboolean ecm_is_cell_editable (ETableModel *etm, int col, int row);
+static void ecm_append_row (ETableModel *etm, ETableModel *source, int row);
+static void *ecm_duplicate_value (ETableModel *etm, int col, const void *value);
+static void ecm_free_value (ETableModel *etm, int col, void *value);
+static void *ecm_initialize_value (ETableModel *etm, int col);
+static gboolean ecm_value_is_empty (ETableModel *etm, int col, const void *value);
+static char *ecm_value_to_string (ETableModel *etm, int col, const void *value);
+
+static const char *ecm_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data);
+
+static GObjectClass *parent_class = NULL;
+
+E_MAKE_TYPE (e_cal_model, "ECalModel", ECalModel, e_cal_model_class_init,
+ e_cal_model_init, E_TABLE_MODEL_TYPE);
+
+static void
+e_cal_model_class_init (ECalModelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ ETableModelClass *etm_class = E_TABLE_MODEL_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = e_cal_model_finalize;
+
+ etm_class->column_count = ecm_column_count;
+ etm_class->row_count = ecm_row_count;
+ etm_class->value_at = ecm_value_at;
+ etm_class->set_value_at = ecm_set_value_at;
+ etm_class->is_cell_editable = ecm_is_cell_editable;
+ etm_class->append_row = ecm_append_row;
+ etm_class->duplicate_value = ecm_duplicate_value;
+ etm_class->free_value = ecm_free_value;
+ etm_class->initialize_value = ecm_initialize_value;
+ etm_class->value_is_empty = ecm_value_is_empty;
+ etm_class->value_to_string = ecm_value_to_string;
+
+ klass->get_color_for_component = ecm_get_color_for_component;
+}
+
+static void
+e_cal_model_init (ECalModel *model, ECalModelClass *klass)
+{
+ ECalModelPrivate *priv;
+
+ priv = g_new0 (ECalModelPrivate, 1);
+ model->priv = priv;
+
+ priv->sexp = g_strdup ("#t"); /* match all by default */
+
+ priv->objects = g_ptr_array_new ();
+ priv->kind = ICAL_NO_COMPONENT;
+
+ priv->accounts = itip_addresses_get ();
+}
+
+static void
+free_comp_data (ECalModelComponent *comp_data)
+{
+ g_return_if_fail (comp_data != NULL);
+
+ comp_data->client = NULL;
+
+ if (comp_data->icalcomp) {
+ icalcomponent_free (comp_data->icalcomp);
+ comp_data->icalcomp = NULL;
+ }
+
+ if (comp_data->dtstart) {
+ g_free (comp_data->dtstart);
+ comp_data->dtstart = NULL;
+ }
+
+ if (comp_data->dtend) {
+ g_free (comp_data->dtend);
+ comp_data->dtend = NULL;
+ }
+
+ g_free (comp_data);
+}
+
+static void
+clear_objects_array (ECalModelPrivate *priv)
+{
+ gint i;
+
+ for (i = 0; i < priv->objects->len; i++) {
+ ECalModelComponent *comp_data;
+
+ comp_data = g_ptr_array_index (priv->objects, i);
+ g_assert (comp_data != NULL);
+ free_comp_data (comp_data);
+ }
+
+
+ g_ptr_array_set_size (priv->objects, 0);
+}
+
+static void
+e_cal_model_finalize (GObject *object)
+{
+ ECalModelPrivate *priv;
+ ECalModel *model = (ECalModel *) object;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ priv = model->priv;
+ if (priv) {
+ if (priv->clients) {
+ e_cal_model_remove_all_clients (model);
+ priv->clients = NULL;
+ }
+
+ if (priv->sexp) {
+ g_free (priv->sexp);
+ priv->sexp = NULL;
+ }
+
+ if (priv->default_category) {
+ g_free (priv->default_category);
+ priv->default_category = NULL;
+ }
+
+ if (priv->objects) {
+ clear_objects_array (priv);
+ g_ptr_array_free (priv->objects, FALSE);
+ priv->objects = NULL;
+ }
+
+ if (priv->accounts) {
+ g_object_unref (priv->accounts);
+ priv->accounts = NULL;
+ }
+
+ g_free (priv);
+ model->priv = NULL;
+ }
+
+ if (parent_class->finalize)
+ parent_class->finalize (object);
+}
+
+/* ETableModel methods */
+
+static int
+ecm_column_count (ETableModel *etm)
+{
+ return E_CAL_MODEL_FIELD_LAST;
+}
+
+static int
+ecm_row_count (ETableModel *etm)
+{
+ ECalModelPrivate *priv;
+ ECalModel *model = (ECalModel *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), -1);
+
+ priv = model->priv;
+
+ return priv->objects->len;
+}
+
+static char *
+get_categories (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CATEGORIES_PROPERTY);
+ if (prop)
+ return (char *) icalproperty_get_categories (prop);
+
+ return "";
+}
+
+static char *
+get_classification (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_CLASS_PROPERTY);
+
+ if (prop)
+ return (char *) icalproperty_get_class (prop);
+
+ return _("Public");
+}
+
+static const char *
+get_color (ECalModel *model, ECalModelComponent *comp_data)
+{
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
+
+ return e_cal_model_get_color_for_component (model, comp_data);
+}
+
+static char *
+get_description (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+ static GString *str = NULL;
+
+ if (str)
+ g_string_free (str, TRUE);
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DESCRIPTION_PROPERTY);
+ if (prop) {
+ str = g_string_new ("");
+ do {
+ str = g_string_append (str, icalproperty_get_description (prop));
+ } while ((prop = icalcomponent_get_next_property (comp_data->icalcomp, ICAL_DESCRIPTION_PROPERTY)));
+
+ return str->str;
+ }
+
+ return "";
+}
+
+static ECellDateEditValue*
+get_dtstart (ECalModel *model, ECalModelComponent *comp_data)
+{
+ ECalModelPrivate *priv;
+ struct icaltimetype tt_start;
+
+ priv = model->priv;
+
+ if (!comp_data->dtstart) {
+ icaltimezone *zone;
+
+ tt_start = icalcomponent_get_dtstart (comp_data->icalcomp);
+ if (!icaltime_is_valid_time (tt_start))
+ return NULL;
+
+ comp_data->dtstart = g_new0 (ECellDateEditValue, 1);
+ comp_data->dtstart->tt = tt_start;
+
+ /* FIXME: handle errors */
+ cal_client_get_timezone (comp_data->client,
+ icaltimezone_get_tzid (icaltimezone_get_builtin_timezone (tt_start.zone)),
+ &zone);
+ comp_data->dtstart->zone = zone;
+ }
+
+ return comp_data->dtstart;
+}
+
+static char *
+get_summary (ECalModelComponent *comp_data)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_SUMMARY_PROPERTY);
+ if (prop)
+ return (char *) icalproperty_get_summary (prop);
+
+ return "";
+}
+
+static char *
+get_uid (ECalModelComponent *comp_data)
+{
+ return (char *) icalcomponent_get_uid (comp_data->icalcomp);
+}
+
+static void *
+ecm_value_at (ETableModel *etm, int col, int row)
+{
+ ECalModelPrivate *priv;
+ ECalModelComponent *comp_data;
+ ECalModel *model = (ECalModel *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
+
+ priv = model->priv;
+
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
+ g_return_val_if_fail (row >= 0 && row < priv->objects->len, NULL);
+
+ comp_data = g_ptr_array_index (priv->objects, row);
+ g_assert (comp_data != NULL);
+
+ switch (col) {
+ case E_CAL_MODEL_FIELD_CATEGORIES :
+ return get_categories (comp_data);
+ case E_CAL_MODEL_FIELD_CLASSIFICATION :
+ return get_classification (comp_data);
+ case E_CAL_MODEL_FIELD_COLOR :
+ return GINT_TO_POINTER (get_color (model, comp_data));
+ case E_CAL_MODEL_FIELD_COMPONENT :
+ return comp_data->icalcomp;
+ case E_CAL_MODEL_FIELD_DESCRIPTION :
+ return get_description (comp_data);
+ case E_CAL_MODEL_FIELD_DTSTART :
+ return get_dtstart (model, comp_data);
+ case E_CAL_MODEL_FIELD_HAS_ALARMS :
+ return GINT_TO_POINTER ((icalcomponent_get_first_component (comp_data->icalcomp,
+ ICAL_VALARM_COMPONENT) != NULL));
+ case E_CAL_MODEL_FIELD_ICON :
+ {
+ CalComponent *comp;
+ icalcomponent *icalcomp;
+ gint retval = 0;
+
+ comp = cal_component_new ();
+ icalcomp = icalcomponent_new_clone (comp_data->icalcomp);
+ if (cal_component_set_icalcomponent (comp, icalcomp)) {
+ if (cal_component_has_recurrences (comp))
+ retval = 1;
+ else if (itip_organizer_is_user (comp, comp_data->client))
+ retval = 3;
+ else {
+ GSList *attendees = NULL, *sl;
+
+ cal_component_get_attendee_list (comp, &attendees);
+ for (sl = attendees; sl != NULL; sl = sl->next) {
+ CalComponentAttendee *ca = sl->data;
+ const char *text;
+
+ text = itip_strip_mailto (ca->value);
+ if (e_account_list_find (priv->accounts, E_ACCOUNT_FIND_ID_ADDRESS, text) != NULL) {
+ if (ca->delto != NULL)
+ retval = 3;
+ else
+ retval = 2;
+ break;
+ }
+ }
+
+ cal_component_free_attendee_list (attendees);
+ }
+ } else
+ icalcomponent_free (icalcomp);
+
+ g_object_unref (comp);
+
+ return GINT_TO_POINTER (retval);
+ }
+ case E_CAL_MODEL_FIELD_SUMMARY :
+ return get_summary (comp_data);
+ case E_CAL_MODEL_FIELD_UID :
+ return get_uid (comp_data);
+ }
+
+ return "";
+}
+
+static void
+set_categories (icalcomponent *icalcomp, const char *value)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_CATEGORIES_PROPERTY);
+ if (!value || !(*value)) {
+ if (prop) {
+ icalcomponent_remove_property (icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else {
+ if (!prop) {
+ prop = icalproperty_new_categories (value);
+ icalcomponent_add_property (icalcomp, prop);
+ } else
+ icalproperty_set_categories (prop, value);
+ }
+}
+
+static void
+set_classification (icalcomponent *icalcomp, const char *value)
+{
+ icalproperty *prop;
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
+ if (!value || !(*value)) {
+ if (prop) {
+ icalcomponent_remove_property (icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else {
+ if (!prop) {
+ prop = icalproperty_new_class (value);
+ icalcomponent_add_property (icalcomp, prop);
+ } else
+ icalproperty_set_class (prop, value);
+ }
+}
+
+static void
+set_description (icalcomponent *icalcomp, const char *value)
+{
+ icalproperty *prop;
+
+ /* remove old description(s) */
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_DESCRIPTION_PROPERTY);
+ while (prop) {
+ icalproperty *next;
+
+ next = icalcomponent_get_next_property (icalcomp, ICAL_DESCRIPTION_PROPERTY);
+
+ icalcomponent_remove_property (icalcomp, prop);
+ icalproperty_free (prop);
+
+ prop = next;
+ }
+
+ /* now add the new description */
+ if (!value || !(*value))
+ return;
+
+ prop = icalproperty_new_description (value);
+ icalcomponent_add_property (icalcomp, prop);
+}
+
+static void
+set_dtstart (ECalModel *model, ECalModelComponent *comp_data, const void *value)
+{
+ icalproperty *prop;
+ ECellDateEditValue *dv = (ECellDateEditValue *) value;
+
+ prop = icalcomponent_get_first_property (comp_data->icalcomp, ICAL_DTSTART_PROPERTY);
+ if (!dv) {
+ if (prop) {
+ icalcomponent_remove_property (comp_data->icalcomp, prop);
+ icalproperty_free (prop);
+ }
+ } else
+ icalcomponent_set_dtstart (comp_data->icalcomp, dv->tt);
+}
+
+static void
+set_summary (icalcomponent *icalcomp, const char *value)
+{
+ icalcomponent_set_summary (icalcomp, value);
+}
+
+static void
+ecm_set_value_at (ETableModel *etm, int col, int row, const void *value)
+{
+ ECalModelPrivate *priv;
+ ECalModelComponent *comp_data;
+ ECalModel *model = (ECalModel *) etm;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ priv = model->priv;
+
+ g_return_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST);
+ g_return_if_fail (row >= 0 && row < priv->objects->len);
+
+ comp_data = g_ptr_array_index (priv->objects, row);
+ g_assert (comp_data != NULL);
+
+ switch (col) {
+ case E_CAL_MODEL_FIELD_CATEGORIES :
+ set_categories (comp_data, value);
+ case E_CAL_MODEL_FIELD_CLASSIFICATION :
+ set_classification (comp_data, value);
+ case E_CAL_MODEL_FIELD_DESCRIPTION :
+ set_description (comp_data, value);
+ case E_CAL_MODEL_FIELD_DTSTART :
+ set_dtstart (model, comp_data, value);
+ case E_CAL_MODEL_FIELD_SUMMARY :
+ set_summary (comp_data, value);
+ }
+
+ if (cal_client_update_objects (comp_data->client, comp_data->icalcomp) != CAL_CLIENT_RESULT_SUCCESS)
+ g_message ("ecm_set_value_at(): Could not update the object!");
+}
+
+static gboolean
+ecm_is_cell_editable (ETableModel *etm, int col, int row)
+{
+ ECalModelPrivate *priv;
+ ECalModel *model = (ECalModel *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), FALSE);
+
+ priv = model->priv;
+
+ g_return_val_if_fail (col >= 0 && col <= E_CAL_MODEL_FIELD_LAST, FALSE);
+
+ /* FIXME: We can't check this as 'click-to-add' passes row 0. */
+ /*g_return_val_if_fail (row >= 0 && row < priv->objects->len, FALSE);*/
+
+ switch (col) {
+ case E_CAL_MODEL_FIELD_CATEGORIES :
+ case E_CAL_MODEL_FIELD_CLASSIFICATION :
+ case E_CAL_MODEL_FIELD_DESCRIPTION :
+ case E_CAL_MODEL_FIELD_DTSTART :
+ case E_CAL_MODEL_FIELD_SUMMARY :
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+ecm_append_row (ETableModel *etm, ETableModel *source, int row)
+{
+ ECalModelComponent *comp_data;
+ icalcomponent *icalcomp;
+ ECalModel *source_model = (ECalModel *) source;
+ ECalModel *model = (ECalModel *) etm;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+ g_return_if_fail (E_IS_CAL_MODEL (source_model));
+
+ comp_data = g_ptr_array_index (source_model->priv->objects, row);
+ g_assert (comp_data != NULL);
+
+ /* guard against saving before the calendar is open */
+ if (!(comp_data->client && cal_client_get_load_state (comp_data->client) == CAL_CLIENT_LOAD_LOADED))
+ return;
+
+ icalcomp = e_cal_model_create_component_with_defaults (model);
+
+ set_categories (icalcomp, e_table_model_value_at (source, E_CAL_MODEL_FIELD_CATEGORIES, row));
+ set_classification (icalcomp, e_table_model_value_at (source, E_CAL_MODEL_FIELD_CLASSIFICATION, row));
+ set_description (icalcomp, e_table_model_value_at (source, E_CAL_MODEL_FIELD_DESCRIPTION, row));
+ set_summary (icalcomp, e_table_model_value_at (source, E_CAL_MODEL_FIELD_SUMMARY, row));
+
+ if (cal_client_update_objects (comp_data->client, icalcomp) != CAL_CLIENT_RESULT_SUCCESS) {
+ /* FIXME: show error dialog */
+ }
+
+ icalcomponent_free (icalcomp);
+}
+
+static void *
+ecm_duplicate_value (ETableModel *etm, int col, const void *value)
+{
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
+
+ switch (col) {
+ case E_CAL_MODEL_FIELD_CATEGORIES :
+ case E_CAL_MODEL_FIELD_CLASSIFICATION :
+ case E_CAL_MODEL_FIELD_SUMMARY :
+ return g_strdup (value);
+ case E_CAL_MODEL_FIELD_HAS_ALARMS :
+ case E_CAL_MODEL_FIELD_ICON :
+ case E_CAL_MODEL_FIELD_COLOR :
+ return (void *) value;
+ case E_CAL_MODEL_FIELD_COMPONENT :
+ return icalcomponent_new_clone ((icalcomponent *) value);
+ case E_CAL_MODEL_FIELD_DTSTART :
+ if (value) {
+ ECellDateEditValue *dv, *orig_dv;
+
+ orig_dv = (ECellDateEditValue *) value;
+ dv = g_new0 (ECellDateEditValue, 1);
+ *dv = *orig_dv;
+
+ return dv;
+ }
+ break;
+ }
+
+ return NULL;
+}
+
+static void
+ecm_free_value (ETableModel *etm, int col, void *value)
+{
+ g_return_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST);
+
+ switch (col) {
+ case E_CAL_MODEL_FIELD_CATEGORIES :
+ case E_CAL_MODEL_FIELD_DESCRIPTION :
+ case E_CAL_MODEL_FIELD_SUMMARY :
+ if (value)
+ g_free (value);
+ break;
+ case E_CAL_MODEL_FIELD_CLASSIFICATION :
+ case E_CAL_MODEL_FIELD_HAS_ALARMS :
+ case E_CAL_MODEL_FIELD_ICON :
+ case E_CAL_MODEL_FIELD_COLOR :
+ break;
+ case E_CAL_MODEL_FIELD_DTSTART :
+ if (value)
+ g_free (value);
+ break;
+ case E_CAL_MODEL_FIELD_COMPONENT :
+ if (value)
+ icalcomponent_free ((icalcomponent *) value);
+ break;
+ }
+}
+
+static void *
+ecm_initialize_value (ETableModel *etm, int col)
+{
+ ECalModelPrivate *priv;
+ ECalModel *model = (ECalModel *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
+
+ priv = model->priv;
+
+ switch (col) {
+ case E_CAL_MODEL_FIELD_CATEGORIES :
+ return g_strdup (priv->default_category);
+ case E_CAL_MODEL_FIELD_CLASSIFICATION :
+ case E_CAL_MODEL_FIELD_DESCRIPTION :
+ case E_CAL_MODEL_FIELD_SUMMARY :
+ return g_strdup ("");
+ case E_CAL_MODEL_FIELD_DTSTART :
+ case E_CAL_MODEL_FIELD_HAS_ALARMS :
+ case E_CAL_MODEL_FIELD_ICON :
+ case E_CAL_MODEL_FIELD_COLOR :
+ case E_CAL_MODEL_FIELD_COMPONENT :
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static gboolean
+ecm_value_is_empty (ETableModel *etm, int col, const void *value)
+{
+ ECalModelPrivate *priv;
+ ECalModel *model = (ECalModel *) etm;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), TRUE);
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, TRUE);
+
+ priv = model->priv;
+
+ switch (col) {
+ case E_CAL_MODEL_FIELD_CATEGORIES :
+ /* This could be a hack or not. If the categories field only
+ * contains the default category, then it possibly means that
+ * the user has not entered anything at all in the click-to-add;
+ * the category is in the value because we put it there in
+ * calendar_model_initialize_value().
+ */
+ if (priv->default_category && value && strcmp (priv->default_category, value) == 0)
+ return TRUE;
+ else
+ return string_is_empty (value);
+ case E_CAL_MODEL_FIELD_CLASSIFICATION :
+ case E_CAL_MODEL_FIELD_DESCRIPTION :
+ case E_CAL_MODEL_FIELD_SUMMARY :
+ return string_is_empty (value);
+ case E_CAL_MODEL_FIELD_DTSTART :
+ return value ? FALSE : TRUE;
+ case E_CAL_MODEL_FIELD_HAS_ALARMS :
+ case E_CAL_MODEL_FIELD_ICON :
+ case E_CAL_MODEL_FIELD_COLOR :
+ case E_CAL_MODEL_FIELD_COMPONENT :
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+static char *
+ecm_value_to_string (ETableModel *etm, int col, const void *value)
+{
+ g_return_val_if_fail (col >= 0 && col < E_CAL_MODEL_FIELD_LAST, NULL);
+
+ switch (col) {
+ case E_CAL_MODEL_FIELD_CATEGORIES :
+ case E_CAL_MODEL_FIELD_CLASSIFICATION :
+ case E_CAL_MODEL_FIELD_DESCRIPTION :
+ case E_CAL_MODEL_FIELD_SUMMARY :
+ return g_strdup (value);
+ case E_CAL_MODEL_FIELD_DTSTART :
+ return e_cal_model_date_value_to_string (E_CAL_MODEL (etm), value);
+ case E_CAL_MODEL_FIELD_ICON :
+ if (GPOINTER_TO_INT (value) == 0)
+ return _("Normal");
+ else if (GPOINTER_TO_INT (value) == 1)
+ return _("Recurring");
+ else
+ return _("Assigned");
+ case E_CAL_MODEL_FIELD_HAS_ALARMS :
+ return value ? _("Yes") : _("No");
+ case E_CAL_MODEL_FIELD_COLOR :
+ case E_CAL_MODEL_FIELD_COMPONENT :
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/* ECalModel class methods */
+
+static const char *
+ecm_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data)
+{
+ ECalModelPrivate *priv;
+ gint i, pos;
+ GList *l;
+ gchar *colors[] = { "gray", "green", "darkblue" };
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
+ g_return_val_if_fail (comp_data != NULL, NULL);
+
+ priv = model->priv;
+
+ for (l = priv->clients, i = 0; l != NULL; l = l->next, i++) {
+ ECalModelClient *client_data = (ECalModelClient *) l->data;
+
+ if (client_data->client == comp_data->client) {
+ pos = i % G_N_ELEMENTS (colors);
+ return colors[pos];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * e_cal_model_get_component_kind
+ */
+icalcomponent_kind
+e_cal_model_get_component_kind (ECalModel *model)
+{
+ ECalModelPrivate *priv;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), ICAL_NO_COMPONENT);
+
+ priv = model->priv;
+ return priv->kind;
+}
+
+/**
+ * e_cal_model_set_component_kind
+ */
+void
+e_cal_model_set_component_kind (ECalModel *model, icalcomponent_kind kind)
+{
+ ECalModelPrivate *priv;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ priv = model->priv;
+ priv->kind = kind;
+}
+
+/**
+ * e_cal_model_get_timezone
+ */
+icaltimezone *
+e_cal_model_get_timezone (ECalModel *model)
+{
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
+ return model->priv->zone;
+}
+
+/**
+ * e_cal_model_set_timezone
+ */
+void
+e_cal_model_set_timezone (ECalModel *model, icaltimezone *zone)
+{
+ ECalModelPrivate *priv;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ priv = model->priv;
+ if (priv->zone != zone) {
+ e_table_model_pre_change (E_TABLE_MODEL (model));
+ priv->zone = zone;
+
+ /* the timezone affects the times shown for date fields,
+ so we need to redisplay everything */
+ e_table_model_changed (E_TABLE_MODEL (model));
+ }
+}
+
+static ECalModelComponent *
+search_by_uid_and_client (ECalModelPrivate *priv, CalClient *client, const char *uid)
+{
+ gint i;
+
+ for (i = 0; i < priv->objects->len; i++) {
+ ECalModelComponent *comp_data = g_ptr_array_index (priv->objects, i);
+
+ if (comp_data) {
+ const char *tmp_uid;
+
+ tmp_uid = icalcomponent_get_uid (comp_data->icalcomp);
+ if (tmp_uid && *tmp_uid) {
+ if (comp_data->client == client && !strcmp (uid, tmp_uid))
+ return comp_data;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static gint
+get_position_in_array (GPtrArray *objects, gpointer item)
+{
+ gint i;
+
+ for (i = 0; i < objects->len; i++) {
+ if (g_ptr_array_index (objects, i) == item)
+ return i;
+ }
+
+ return -1;
+}
+
+static void
+query_obj_updated_cb (CalQuery *query, const char *uid,
+ gboolean query_in_progress,
+ int n_scanned, int total,
+ gpointer user_data)
+{
+ ECalModelPrivate *priv;
+ icalcomponent *new_icalcomp;
+ CalClientGetStatus status;
+ ECalModelComponent *comp_data;
+ gint pos;
+ ECalModel *model = (ECalModel *) user_data;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ priv = model->priv;
+
+ e_table_model_pre_change (E_TABLE_MODEL (model));
+
+ comp_data = search_by_uid_and_client (priv, cal_query_get_client (query), uid);
+ status = cal_client_get_object (cal_query_get_client (query), uid, &new_icalcomp);
+ switch (status) {
+ case CAL_CLIENT_GET_SUCCESS :
+ if (comp_data) {
+ if (comp_data->icalcomp)
+ icalcomponent_free (comp_data->icalcomp);
+ comp_data->icalcomp = new_icalcomp;
+
+ e_table_model_row_changed (E_TABLE_MODEL (model), get_position_in_array (priv->objects, comp_data));
+ } else {
+ comp_data = g_new0 (ECalModelComponent, 1);
+ comp_data->client = cal_query_get_client (query);
+ comp_data->icalcomp = new_icalcomp;
+
+ g_ptr_array_add (priv->objects, comp_data);
+ e_table_model_row_inserted (E_TABLE_MODEL (model), priv->objects->len - 1);
+ }
+ break;
+ case CAL_CLIENT_GET_NOT_FOUND :
+ case CAL_CLIENT_GET_SYNTAX_ERROR :
+ if (comp_data) {
+ /* Nothing; the object may have been removed from the server. We just
+ notify that the old object was deleted.
+ */
+ pos = get_position_in_array (priv->objects, comp_data);
+
+ g_ptr_array_remove (priv->objects, comp_data);
+ free_comp_data (comp_data);
+
+ e_table_model_row_deleted (E_TABLE_MODEL (model), pos);
+ } else
+ e_table_model_no_change (E_TABLE_MODEL (model));
+ break;
+ default :
+ g_assert_not_reached ();
+ }
+}
+
+static void
+query_obj_removed_cb (CalQuery *query, const char *uid, gpointer user_data)
+{
+ ECalModelComponent *comp_data;
+ ECalModelPrivate *priv;
+ ECalModel *model = (ECalModel *) user_data;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ priv = model->priv;
+
+ e_table_model_pre_change (E_TABLE_MODEL (model));
+
+ comp_data = search_by_uid_and_client (priv, cal_query_get_client (query), uid);
+ if (comp_data) {
+ gint pos = get_position_in_array (priv->objects, comp_data);
+
+ g_ptr_array_remove (priv->objects, comp_data);
+ free_comp_data (comp_data);
+
+ e_table_model_row_deleted (E_TABLE_MODEL (model), pos);
+ } else
+ e_table_model_no_change (E_TABLE_MODEL (model));
+}
+
+static void
+query_done_cb (CalQuery *query, CalQueryDoneStatus status, const char *error_str, gpointer user_data)
+{
+ ECalModel *model = (ECalModel *) user_data;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ if (status != CAL_QUERY_DONE_SUCCESS)
+ g_warning ("query done: %s\n", error_str);
+}
+
+static void
+query_eval_error_cb (CalQuery *query, const char *error_str, gpointer user_data)
+{
+ ECalModel *model = (ECalModel *) user_data;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ g_warning ("eval error: %s\n", error_str);
+}
+
+/* Builds a complete query sexp for the calendar model by adding the predicates
+ * to filter only for the type of objects that the model supports, and
+ * whether we want completed tasks.
+ */
+static char *
+adjust_query_sexp (ECalModel *model, const char *sexp)
+{
+ ECalModelPrivate *priv;
+ char *type_sexp, *new_sexp;
+
+ priv = model->priv;
+
+ if (priv->kind == ICAL_NO_COMPONENT)
+ type_sexp = g_strdup ("#t");
+ else {
+ if (priv->kind == ICAL_VEVENT_COMPONENT)
+ type_sexp = g_strdup ("(or (= (get-vtype) \"VEVENT\"))");
+ else if (priv->kind == ICAL_VTODO_COMPONENT)
+ type_sexp = g_strdup ("(or (= (get-vtype) \"VTODO\"))");
+ else if (priv->kind == ICAL_VJOURNAL_COMPONENT)
+ type_sexp = g_strdup ("(or (= (get-vtype) \"VJOURNAL\"))");
+ else
+ type_sexp = g_strdup ("#t");
+ }
+
+ new_sexp = g_strdup_printf ("(and %s %s)", type_sexp, sexp);
+ g_free (type_sexp);
+
+ return new_sexp;
+}
+
+static void
+update_query_for_client (ECalModel *model, ECalModelClient *client_data)
+{
+ ECalModelPrivate *priv;
+ gchar *real_sexp;
+
+ priv = model->priv;
+
+ /* free the previous query, if any */
+ if (client_data->query) {
+ g_signal_handlers_disconnect_matched (client_data->query, G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL, model);
+ g_object_unref (client_data->query);
+ }
+
+ /* prepare the query */
+ g_assert (priv->sexp != NULL);
+ real_sexp = adjust_query_sexp (model, priv->sexp);
+
+ client_data->query = cal_client_get_query (client_data->client, real_sexp);
+ g_free (real_sexp);
+
+ if (!client_data->query) {
+ g_message ("update_query_for_client(): Could not create the query");
+ return;
+ }
+
+ g_signal_connect (client_data->query, "obj_updated", G_CALLBACK (query_obj_updated_cb), model);
+ g_signal_connect (client_data->query, "obj_removed", G_CALLBACK (query_obj_removed_cb), model);
+ g_signal_connect (client_data->query, "query_done", G_CALLBACK (query_done_cb), model);
+ g_signal_connect (client_data->query, "eval_error", G_CALLBACK (query_eval_error_cb), model);
+}
+
+static void
+add_new_client (ECalModel *model, CalClient *client)
+{
+ ECalModelPrivate *priv;
+ ECalModelClient *client_data;
+
+ priv = model->priv;
+
+ client_data = g_new0 (ECalModelClient, 1);
+ client_data->client = client;
+ client_data->query = NULL;
+ g_object_ref (client_data->client);
+
+ priv->clients = g_list_append (priv->clients, client_data);
+
+ update_query_for_client (model, client_data);
+}
+
+static void
+cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer user_data)
+{
+ ECalModel *model = (ECalModel *) user_data;
+
+ if (status != CAL_CLIENT_OPEN_SUCCESS) {
+ e_cal_model_remove_client (model, client);
+ return;
+ }
+
+ add_new_client (model, client);
+}
+
+/**
+ * e_cal_model_add_client
+ */
+void
+e_cal_model_add_client (ECalModel *model, CalClient *client)
+{
+ ECalModelPrivate *priv;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+ g_return_if_fail (IS_CAL_CLIENT (client));
+
+ priv = model->priv;
+
+ if (cal_client_get_load_state (client) == CAL_CLIENT_LOAD_LOADED)
+ add_new_client (model, client);
+ else
+ g_signal_connect (client, "cal_opened", G_CALLBACK (cal_opened_cb), model);
+}
+
+static void
+remove_client (ECalModel *model, ECalModelClient *client_data)
+{
+ gint i;
+
+ g_signal_handlers_disconnect_matched (client_data->client, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model);
+ g_signal_handlers_disconnect_matched (client_data->query, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, model);
+
+ model->priv->clients = g_list_remove (model->priv->clients, client_data);
+
+ /* remove all objects belonging to this client */
+ e_table_model_pre_change (E_TABLE_MODEL (model));
+ for (i = 0; i < model->priv->objects->len; i++) {
+ ECalModelComponent *comp_data = (ECalModelComponent *) g_ptr_array_index (model->priv->objects, i);
+
+ g_assert (comp_data != NULL);
+
+ if (comp_data->client == client_data->client) {
+ g_ptr_array_remove (model->priv->objects, comp_data);
+ free_comp_data (comp_data);
+ }
+ }
+ e_table_model_changed (E_TABLE_MODEL (model));
+
+ /* free all remaining memory */
+ g_object_unref (client_data->client);
+ g_object_unref (client_data->query);
+ g_free (client_data);
+
+}
+
+/**
+ * e_cal_model_remove_client
+ */
+void
+e_cal_model_remove_client (ECalModel *model, CalClient *client)
+{
+ GList *l;
+ ECalModelPrivate *priv;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+ g_return_if_fail (IS_CAL_CLIENT (client));
+
+ priv = model->priv;
+ for (l = priv->clients; l != NULL; l = l->next) {
+ ECalModelClient *client_data = (ECalModelClient *) l->data;
+
+ if (client_data->client == client) {
+ remove_client (model, client_data);
+ break;
+ }
+ }
+}
+
+/**
+ * e_cal_model_remove_all_clients
+ */
+void
+e_cal_model_remove_all_clients (ECalModel *model)
+{
+ ECalModelPrivate *priv;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+
+ priv = model->priv;
+ while (priv->clients != NULL) {
+ ECalModelClient *client_data = (ECalModelClient *) priv->clients->data;
+ remove_client (model, client_data);
+ }
+}
+
+/**
+ * e_cal_model_set_query
+ */
+void
+e_cal_model_set_query (ECalModel *model, const char *sexp)
+{
+ ECalModelPrivate *priv;
+ GList *l;
+
+ g_return_if_fail (E_IS_CAL_MODEL (model));
+ g_return_if_fail (sexp != NULL);
+
+ priv = model->priv;
+
+ if (priv->sexp)
+ g_free (priv->sexp);
+
+ priv->sexp = g_strdup (sexp);
+
+ /* clean up the current contents */
+ e_table_model_pre_change (E_TABLE_MODEL (model));
+ clear_objects_array (priv);
+ e_table_model_changed (E_TABLE_MODEL (model));
+
+ /* update the query for all clients */
+ for (l = priv->clients; l != NULL; l = l->next) {
+ ECalModelClient *client_data;
+
+ client_data = (ECalModelClient *) l->data;
+ update_query_for_client (model, client_data);
+ }
+}
+
+/**
+ * e_cal_model_create_component_with_defaults
+ */
+icalcomponent *
+e_cal_model_create_component_with_defaults (ECalModel *model)
+{
+ ECalModelPrivate *priv;
+ CalComponent *comp;
+ icalcomponent *icalcomp;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
+
+ priv = model->priv;
+
+ g_return_val_if_fail (priv->clients != NULL, NULL);
+
+ switch (priv->kind) {
+ case ICAL_VEVENT_COMPONENT :
+ comp = cal_comp_event_new_with_defaults ((CalClient *) priv->clients->data);
+ break;
+ case ICAL_VTODO_COMPONENT :
+ comp = cal_comp_task_new_with_defaults ((CalClient *) priv->clients->data);
+ break;
+ default:
+ return NULL;
+ }
+
+ icalcomp = icalcomponent_new_clone (cal_component_get_icalcomponent (comp));
+ g_object_unref (comp);
+
+ return icalcomp;
+}
+
+/**
+ * e_cal_model_get_color_for_component
+ */
+const gchar *
+e_cal_model_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data)
+{
+ ECalModelClass *model_class;
+ const gchar *color = NULL;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
+ g_return_val_if_fail (comp_data != NULL, NULL);
+
+ model_class = (ECalModelClass *) G_OBJECT_GET_CLASS (model);
+ if (model_class->get_color_for_component != NULL)
+ color = model_class->get_color_for_component (model, comp_data);
+
+ if (!color)
+ color = ecm_get_color_for_component (model, comp_data);
+
+ return color;
+}
+
+/**
+ * e_cal_model_get_component_at
+ */
+ECalModelComponent *
+e_cal_model_get_component_at (ECalModel *model, gint row)
+{
+ ECalModelPrivate *priv;
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
+
+ priv = model->priv;
+
+ g_return_val_if_fail (row >= 0 && row < priv->objects->len, NULL);
+
+ return g_ptr_array_index (priv->objects, row);
+}
+
+/**
+ * e_cal_model_date_value_to_string
+ */
+gchar*
+e_cal_model_date_value_to_string (ECalModel *model, const void *value)
+{
+ ECalModelPrivate *priv;
+ ECellDateEditValue *dv = (ECellDateEditValue *) value;
+ struct icaltimetype tt;
+ struct tm tmp_tm;
+ char buffer[64];
+
+ g_return_val_if_fail (E_IS_CAL_MODEL (model), NULL);
+
+ priv = model->priv;
+
+ if (!dv)
+ return g_strdup ("");
+
+ /* We currently convert all the dates to the current timezone. */
+ tt = dv->tt;
+ icaltimezone_convert_time (&tt, dv->zone, priv->zone);
+
+ tmp_tm.tm_year = tt.year - 1900;
+ tmp_tm.tm_mon = tt.month - 1;
+ tmp_tm.tm_mday = tt.day;
+ tmp_tm.tm_hour = tt.hour;
+ tmp_tm.tm_min = tt.minute;
+ tmp_tm.tm_sec = tt.second;
+ tmp_tm.tm_isdst = -1;
+
+ tmp_tm.tm_wday = time_day_of_week (tt.day, tt.month - 1, tt.year);
+
+ e_time_format_date_and_time (&tmp_tm, calendar_config_get_24_hour_format (),
+ TRUE, FALSE,
+ buffer, sizeof (buffer));
+ return g_strdup (buffer);
+}
diff --git a/calendar/gui/e-cal-model.h b/calendar/gui/e-cal-model.h
new file mode 100644
index 0000000000..69d9e785ba
--- /dev/null
+++ b/calendar/gui/e-cal-model.h
@@ -0,0 +1,95 @@
+/* Evolution calendar - Data model for ETable
+ *
+ * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000 Ximian, Inc.
+ *
+ * Authors: Rodrigo Moya <rodrigo@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef E_CAL_MODEL_H
+#define E_CAL_MODEL_H
+
+#include <gal/e-table/e-table-model.h>
+#include <cal-client/cal-client.h>
+#include "e-cell-date-edit-text.h"
+
+G_BEGIN_DECLS
+
+#define E_TYPE_CAL_MODEL (e_cal_model_get_type ())
+#define E_CAL_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CAL_MODEL, ECalModel))
+#define E_CAL_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CAL_MODEL, ECalModelClass))
+#define E_IS_CAL_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CAL_MODEL))
+#define E_IS_CAL_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CAL_MODEL))
+
+typedef struct _ECalModelPrivate ECalModelPrivate;
+
+typedef enum {
+ E_CAL_MODEL_FIELD_CATEGORIES,
+ E_CAL_MODEL_FIELD_CLASSIFICATION,
+ E_CAL_MODEL_FIELD_COLOR, /* not a real field */
+ E_CAL_MODEL_FIELD_COMPONENT, /* not a real field */
+ E_CAL_MODEL_FIELD_DESCRIPTION,
+ E_CAL_MODEL_FIELD_DTSTART,
+ E_CAL_MODEL_FIELD_HAS_ALARMS, /* not a real field */
+ E_CAL_MODEL_FIELD_ICON, /* not a real field */
+ E_CAL_MODEL_FIELD_SUMMARY,
+ E_CAL_MODEL_FIELD_UID,
+ E_CAL_MODEL_FIELD_LAST
+} ECalModelField;
+
+typedef struct {
+ CalClient *client;
+ icalcomponent *icalcomp;
+
+ /* private data */
+ ECellDateEditValue *dtstart;
+ ECellDateEditValue *dtend;
+} ECalModelComponent;
+
+typedef struct {
+ ETableModel model;
+ ECalModelPrivate *priv;
+} ECalModel;
+
+typedef struct {
+ ETableModelClass parent_class;
+
+ /* virtual methods */
+ const gchar * (* get_color_for_component) (ECalModel *model, ECalModelComponent *comp_data);
+} ECalModelClass;
+
+GType e_cal_model_get_type (void);
+
+icalcomponent_kind e_cal_model_get_component_kind (ECalModel *model);
+void e_cal_model_set_component_kind (ECalModel *model, icalcomponent_kind kind);
+icaltimezone *e_cal_model_get_timezone (ECalModel *model);
+void e_cal_model_set_timezone (ECalModel *model, icaltimezone *zone);
+
+void e_cal_model_add_client (ECalModel *model, CalClient *client);
+void e_cal_model_remove_client (ECalModel *model, CalClient *client);
+void e_cal_model_remove_all_clients (ECalModel *model);
+
+void e_cal_model_set_query (ECalModel *model, const gchar *sexp);
+
+icalcomponent *e_cal_model_create_component_with_defaults (ECalModel *model);
+const gchar *e_cal_model_get_color_for_component (ECalModel *model, ECalModelComponent *comp_data);
+ECalModelComponent *e_cal_model_get_component_at (ECalModel *model, gint row);
+
+gchar *e_cal_model_date_value_to_string (ECalModel *model, const void *value);
+
+G_END_DECLS
+
+#endif
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index 5acd71965b..1ef6f9c07b 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -5,7 +5,7 @@
* Damon Chaplin <damon@ximian.com>
* Rodrigo Moya <rodrigo@ximian.com>
*
- * Copyright 1999, Ximian, Inc.
+ * Copyright 1999-2003, Ximian, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -1434,6 +1434,7 @@ query_obj_updated_cb (CalQuery *query, const char *uid,
EDayView *day_view;
EDayViewEvent *event;
CalComponent *comp;
+ icalcomponent *icalcomp;
CalClientGetStatus status;
gint day, event_num;
@@ -1444,11 +1445,18 @@ query_obj_updated_cb (CalQuery *query, const char *uid,
return;
/* Get the event from the server. */
- status = cal_client_get_object (e_cal_view_get_cal_client (E_CAL_VIEW (day_view)), uid, &comp);
+ status = cal_client_get_object (e_cal_view_get_cal_client (E_CAL_VIEW (day_view)), uid, &icalcomp);
switch (status) {
case CAL_CLIENT_GET_SUCCESS:
- /* Everything is fine */
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+
+ g_message ("query_obj_updated_cb(): Invalid object %s", uid);
+ return;
+ }
break;
case CAL_CLIENT_GET_SYNTAX_ERROR:
diff --git a/calendar/gui/e-itip-control.c b/calendar/gui/e-itip-control.c
index 2e1ff4cb67..91a355f269 100644
--- a/calendar/gui/e-itip-control.c
+++ b/calendar/gui/e-itip-control.c
@@ -304,13 +304,13 @@ find_server (GPtrArray *servers, CalComponent *comp)
cal_component_get_uid (comp, &uid);
for (i = 0; i < servers->len; i++) {
CalClient *client;
- CalComponent *found_comp;
+ icalcomponent *icalcomp;
CalClientGetStatus status;
client = g_ptr_array_index (servers, i);
- status = cal_client_get_object (client, uid, &found_comp);
+ status = cal_client_get_object (client, uid, &icalcomp);
if (status == CAL_CLIENT_GET_SUCCESS) {
- g_object_unref (found_comp);
+ icalcomponent_free (icalcomp);
g_object_ref (client);
return client;
@@ -1248,6 +1248,7 @@ get_real_item (EItipControl *itip)
{
EItipControlPrivate *priv;
CalComponent *comp;
+ icalcomponent *icalcomp;
CalComponentVType type;
CalClientGetStatus status = CAL_CLIENT_GET_NOT_FOUND;
const char *uid;
@@ -1260,11 +1261,11 @@ get_real_item (EItipControl *itip)
switch (type) {
case CAL_COMPONENT_EVENT:
if (priv->event_client != NULL)
- status = cal_client_get_object (priv->event_client, uid, &comp);
+ status = cal_client_get_object (priv->event_client, uid, &icalcomp);
break;
case CAL_COMPONENT_TODO:
if (priv->task_client != NULL)
- status = cal_client_get_object (priv->task_client, uid, &comp);
+ status = cal_client_get_object (priv->task_client, uid, &icalcomp);
break;
default:
status = CAL_CLIENT_GET_NOT_FOUND;
@@ -1273,6 +1274,13 @@ get_real_item (EItipControl *itip)
if (status != CAL_CLIENT_GET_SUCCESS)
return NULL;
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ return NULL;
+ }
+
return comp;
}
@@ -1936,6 +1944,7 @@ update_attendee_status (EItipControl *itip)
CalClient *client;
CalClientGetStatus status;
CalComponent *comp = NULL;
+ icalcomponent *icalcomp = NULL;
CalComponentVType type;
const char *uid;
GtkWidget *dialog;
@@ -1957,41 +1966,47 @@ update_attendee_status (EItipControl *itip)
/* Obtain our version */
cal_component_get_uid (priv->comp, &uid);
- status = cal_client_get_object (client, uid, &comp);
+ status = cal_client_get_object (client, uid, &icalcomp);
if (status == CAL_CLIENT_GET_SUCCESS) {
GSList *attendees;
- cal_component_get_attendee_list (priv->comp, &attendees);
- if (attendees != NULL) {
- CalComponentAttendee *a = attendees->data;
- icalproperty *prop;
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ icalcomponent_free (icalcomp);
- prop = find_attendee (cal_component_get_icalcomponent (comp),
- itip_strip_mailto (a->value));
-
- if (prop == NULL) {
- dialog = gnome_question_dialog_modal (_("This response is not from a current "
- "attendee. Add as an attendee?"),
- NULL, NULL);
- if (gnome_dialog_run_and_close (GNOME_DIALOG (dialog)) == GNOME_YES) {
- change_status (cal_component_get_icalcomponent (comp),
+ dialog = gnome_warning_dialog (_("Object is invalid and cannot be updated\n"));
+ } else {
+ cal_component_get_attendee_list (priv->comp, &attendees);
+ if (attendees != NULL) {
+ CalComponentAttendee *a = attendees->data;
+ icalproperty *prop;
+
+ prop = find_attendee (icalcomp, itip_strip_mailto (a->value));
+
+ if (prop == NULL) {
+ dialog = gnome_question_dialog_modal (_("This response is not from a current "
+ "attendee. Add as an attendee?"),
+ NULL, NULL);
+ if (gnome_dialog_run_and_close (GNOME_DIALOG (dialog)) == GNOME_YES) {
+ change_status (icalcomp,
+ itip_strip_mailto (a->value),
+ a->status);
+ cal_component_rescan (comp);
+ } else {
+ goto cleanup;
+ }
+ } else if (a->status == ICAL_PARTSTAT_NONE || a->status == ICAL_PARTSTAT_X) {
+ dialog = gnome_warning_dialog (_("Attendee status could "
+ "not be updated because "
+ "of an invalid status!\n"));
+ goto cleanup;
+ } else {
+ change_status (icalcomp,
itip_strip_mailto (a->value),
a->status);
- cal_component_rescan (comp);
- } else {
- goto cleanup;
+ cal_component_rescan (comp);
}
- } else if (a->status == ICAL_PARTSTAT_NONE || a->status == ICAL_PARTSTAT_X) {
- dialog = gnome_warning_dialog (_("Attendee status could "
- "not be updated because "
- "of an invalid status!\n"));
- goto cleanup;
- } else {
- change_status (cal_component_get_icalcomponent (comp),
- itip_strip_mailto (a->value),
- a->status);
- cal_component_rescan (comp);
}
}
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index 9beb123b95..19ef3147e4 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -1065,7 +1065,8 @@ query_obj_updated_cb (CalQuery *query, const char *uid,
EWeekView *week_view;
EWeekViewEvent *event;
gint event_num, num_days;
- CalComponent *comp;
+ CalComponent *comp = NULL;
+ icalcomponent *icalcomp;
CalClientGetStatus status;
week_view = E_WEEK_VIEW (data);
@@ -1075,11 +1076,18 @@ query_obj_updated_cb (CalQuery *query, const char *uid,
return;
/* Get the event from the server. */
- status = cal_client_get_object (e_cal_view_get_cal_client (E_CAL_VIEW (week_view)), uid, &comp);
+ status = cal_client_get_object (e_cal_view_get_cal_client (E_CAL_VIEW (week_view)), uid, &icalcomp);
switch (status) {
case CAL_CLIENT_GET_SUCCESS:
- /* Everything is fine */
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+
+ g_message ("query_obj_updated_cb(): Could not set icalcomponent on CalComponent");
+ return;
+ }
break;
case CAL_CLIENT_GET_SYNTAX_ERROR:
diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c
index 7598aecd8d..4dab508ffc 100644
--- a/calendar/gui/gnome-cal.c
+++ b/calendar/gui/gnome-cal.c
@@ -363,7 +363,8 @@ dn_query_obj_updated_cb (CalQuery *query, const char *uid,
{
GnomeCalendar *gcal;
GnomeCalendarPrivate *priv;
- CalComponent *comp;
+ CalComponent *comp = NULL;
+ icalcomponent *icalcomp;
CalClientGetStatus status;
gcal = GNOME_CALENDAR (data);
@@ -379,20 +380,25 @@ dn_query_obj_updated_cb (CalQuery *query, const char *uid,
return;
}
- status = cal_client_get_object (priv->client, uid, &comp);
+ status = cal_client_get_object (priv->client, uid, &icalcomp);
switch (status) {
case CAL_CLIENT_GET_SUCCESS:
- /* Everything is fine */
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ return;
+ }
break;
case CAL_CLIENT_GET_SYNTAX_ERROR:
g_message ("dn_query_obj_updated_cb(): Syntax error while getting object `%s'", uid);
- break;
+ return;
case CAL_CLIENT_GET_NOT_FOUND:
/* The object is no longer in the server, so do nothing */
- break;
+ return;
default:
g_assert_not_reached ();
@@ -3001,14 +3007,22 @@ purging_obj_updated_cb (CalQuery *query, const char *uid,
GnomeCalendarPrivate *priv;
GnomeCalendar *gcal = data;
CalComponent *comp;
+ icalcomponent *icalcomp;
obj_updated_closure closure;
gchar *msg;
priv = gcal->priv;
- if (cal_client_get_object (priv->client, uid, &comp) != CAL_CLIENT_GET_SUCCESS)
+ if (cal_client_get_object (priv->client, uid, &icalcomp) != CAL_CLIENT_GET_SUCCESS)
return;
+ comp = cal_component_new ();
+ if (!cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ return;
+ }
+
msg = g_strdup_printf (_("Purging event %s"), uid);
/* further filter the event, to check the last recurrence end date */