[evolution-patches] merging new-calendar-branch into HEAD



Hi

The attached patch merges the stuff in the new-calendar-branch into
HEAD. The work in that branch is not finished yet, but since I am
starting the changes in the views, which will mean the branch will be a
bit unstable for a while.

So, I think it is a good time to merge what there is in the branch
before breaking it. It works for me, so, is it ok to merge now?

cheers
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/calendar/ChangeLog,v
retrieving revision 1.1844
diff -u -p -r1.1844 ChangeLog
--- ChangeLog	6 Aug 2003 02:34:03 -0000	1.1844
+++ ChangeLog	7 Aug 2003 10:34:38 -0000
@@ -1,12 +1,119 @@
+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>
 
Index: cal-client/cal-client.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/cal-client/cal-client.c,v
retrieving revision 1.122
diff -u -p -r1.122 cal-client.c
--- cal-client/cal-client.c	7 Jul 2003 09:51:34 -0000	1.122
+++ cal-client/cal-client.c	7 Aug 2003 10:34:40 -0000
@@ -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
 	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
 	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
 	   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
  * 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
  * 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
 	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
 		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
 	   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 (CalCl
 {
 	GHashTable *uid_comp_hash;
 	CalComponent *comp;
+	icalcomponent *icalcomp;
 	CalClientGetStatus status;
 	const char *comp_uid;
 
@@ -1953,13 +1932,19 @@ generate_instances_obj_updated_cb (CalCl
 	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 *clien
 
 	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,
 
 	g_return_val_if_fail (sexp != NULL, NULL);
 
-	return cal_query_new (priv->cal, sexp);
+	return cal_query_new (client, priv->cal, sexp);
 }
 
 
Index: cal-client/cal-client.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/cal-client/cal-client.h,v
retrieving revision 1.63
diff -u -p -r1.63 cal-client.h
--- cal-client/cal-client.h	26 Apr 2003 16:39:53 -0000	1.63
+++ cal-client/cal-client.h	7 Aug 2003 10:34:40 -0000
@@ -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 
 
 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,
Index: cal-client/cal-query.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/cal-client/cal-query.c,v
retrieving revision 1.12
diff -u -p -r1.12 cal-query.c
--- cal-client/cal-query.c	7 Dec 2002 02:56:56 -0000	1.12
+++ cal-client/cal-query.c	7 Aug 2003 10:34:40 -0000
@@ -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_
 		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;
 }
Index: cal-client/cal-query.h
===================================================================
RCS file: /cvs/gnome/evolution/calendar/cal-client/cal-query.h,v
retrieving revision 1.6
diff -u -p -r1.6 cal-query.h
--- cal-client/cal-query.h	7 Dec 2002 02:56:56 -0000	1.6
+++ cal-client/cal-query.h	7 Aug 2003 10:34:40 -0000
@@ -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_done_status_enum_get_type (void);
+GType      cal_query_get_type (void);
 
-CalQuery *cal_query_construct (CalQuery *query,
-			       GNOME_Evolution_Calendar_Cal cal,
-			       const char *sexp);
+GType      cal_query_done_status_enum_get_type (void);
 
-CalQuery *cal_query_new (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 (CalClient *client,
+			  GNOME_Evolution_Calendar_Cal cal,
+			  const char *sexp);
+CalClient *cal_query_get_client (CalQuery *query);
 
 
 
Index: conduits/calendar/calendar-conduit.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/conduits/calendar/calendar-conduit.c,v
retrieving revision 1.112
diff -u -p -r1.112 calendar-conduit.c
--- conduits/calendar/calendar-conduit.c	7 Apr 2003 17:06:37 -0000	1.112
+++ conduits/calendar/calendar-conduit.c	7 Aug 2003 10:34:41 -0000
@@ -1006,13 +1006,21 @@ local_record_from_uid (ECalLocalRecord *
 		       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,8 +1364,15 @@ 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);
Index: conduits/todo/todo-conduit.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/conduits/todo/todo-conduit.c,v
retrieving revision 1.82
diff -u -p -r1.82 todo-conduit.c
--- conduits/todo/todo-conduit.c	7 Apr 2003 17:06:37 -0000	1.82
+++ conduits/todo/todo-conduit.c	7 Aug 2003 10:34:42 -0000
@@ -675,13 +675,21 @@ local_record_from_uid (EToDoLocalRecord 
 		       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,8 +906,15 @@ 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);
Index: gui/Makefile.am
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/Makefile.am,v
retrieving revision 1.269
diff -u -p -r1.269 Makefile.am
--- gui/Makefile.am	18 Jul 2003 10:37:44 -0000	1.269
+++ gui/Makefile.am	7 Aug 2003 10:34:42 -0000
@@ -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			\
Index: gui/calendar-model.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/calendar-model.c,v
retrieving revision 1.109
diff -u -p -r1.109 calendar-model.c
--- gui/calendar-model.c	30 May 2003 17:35:09 -0000	1.109
+++ gui/calendar-model.c	7 Aug 2003 10:34:43 -0000
@@ -1763,6 +1763,7 @@ query_obj_updated_cb (CalQuery *query, c
 	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, c
 
 	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);
Index: gui/comp-editor-factory.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/comp-editor-factory.c,v
retrieving revision 1.23
diff -u -p -r1.23 comp-editor-factory.c
--- gui/comp-editor-factory.c	25 Mar 2003 13:57:25 -0000	1.23
+++ gui/comp-editor-factory.c	7 Aug 2003 10:34:44 -0000
@@ -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 cha
 
 	/* 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:
Index: gui/comp-util.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/comp-util.c,v
retrieving revision 1.18
diff -u -p -r1.18 comp-util.c
--- gui/comp-util.c	4 Mar 2003 19:52:30 -0000	1.18
+++ gui/comp-util.c	7 Aug 2003 10:34:44 -0000
@@ -211,7 +211,7 @@ cal_comp_is_on_server (CalComponent *com
 {
 	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 *com
 	 */
 	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 *com
 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;
 }
Index: gui/e-cal-model-calendar.c
===================================================================
RCS file: gui/e-cal-model-calendar.c
diff -N gui/e-cal-model-calendar.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gui/e-cal-model-calendar.c	7 Aug 2003 10:34:44 -0000
@@ -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);
+}
Index: gui/e-cal-model-calendar.h
===================================================================
RCS file: gui/e-cal-model-calendar.h
diff -N gui/e-cal-model-calendar.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gui/e-cal-model-calendar.h	7 Aug 2003 10:34:44 -0000
@@ -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
Index: gui/e-cal-model-tasks.c
===================================================================
RCS file: gui/e-cal-model-tasks.c
diff -N gui/e-cal-model-tasks.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gui/e-cal-model-tasks.c	7 Aug 2003 10:34:45 -0000
@@ -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);
+}
Index: gui/e-cal-model-tasks.h
===================================================================
RCS file: gui/e-cal-model-tasks.h
diff -N gui/e-cal-model-tasks.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gui/e-cal-model-tasks.h	7 Aug 2003 10:34:45 -0000
@@ -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
Index: gui/e-cal-model.c
===================================================================
RCS file: gui/e-cal-model.c
diff -N gui/e-cal-model.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gui/e-cal-model.c	7 Aug 2003 10:34:45 -0000
@@ -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);
+}
Index: gui/e-cal-model.h
===================================================================
RCS file: gui/e-cal-model.h
diff -N gui/e-cal-model.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gui/e-cal-model.h	7 Aug 2003 10:34:45 -0000
@@ -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
Index: gui/e-day-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-day-view.c,v
retrieving revision 1.213
diff -u -p -r1.213 e-day-view.c
--- gui/e-day-view.c	29 Jul 2003 05:21:39 -0000	1.213
+++ gui/e-day-view.c	7 Aug 2003 10:34:49 -0000
@@ -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, c
 	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, c
 		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:
Index: gui/e-itip-control.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-itip-control.c,v
retrieving revision 1.123
diff -u -p -r1.123 e-itip-control.c
--- gui/e-itip-control.c	23 Jul 2003 15:05:02 -0000	1.123
+++ gui/e-itip-control.c	7 Aug 2003 10:34:50 -0000
@@ -304,13 +304,13 @@ find_server (GPtrArray *servers, CalComp
 	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 *it
 	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 *it
 	
 	/* 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);				
 			}
 		}
 
Index: gui/e-week-view.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/e-week-view.c,v
retrieving revision 1.179
diff -u -p -r1.179 e-week-view.c
--- gui/e-week-view.c	29 Jul 2003 05:21:39 -0000	1.179
+++ gui/e-week-view.c	7 Aug 2003 10:34:52 -0000
@@ -1065,7 +1065,8 @@ query_obj_updated_cb (CalQuery *query, c
 	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, c
 		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:
Index: gui/gnome-cal.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/gnome-cal.c,v
retrieving revision 1.254
diff -u -p -r1.254 gnome-cal.c
--- gui/gnome-cal.c	24 Jul 2003 16:02:54 -0000	1.254
+++ gui/gnome-cal.c	7 Aug 2003 10:34:53 -0000
@@ -363,7 +363,8 @@ dn_query_obj_updated_cb (CalQuery *query
 {
 	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
 		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,13 +3007,21 @@ purging_obj_updated_cb (CalQuery *query,
 	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);
 
Index: gui/dialogs/comp-editor.c
===================================================================
RCS file: /cvs/gnome/evolution/calendar/gui/dialogs/comp-editor.c,v
retrieving revision 1.80
diff -u -p -r1.80 comp-editor.c
--- gui/dialogs/comp-editor.c	29 Jun 2003 19:29:45 -0000	1.80
+++ gui/dialogs/comp-editor.c	7 Aug 2003 10:34:54 -0000
@@ -1450,9 +1450,21 @@ obj_updated_cb (CalClient *client, const
 
 	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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]