aboutsummaryrefslogtreecommitdiffstats
path: root/calendar
diff options
context:
space:
mode:
Diffstat (limited to 'calendar')
-rw-r--r--calendar/ChangeLog78
-rw-r--r--calendar/cal-client/cal-client.c70
-rw-r--r--calendar/cal-client/cal-client.h1
-rw-r--r--calendar/cal-util/cal-util.c25
-rw-r--r--calendar/cal-util/cal-util.h14
-rw-r--r--calendar/conduits/todo/Makefile.am6
-rw-r--r--calendar/conduits/todo/e-todo.conduit.in4
-rw-r--r--calendar/conduits/todo/todo-conduit-config.h12
-rw-r--r--calendar/conduits/todo/todo-conduit.c964
-rw-r--r--calendar/conduits/todo/todo-conduit.h18
-rw-r--r--calendar/idl/evolution-calendar.idl16
-rw-r--r--calendar/pcs/cal-backend-file.c30
-rw-r--r--calendar/pcs/cal-backend-imc.c1421
-rw-r--r--calendar/pcs/cal-backend-imc.h61
-rw-r--r--calendar/pcs/cal-backend.c380
-rw-r--r--calendar/pcs/cal-backend.h8
-rw-r--r--calendar/pcs/cal.c58
17 files changed, 1170 insertions, 1996 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 3838986f93..5dd236f207 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,81 @@
+2000-09-19 JP Rosevear <jpr@helixcode.com>
+
+ * conduits/todo/todo-conduit.c (check_for_slow_setting): Add some
+ other cases where a slow sync is in order
+ (pre_sync): Pre load the uids, the map and the add/mod/del lists
+ (match_record): Use the map hash to match records
+ (iterate): Iterate using the pre-loaded uid list
+ (iterate_specific): Iterate using the add/mod/del lists
+ (purge): Delete all entries in the del list
+ (set_status): Set status by adding to an appropriate list
+ (set_pilot_id): Set pilot_id by updating map hash
+
+ * conduits/todo/todo-conduit.h: Add lists for added, modified and
+ deleted objects
+
+ * conduits/todo/todo-conduit.c (map_name): Get the pilot_id->uid map
+ file name
+ (map_sax_start_element): SAX handler to extract a pilot_id->uid
+ mapping
+ (map_sax_parse): Parse the given file and build a pilot_id->uid hash
+ (map_write_foreach): Write out individual mapping elements
+ (map_write): Write out the pilot_id->uid mapping
+ (start_calendar_server_cb): Rename from gnome_calendar_load_cb
+
+ * conduits/todo/todo-conduit-config.h: Rename pilotID to pilot_id
+
+ * conduits/todo/e-todo.conduit.in: A little renaming
+
+ * conduits/todo/Makefile.am: Fix build slightly
+
+ * pcs/cal.c (build_change_seq): Build a corba sequence out of a list
+ of CalObjChanges
+ (Cal_get_objects_in_range): Implement new corba function
+
+ * pcs/cal-backend.c (cal_backend_init): Intiliaze to NULL
+ (cal_backend_load): Track the uri so we can write the log file
+ to the same place
+ (cal_backend_log_name): Figure out the log filename/path based on
+ the calendar uri
+ (cal_backend_set_node_timet): Set an xml node property value from
+ a time_t
+ (cal_backend_log_entry): Adds a log entry to list waiting to be written
+ out
+ (cal_backend_log_sync): Syncs the log entries to disk
+ (cal_backend_log_sax_start_element): SAX callback for reading in
+ log entries
+ (cal_backend_log_sax_end_element): ditto
+ (cal_backend_log_sax_parse): Main SAX parser call to parse the log
+ file looking for particular log entries and creating a CalObjChange
+ hash with the last change for each object
+ (cal_backend_get_log_entries): Returns a hash of objects of a given
+ type changed since the given time
+ (cal_backend_update_object): Add appropriate log entries
+ (cal_backend_remove_object): ditto
+ (cal_backend_get_changed_uids): Implement new idl interface call
+ (cal_backend_foreach_changed): Convert CalObjChange hash into a list
+
+ * pcs/cal-backend-imc.[hc]: Remove crufty files
+
+ * pcs/cal-backend-file.c (cal_backend_file_get_type_by_uid): New
+ function that returns the CalObjType for a uid.
+
+ * cal-client/cal-client.h: Update prototypes.
+
+ * cal-client/cal-client.c (build_change_list): Build a list
+ of CalObjChange items from a corba sequence.
+ (cal_client_get_changed_uids): New accessor method for the
+ similarly named addition to the idl file.
+
+ * cal-util/cal-util.h: Update prototypes and add CalObjChangeType
+ enum.
+
+ * cal-util/cal-util.c (cal_obj_change_list_free): New utility
+ method to free a list of CalObjChange objects.
+
+ * idl/evolution-calendar.idl: Add get_changed_uids method
+ and associated types.
+
2000-09-18 Christopher James Lahey <clahey@helixcode.com>
* gui/Makefile.am: Added $(EXTRA_GNOME_CFLAGS) and
diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c
index 65c0c4aea4..7b5f248d85 100644
--- a/calendar/cal-client/cal-client.c
+++ b/calendar/cal-client/cal-client.c
@@ -1,3 +1,4 @@
+
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Evolution calendar client
*
@@ -800,6 +801,75 @@ cal_client_get_uids (CalClient *client, CalObjType type)
return uids;
}
+/* Builds a GList of CalObjChange structures from the CORBA sequence */
+static GList *
+build_change_list (Evolution_Calendar_CalObjChangeSeq *seq)
+{
+ GList *list;
+ int i;
+
+ /* Create the list in reverse order */
+ list = NULL;
+ for (i = 0; i < seq->_length; i++) {
+ Evolution_Calendar_CalObjChange *corba_coc;
+ CalObjChange *coc;
+
+ corba_coc = &seq->_buffer[i];
+ coc = g_new (CalObjChange, 1);
+
+ coc->uid = g_strdup (corba_coc->uid);
+ coc->type = corba_coc->type;
+
+ list = g_list_prepend (list, coc);
+ }
+
+ list = g_list_reverse (list);
+ return list;
+}
+
+/**
+ * cal_client_get_changed_uids:
+ * @client: A calendar client.
+ * @type: Bitmask with types of objects to return.
+ *
+ * Queries a calendar for a list of unique identifiers corresponding to calendar
+ * objects whose type matches one of the types specified in the @type flags.
+ *
+ * Return value: A list of strings that are the sought UIDs.
+ **/
+GList *
+cal_client_get_changed_uids (CalClient *client, CalObjType type, time_t since)
+{
+ CalClientPrivate *priv;
+ CORBA_Environment ev;
+ Evolution_Calendar_CalObjChangeSeq *seq;
+ int t;
+ GList *changes;
+
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (IS_CAL_CLIENT (client), NULL);
+
+ priv = client->priv;
+ g_return_val_if_fail (priv->load_state == LOAD_STATE_LOADED, NULL);
+
+ t = corba_obj_type (type);
+ CORBA_exception_init (&ev);
+
+ seq = Evolution_Calendar_Cal_get_changed_uids (priv->cal, t, since, &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_message ("cal_client_get_changed_uids(): could not get the list of changes");
+ CORBA_exception_free (&ev);
+ return NULL;
+ }
+
+ CORBA_exception_free (&ev);
+
+ changes = build_change_list (seq);
+ CORBA_free (seq);
+
+ return changes;
+}
+
/* FIXME: Not used? */
#if 0
/* Builds a GList of CalObjInstance structures from the CORBA sequence */
diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h
index 6747c7488e..9853c63e2c 100644
--- a/calendar/cal-client/cal-client.h
+++ b/calendar/cal-client/cal-client.h
@@ -101,6 +101,7 @@ void cal_client_update_pilot_id (CalClient *client, char *uid,
unsigned long pilot_status);
GList *cal_client_get_uids (CalClient *client, CalObjType type);
+GList *cal_client_get_changed_uids (CalClient *client, CalObjType type, time_t since);
GList *cal_client_get_objects_in_range (CalClient *client, CalObjType type,
time_t start, time_t end);
diff --git a/calendar/cal-util/cal-util.c b/calendar/cal-util/cal-util.c
index 092fd79889..bfb9c88fff 100644
--- a/calendar/cal-util/cal-util.c
+++ b/calendar/cal-util/cal-util.c
@@ -51,6 +51,31 @@ cal_obj_instance_list_free (GList *list)
}
/**
+ * cal_obj_change_list_free:
+ * @list: List of #CalObjChange structures.
+ *
+ * Frees a list of #CalObjChange structures.
+ **/
+void
+cal_obj_change_list_free (GList *list)
+{
+ CalObjChange *c;
+ GList *l;
+
+ for (l = list; l; l = l->next) {
+ c = l->data;
+
+ g_assert (c != NULL);
+ g_assert (c->uid != NULL);
+
+ g_free (c->uid);
+ g_free (c);
+ }
+
+ g_list_free (list);
+}
+
+/**
* cal_alarm_instance_list_free:
* @list: List of #CalAlarmInstance structures.
*
diff --git a/calendar/cal-util/cal-util.h b/calendar/cal-util/cal-util.h
index 154f4c2ad5..243cc34105 100644
--- a/calendar/cal-util/cal-util.h
+++ b/calendar/cal-util/cal-util.h
@@ -41,6 +41,19 @@ typedef struct {
void cal_obj_instance_list_free (GList *list);
+typedef enum {
+ CALOBJ_UPDATED = 1 << 0,
+ CALOBJ_REMOVED = 1 << 1
+} CalObjChangeType;
+
+typedef struct
+{
+ char *uid;
+ CalObjChangeType type;
+} CalObjChange;
+
+void cal_obj_change_list_free (GList *list);
+
/* Instance of an alarm trigger */
typedef struct {
char *uid; /* UID of object */
@@ -66,3 +79,4 @@ void cal_obj_uid_list_free (GList *list);
END_GNOME_DECLS
#endif
+
diff --git a/calendar/conduits/todo/Makefile.am b/calendar/conduits/todo/Makefile.am
index 3bbfc3f418..94eb5251b5 100644
--- a/calendar/conduits/todo/Makefile.am
+++ b/calendar/conduits/todo/Makefile.am
@@ -3,7 +3,7 @@ INCLUDES = \
-I$(top_srcdir)/calendar \
-I$(top_srcdir)/libical/src/libical \
-I$(top_builddir)/libical/src/libical \
- $(BONOBO_GNOME_CFLAGS) \
+ $(BONOBO_VFS_GNOME_CFLAGS) \
$(GNOME_PILOT_CFLAGS)
# ToDo Capplet
@@ -30,9 +30,6 @@ e_todo_conduits_LTLIBRARIES = libetodo_conduit.la
libetodo_conduit_la_SOURCES = todo-conduit.c
-libetodo_conduit_la_LDFLAGS = \
- -rpath $(libdir)
-
libetodo_conduit_la_LIBADD = \
$(top_builddir)/calendar/cal-client/libcal-client-static.la \
$(top_builddir)/calendar/cal-util/libcal-util-static.la \
@@ -40,6 +37,7 @@ libetodo_conduit_la_LIBADD = \
$(top_builddir)/libical/src/libical/libical-static.la \
$(BONOBO_VFS_GNOME_LIBS) \
$(PISOCK_LIBDIR) $(PISOCK_LIBS) \
+ $(UNICODE_LIBS) \
$(GNOME_LIBDIR) \
$(GNOME_LIBS)
diff --git a/calendar/conduits/todo/e-todo.conduit.in b/calendar/conduits/todo/e-todo.conduit.in
index 42691745a6..40e6fd620c 100644
--- a/calendar/conduits/todo/e-todo.conduit.in
+++ b/calendar/conduits/todo/e-todo.conduit.in
@@ -1,6 +1,6 @@
<gnome-pilot-conduit version="1.0">
-<conduit id="todo_conduit" type="shlib" location="@prefix@/lib/gnome-pilot/conduits/libetodo_conduit.so"/>
-<name value="e-todo"/>
+<conduit id="e_todo_conduit" type="shlib" location="@prefix@/lib/gnome-pilot/conduits/libetodo_conduit.so"/>
+<name value="EToDo"/>
<conduit-attribute name="description" value="Synchronizes ToDo List with Evolution"/>
<conduit-attribute name="default-synctype" value="synchronize"/>
<conduit-attribute name="icon" value="@prefix@/share/pixmaps/gnome-calendar-conduit.png"/>
diff --git a/calendar/conduits/todo/todo-conduit-config.h b/calendar/conduits/todo/todo-conduit-config.h
index 18bb353b08..38f3cf8e39 100644
--- a/calendar/conduits/todo/todo-conduit-config.h
+++ b/calendar/conduits/todo/todo-conduit-config.h
@@ -33,16 +33,16 @@
typedef struct _EToDoConduitCfg EToDoConduitCfg;
struct _EToDoConduitCfg {
gboolean open_secret;
- guint32 pilotId;
+ guint32 pilot_id;
GnomePilotConduitSyncType sync_type; /* only used by capplet */
};
static void
-todoconduit_load_configuration (EToDoConduitCfg **c, guint32 pilotId)
+todoconduit_load_configuration (EToDoConduitCfg **c, guint32 pilot_id)
{
gchar prefix[256];
g_snprintf (prefix, 255, "/gnome-pilot.d/e-todo-conduit/Pilot_%u/",
- pilotId);
+ pilot_id);
*c = g_new0 (EToDoConduitCfg,1);
g_assert (*c != NULL);
@@ -54,7 +54,7 @@ todoconduit_load_configuration (EToDoConduitCfg **c, guint32 pilotId)
(*c)->sync_type = GnomePilotConduitSyncTypeCustom;
gnome_config_pop_prefix ();
- (*c)->pilotId = pilotId;
+ (*c)->pilot_id = pilot_id;
}
/* Saves the configuration data. */
@@ -64,7 +64,7 @@ todoconduit_save_configuration (EToDoConduitCfg *c)
gchar prefix[256];
g_snprintf (prefix, 255, "/gnome-pilot.d/e-todo-conduit/Pilot_%u/",
- c->pilotId);
+ c->pilot_id);
gnome_config_push_prefix (prefix);
gnome_config_set_bool ("open_secret", c->open_secret);
@@ -85,7 +85,7 @@ todoconduit_dupe_configuration (EToDoConduitCfg *c)
retval = g_new0 (EToDoConduitCfg, 1);
retval->sync_type = c->sync_type;
retval->open_secret = c->open_secret;
- retval->pilotId = c->pilotId;
+ retval->pilot_id = c->pilot_id;
return retval;
}
diff --git a/calendar/conduits/todo/todo-conduit.c b/calendar/conduits/todo/todo-conduit.c
index f1f0e11e28..6b9659f70f 100644
--- a/calendar/conduits/todo/todo-conduit.c
+++ b/calendar/conduits/todo/todo-conduit.c
@@ -48,7 +48,6 @@
GnomePilotConduit * conduit_get_gpilot_conduit (guint32);
void conduit_destroy_gpilot_conduit (GnomePilotConduit*);
-void local_record_from_compobject (EToDoLocalRecord *local, CalComponent *comp);
#define CONDUIT_VERSION "0.8.11"
#ifdef G_LOG_DOMAIN
@@ -60,15 +59,13 @@ void local_record_from_compobject (EToDoLocalRecord *local, CalComponent *comp);
/* #undef DEBUG_CALCONDUIT */
#ifdef DEBUG_CALCONDUIT
-#define show_exception(e) g_warning ("Exception: %s\n", CORBA_exception_id (e))
-#define LOG(e...) g_log(G_LOG_DOMAIN,G_LOG_LEVEL_MESSAGE, e)
+#define LOG(e...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, e)
#else
-#define show_exception(e)
#define LOG(e...)
#endif
-#define WARN(e...) g_log(G_LOG_DOMAIN,G_LOG_LEVEL_WARNING, e)
-#define INFO(e...) g_log(G_LOG_DOMAIN,G_LOG_LEVEL_MESSAGE, e)
+#define WARN(e...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, e)
+#define INFO(e...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, e)
/* debug spew DELETE ME */
static char *print_local (EToDoLocalRecord *local)
@@ -120,19 +117,16 @@ static char *print_remote (PilotRecord *remote)
return buff;
}
-/* Given a GCalConduitContxt*, allocates the structure */
+/* Context Routines */
static void
-e_todo_context_new (EToDoConduitContext **ctxt, guint32 pilotId)
+e_todo_context_new (EToDoConduitContext **ctxt, guint32 pilot_id)
{
*ctxt = g_new0 (EToDoConduitContext,1);
g_assert (ctxt!=NULL);
- todoconduit_load_configuration (&(*ctxt)->cfg, pilotId);
+ todoconduit_load_configuration (&(*ctxt)->cfg, pilot_id);
}
-
-/* Destroys any data allocated by gcalconduit_new_context
- and deallocates its data. */
static void
e_todo_context_destroy (EToDoConduitContext **ctxt)
{
@@ -149,15 +143,135 @@ e_todo_context_destroy (EToDoConduitContext **ctxt)
*ctxt = NULL;
}
+/* Map routines */
+static char *
+map_name (EToDoConduitContext *ctxt)
+{
+ char *filename;
+
+ filename = g_strdup_printf ("%s/evolution/local/Calendar/pilot-map-%d.xml", g_get_home_dir (), ctxt->cfg->pilot_id);
+
+ return filename;
+}
+
+static void
+map_sax_start_element (void *data, const xmlChar *name,
+ const xmlChar **attrs)
+{
+ EToDoConduitContext *ctxt = (EToDoConduitContext *)data;
+
+ if (!strcmp (name, "map")) {
+ char *uid = NULL;
+ guint32 *pid = g_new (guint32, 1);
+
+ *pid = 0;
+
+ while (*attrs != NULL) {
+ const xmlChar **val = attrs;
+
+ val++;
+ if (!strcmp (*attrs, "uid"))
+ uid = g_strdup (*val);
+
+ if (!strcmp (*attrs, "pilotid"))
+ *pid = strtoul (*val, NULL, 0);
+
+ attrs = ++val;
+ }
+
+ if (uid && *pid != 0)
+ g_hash_table_insert (ctxt->map, pid, uid);
+ else
+ g_free (pid);
+ }
+}
+
+static int
+map_sax_parse (xmlSAXHandler *handler, EToDoConduitContext *ctxt, const char *filename)
+{
+ int ret = 0;
+ xmlParserCtxtPtr xc;
+
+ if (!g_file_exists (filename))
+ return 0;
+
+ xc = xmlCreateFileParserCtxt (filename);
+ if (xc == NULL)
+ return -1;
+
+ xc->sax = handler;
+ xc->userData = (void *)ctxt;
+
+ xmlParseDocument (xc);
+
+ if (xc->wellFormed)
+ ret = 0;
+ else
+ ret = -1;
+
+ if (handler != NULL)
+ xc->sax = NULL;
+ xmlFreeParserCtxt(xc);
+
+ return ret;
+}
static void
-gnome_calendar_load_cb (GtkWidget *cal_client,
- CalClientLoadStatus status,
- EToDoConduitContext *ctxt)
+map_write_foreach (gpointer key, gpointer value, gpointer data)
+{
+ xmlNodePtr root = data;
+ xmlNodePtr mnode;
+ unsigned long *pid = key;
+ const char *uid = value;
+ char *pidstr;
+
+ mnode = xmlNewChild (root, NULL, "map", NULL);
+ xmlSetProp (mnode, "uid", uid);
+ pidstr = g_strdup_printf ("%lu", *pid);
+ xmlSetProp (mnode, "pilot_id", pidstr);
+ g_free (pidstr);
+}
+
+static int
+map_write (EToDoConduitContext *ctxt, char *filename)
+{
+ xmlDocPtr doc;
+ int ret;
+
+ if (ctxt->map == NULL)
+ return 0;
+
+ doc = xmlNewDoc ("1.0");
+ if (doc == NULL) {
+ WARN ("Pilot map file could not be created\n");
+ return -1;
+ }
+ doc->root = xmlNewDocNode(doc, NULL, "PilotMap", NULL);
+
+ g_hash_table_foreach (ctxt->map, map_write_foreach, doc->root);
+
+ /* Write the file */
+ xmlSetDocCompressMode (doc, 0);
+ ret = xmlSaveFile (filename, doc);
+ if (ret < 0) {
+ g_warning ("Pilot map file '%s' could not be saved\n", filename);
+ return -1;
+ }
+
+ xmlFreeDoc (doc);
+
+ return 0;
+}
+
+/* Calendar Server routines */
+static void
+start_calendar_server_cb (GtkWidget *cal_client,
+ CalClientLoadStatus status,
+ EToDoConduitContext *ctxt)
{
CalClient *client = CAL_CLIENT (cal_client);
- LOG (" todo-conduit entering gnome_calendar_load_cb, tried=%d\n",
+ LOG (" entering start_calendar_server_load_cb, tried=%d\n",
ctxt->calendar_load_tried);
if (status == CAL_CLIENT_LOAD_SUCCESS) {
@@ -172,21 +286,15 @@ gnome_calendar_load_cb (GtkWidget *cal_client,
}
cal_client_create_calendar (client, ctxt->calendar_file);
- ctxt->calendar_load_tried = 1;
+ ctxt->calendar_load_tried = TRUE;
}
}
-
-
-
-
static int
-start_calendar_server (GnomePilotConduitStandardAbs *conduit,
- EToDoConduitContext *ctxt)
+start_calendar_server (EToDoConduitContext *ctxt)
{
- g_return_val_if_fail(conduit!=NULL,-2);
- g_return_val_if_fail(ctxt!=NULL,-2);
+ g_return_val_if_fail (ctxt != NULL, -2);
ctxt->client = cal_client_new ();
@@ -195,7 +303,7 @@ start_calendar_server (GnomePilotConduitStandardAbs *conduit,
"evolution/local/Calendar/calendar.ics");
gtk_signal_connect (GTK_OBJECT (ctxt->client), "cal_loaded",
- gnome_calendar_load_cb, ctxt);
+ start_calendar_server_cb, ctxt);
LOG (" calling cal_client_load_calendar\n");
cal_client_load_calendar (ctxt->client, ctxt->calendar_file);
@@ -210,59 +318,9 @@ start_calendar_server (GnomePilotConduitStandardAbs *conduit,
return -1;
}
-
-static GSList *
-get_calendar_objects(GnomePilotConduitStandardAbs *conduit,
- gboolean *status,
- EToDoConduitContext *ctxt)
-{
- GList *uids;
- GSList *result = NULL;
-
- g_return_val_if_fail (conduit != NULL, NULL);
- g_return_val_if_fail (ctxt != NULL, NULL);
-
- uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_TODO);
-
- LOG ("got %d todo entries from cal server\n", g_list_length (uids));
-
- if (status != NULL)
- (*status) = TRUE;
-
- if (! uids)
- INFO ("No entries found");
- else {
- GList *c;
- for (c=uids; c; c=c->next)
- result = g_slist_prepend (result, (gchar *) c->data);
- /* FIX ME free uids */
- }
-
- return result;
-}
-
-
-static void
-local_record_from_comp_uid (EToDoLocalRecord *local,
- char *uid,
- EToDoConduitContext *ctxt)
-{
- CalComponent *comp;
- CalClientGetStatus status;
-
- g_assert(local!=NULL);
-
- status = cal_client_get_object (ctxt->client, uid, &comp);
-
- if (status == CAL_CLIENT_GET_SUCCESS)
- local_record_from_compobject (local, comp);
- else
- INFO ("Object did not exist");
-}
-
-
-
-static const char *gnome_pilot_status_to_string (gint status)
+/* Utility routines */
+static const char *
+status_to_string (gint status)
{
switch(status) {
case GnomePilotRecordPending: return "GnomePilotRecordPending";
@@ -275,14 +333,37 @@ static const char *gnome_pilot_status_to_string (gint status)
return "Unknown";
}
+static PilotRecord *
+local_record_to_pilot_record (EToDoLocalRecord *local,
+ EToDoConduitContext *ctxt)
+{
+ PilotRecord *p = NULL;
+
+ g_return_val_if_fail (local != NULL, NULL);
+ g_assert (local->comp != NULL);
+ g_assert (local->todo != NULL );
+
+ LOG ("local_record_to_remote_record\n");
+
+ p = g_new0 (PilotRecord, 1);
+ p->ID = local->local.ID;
+ p->attr = local->local.attr;
+ p->archived = local->local.archived;
+ p->secret = local->local.secret;
+
+ /* Generate pilot record structure */
+ p->record = g_new0 (char,0xffff);
+ p->length = pack_ToDo (local->todo, p->record, 0xffff);
+
+ return p;
+}
/*
* converts a CalComponent object to a EToDoLocalRecord
*/
-void
-local_record_from_compobject(EToDoLocalRecord *local,
- CalComponent *comp)
+static void
+local_record_from_comp (EToDoLocalRecord *local, CalComponent *comp)
{
int *priority;
struct icaltimetype *completed;
@@ -295,7 +376,7 @@ local_record_from_compobject(EToDoLocalRecord *local,
unsigned long *pilot_id;
unsigned long *pilot_status;
- LOG ("local_record_from_compobject\n");
+ LOG ("local_record_from_comp\n");
g_return_if_fail (local != NULL);
g_return_if_fail (comp != NULL);
@@ -364,68 +445,23 @@ local_record_from_compobject(EToDoLocalRecord *local,
local->local.archived = 0;
}
-
-/*
- * Given a PilotRecord, find the matching record in
- * the calendar repository. If no match, return NULL
- */
-static EToDoLocalRecord *
-find_record_in_repository(GnomePilotConduitStandardAbs *conduit,
- PilotRecord *remote,
- EToDoConduitContext *ctxt)
+static void
+local_record_from_uid (EToDoLocalRecord *local,
+ char *uid,
+ EToDoConduitContext *ctxt)
{
- char *uid = NULL;
- EToDoLocalRecord *loc;
- CalClientGetStatus status;
CalComponent *comp;
-
- g_return_val_if_fail(conduit!=NULL,NULL);
- g_return_val_if_fail(remote!=NULL,NULL);
-
- LOG ("find_record_in_repository: remote=%s... ",
- print_remote (remote));
+ CalClientGetStatus status;
- LOG ("requesting %ld", remote->ID);
+ g_assert(local!=NULL);
- status = cal_client_get_uid_by_pilot_id (ctxt->client, remote->ID, &uid);
+ status = cal_client_get_object (ctxt->client, uid, &comp);
if (status == CAL_CLIENT_GET_SUCCESS) {
- status = cal_client_get_object (ctxt->client, uid, &comp);
- if (status == CAL_CLIENT_GET_SUCCESS) {
- LOG ("found %s\n", cal_component_get_as_string (comp));
- loc = g_new0(EToDoLocalRecord,1);
- /* memory allocated in new_from_string is freed in free_match */
- local_record_from_compobject (loc, comp);
- return loc;
- }
- LOG ("Pilot ID found, but comp for uid %s was not\n", uid);
- }
-
- INFO ("Object did not exist");
- return NULL;
-}
-
-
-/*
- * updates an given CalComponent in the repository
- */
-static void
-update_calendar_entry_in_repository(GnomePilotConduitStandardAbs *conduit,
- CalComponent *comp,
- EToDoConduitContext *ctxt)
-{
- gboolean success;
-
- g_return_if_fail (conduit != NULL);
- g_return_if_fail (comp != NULL);
-
- LOG (" update_calendar_entry_in_repository "
- "saving to desktop\n%s", cal_component_get_as_string (comp));
-
- success = cal_client_update_object (ctxt->client, comp);
-
- if (!success)
- WARN (_("Error while communicating with calendar server"));
+ local_record_from_comp (local, comp);
+ } else {
+ INFO ("Object did not exist");
+ }
}
@@ -505,90 +541,34 @@ comp_from_remote_record (GnomePilotConduitStandardAbs *conduit,
return comp;
}
-
-/* Code blatantly stolen from
- * calendar-pilot-sync.c:
- *
- * (C) 1999 International GNOME Support
- *
- * Author:
- * Miguel de Icaza (miguel@gnome-support.com)
- *
- * store a copy of a pilot record in the desktop database
- *
- */
-static gint
-update_record (GnomePilotConduitStandardAbs *conduit,
- PilotRecord *remote,
- EToDoConduitContext *ctxt)
+static void
+update_comp (GnomePilotConduitStandardAbs *conduit, CalComponent *comp,
+ EToDoConduitContext *ctxt)
{
- CalComponent *comp;
- CalClientGetStatus status;
- struct ToDo todo;
- unsigned long pilot_status = GnomePilotRecordNothing;
- char *uid;
-
- g_return_val_if_fail (remote!=NULL,-1);
-
- memset (&todo, 0, sizeof (struct ToDo));
- unpack_ToDo (&todo, remote->record, remote->length);
-
- LOG (" cal_client_get_uid_by_pilot_id... ");
-
- status = cal_client_get_uid_by_pilot_id (ctxt->client,
- remote->ID, &uid);
- if (status == CAL_CLIENT_GET_SUCCESS) {
- LOG (" succeeded with '%s'\n", uid);
- LOG (" cal_client_get_object... ");
- status = cal_client_get_object (ctxt->client, uid, &comp);
- }
-
- if (status != CAL_CLIENT_GET_SUCCESS) {
- comp = comp_from_remote_record (conduit, remote, NULL);
- } else {
- CalComponent *new_comp;
-
- LOG ("succeeded %s\n", cal_component_get_as_string (comp));
-
- new_comp = comp_from_remote_record (conduit, remote, comp);
- gtk_object_unref (GTK_OBJECT (comp));
- comp = new_comp;
- }
+ gboolean success;
- /* update record on server */
- {
- const char *uid;
- unsigned long *pilot_id;
+ g_return_if_fail (conduit != NULL);
+ g_return_if_fail (comp != NULL);
- cal_component_get_uid (comp, &uid);
- cal_component_get_pilot_id (comp, &pilot_id);
-
- update_calendar_entry_in_repository (conduit, comp, ctxt);
- cal_client_update_pilot_id (ctxt->client, (char *) uid,
- *pilot_id, pilot_status);
- }
+ LOG ("update_comp: saving to desktop\n%s\n",
+ cal_component_get_as_string (comp));
- /*
- * Shutdown
- */
- gtk_object_unref (GTK_OBJECT (comp));
- free_ToDo(&todo);
+ success = cal_client_update_object (ctxt->client, comp);
- return 0;
+ if (!success)
+ WARN (_("Error while communicating with calendar server"));
}
static void
check_for_slow_setting (GnomePilotConduit *c, EToDoConduitContext *ctxt)
{
- GList *uids;
- unsigned long int entry_number;
-
- uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_TODO);
-
- entry_number = g_list_length (uids);
+ int count, map_count;
- /* If the local base is empty, do a slow sync */
- if (entry_number == 0) {
+ count = g_list_length (ctxt->uids);
+ map_count = g_hash_table_size (ctxt->map);
+
+ /* If there are no objects or objects but no log */
+ if ((count == 0) || (count > 0 && map_count == 0)) {
GnomePilotConduitStandard *conduit;
LOG (" doing slow sync\n");
conduit = GNOME_PILOT_CONDUIT_STANDARD (c);
@@ -598,24 +578,21 @@ check_for_slow_setting (GnomePilotConduit *c, EToDoConduitContext *ctxt)
}
}
+/* Pilot syncing callbacks */
static gint
-pre_sync (GnomePilotConduit *c,
+pre_sync (GnomePilotConduit *conduit,
GnomePilotDBInfo *dbi,
EToDoConduitContext *ctxt)
{
- int l;
+ GnomePilotConduitStandardAbs *abs_conduit;
+ int len, ret;
unsigned char *buf;
- GnomePilotConduitStandardAbs *conduit;
+ char *filename;
+ xmlSAXHandler handler;
+ GList *changes, *l;
gint num_records;
- /*
- g_log_set_always_fatal (G_LOG_LEVEL_ERROR |
- G_LOG_LEVEL_CRITICAL |
- G_LOG_LEVEL_WARNING);
- */
-
-
- conduit = GNOME_PILOT_CONDUIT_STANDARD_ABS(c);
+ abs_conduit = GNOME_PILOT_CONDUIT_STANDARD_ABS (conduit);
LOG ("---------------------------------------------------------\n");
LOG ("pre_sync: ToDo Conduit v.%s", CONDUIT_VERSION);
@@ -623,102 +600,174 @@ pre_sync (GnomePilotConduit *c,
ctxt->client = NULL;
- if (start_calendar_server (GNOME_PILOT_CONDUIT_STANDARD_ABS(c), ctxt) != 0) {
- WARN(_("Could not start gnomecal server"));
- gnome_pilot_conduit_error(GNOME_PILOT_CONDUIT(c),
- _("Could not start gnomecal server"));
+ if (start_calendar_server (ctxt) != 0) {
+ WARN(_("Could not start wombat server"));
+ gnome_pilot_conduit_error (conduit, _("Could not start wombat"));
return -1;
}
-
+ /* Get the local database */
+ ctxt->uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_TODO);
+
+ /* Load the uid <--> pilot id mapping */
+ ctxt->map = g_hash_table_new (g_int_hash, g_int_equal);
+ memset (&handler, 0, sizeof (xmlSAXHandler));
+ handler.startElement = map_sax_start_element;
+
+ filename = map_name (ctxt);
+ ret = map_sax_parse (&handler, ctxt, filename);
+ if (ret < 0)
+ return ret;
+
+ g_free (filename);
+
+ /* Find the added, modified and deleted items */
+ changes = cal_client_get_changed_uids (ctxt->client, CALOBJ_TYPE_TODO, 0);
+ for (l = changes; l != NULL; l = l->next) {
+ CalObjChange *coc = l->data;
+
+ switch (coc->type) {
+ case CALOBJ_UPDATED:
+ if (g_hash_table_lookup (ctxt->map, coc->uid))
+ ctxt->modified = g_list_prepend (ctxt->modified, coc);
+ else
+ ctxt->added = g_list_prepend (ctxt->added, coc);
+ break;
+ case CALOBJ_REMOVED:
+ ctxt->deleted = g_list_prepend (ctxt->deleted, coc);
+ break;
+ }
+ }
+ g_list_free (changes);
+
+ /* Set the count information */
num_records = cal_client_get_n_objects (ctxt->client, CALOBJ_TYPE_TODO);
- gnome_pilot_conduit_standard_abs_set_num_local_records(GNOME_PILOT_CONDUIT_STANDARD_ABS(c), num_records);
+ gnome_pilot_conduit_standard_abs_set_num_local_records(abs_conduit, num_records);
+ num_records = g_list_length (ctxt->added);
+ gnome_pilot_conduit_standard_abs_set_num_new_local_records (abs_conduit, num_records);
+ num_records = g_list_length (ctxt->modified);
+ gnome_pilot_conduit_standard_abs_set_num_updated_local_records (abs_conduit, num_records);
+ num_records = g_list_length (ctxt->deleted);
+ gnome_pilot_conduit_standard_abs_set_num_deleted_local_records(abs_conduit, num_records);
- /* FIX ME How are we going to fill in these fields? */
- num_records = 0;
- gnome_pilot_conduit_standard_abs_set_num_updated_local_records(GNOME_PILOT_CONDUIT_STANDARD_ABS(c), num_records);
- gnome_pilot_conduit_standard_abs_set_num_new_local_records(GNOME_PILOT_CONDUIT_STANDARD_ABS(c), num_records);
- gnome_pilot_conduit_standard_abs_set_num_deleted_local_records(GNOME_PILOT_CONDUIT_STANDARD_ABS(c), num_records);
+ gtk_object_set_data (GTK_OBJECT (conduit), "dbinfo", dbi);
- gtk_object_set_data (GTK_OBJECT(c), "dbinfo", dbi);
-
buf = (unsigned char*)g_malloc (0xffff);
- l = dlp_ReadAppBlock (dbi->pilot_socket, dbi->db_handle, 0,
+ len = dlp_ReadAppBlock (dbi->pilot_socket, dbi->db_handle, 0,
(unsigned char *)buf, 0xffff);
- if (l < 0) {
- WARN(_("Could not read pilot's ToDo application block"));
- WARN("dlp_ReadAppBlock(...) = %d",l);
- gnome_pilot_conduit_error(GNOME_PILOT_CONDUIT(c),
- _("Could not read pilot's ToDo application block"));
+ if (len < 0) {
+ WARN (_("Could not read pilot's ToDo application block"));
+ WARN ("dlp_ReadAppBlock(...) = %d", len);
+ gnome_pilot_conduit_error (conduit,
+ _("Could not read pilot's ToDo application block"));
return -1;
}
- unpack_ToDoAppInfo (&(ctxt->ai), buf, l);
+ unpack_ToDoAppInfo (&(ctxt->ai), buf, len);
g_free (buf);
- check_for_slow_setting (c, ctxt);
+ check_for_slow_setting (conduit, ctxt);
return 0;
}
-/**
- * Find (if possible) the local record which matches
- * the given PilotRecord.
- * if successfull, return non-zero and set *local to
- * a non-null value (the located local record),
- * otherwise return 0 and set *local = NULL;
- */
+static gint
+update_record (GnomePilotConduitStandardAbs *conduit,
+ PilotRecord *remote,
+ EToDoConduitContext *ctxt)
+{
+ CalComponent *comp;
+ CalClientGetStatus status;
+ struct ToDo todo;
+ const char *uid;
+
+ LOG ("update_record\n");
+
+ g_return_val_if_fail (remote != NULL, -1);
+
+ memset (&todo, 0, sizeof (struct ToDo));
+ unpack_ToDo (&todo, remote->record, remote->length);
+
+ uid = g_hash_table_lookup (ctxt->map, &remote->ID);
+
+ if (uid)
+ status = cal_client_get_object (ctxt->client, uid, &comp);
+ else
+ status = CAL_CLIENT_LOAD_ERROR;
+
+ if (status != CAL_CLIENT_GET_SUCCESS) {
+ comp = comp_from_remote_record (conduit, remote, NULL);
+ } else {
+ CalComponent *new_comp;
+
+ LOG ("succeeded %s\n", cal_component_get_as_string (comp));
+
+ new_comp = comp_from_remote_record (conduit, remote, comp);
+ gtk_object_unref (GTK_OBJECT (comp));
+ comp = new_comp;
+ }
+
+ update_comp (conduit, comp, ctxt);
+
+ if (!uid) {
+ guint32 *pid = g_new (guint32, 1);
+
+ *pid = remote->ID;
+ cal_component_get_uid (comp, &uid);
+ g_hash_table_insert (ctxt->map, pid, g_strdup (uid));
+ }
+
+ gtk_object_unref (GTK_OBJECT (comp));
+ free_ToDo(&todo);
+
+ return 0;
+}
static gint
-match_record (GnomePilotConduitStandardAbs *conduit,
- EToDoLocalRecord **local,
- PilotRecord *remote,
- EToDoConduitContext *ctxt)
+match_record (GnomePilotConduitStandardAbs *conduit,
+ EToDoLocalRecord **local,
+ PilotRecord *remote,
+ EToDoConduitContext *ctxt)
{
+ char *uid;
+
LOG ("match_record: looking for local copy of %s\n",
- print_remote (remote));
-
+ print_remote (remote));
+
g_return_val_if_fail (local != NULL, -1);
g_return_val_if_fail (remote != NULL, -1);
- *local = find_record_in_repository (conduit, remote, ctxt);
+ uid = g_hash_table_lookup (ctxt->map, &remote->ID);
+
+ if (!uid)
+ return -1;
+ *local = g_new0 (EToDoLocalRecord, 1);
+ local_record_from_uid (*local, uid, ctxt);
+
if (*local == NULL)
- LOG (" match_record: not found.\n");
- else
- LOG (" match_record: found, %s\n",
- print_local (*local));
-
- if (*local == NULL)
return -1;
-
+
return 0;
}
-/**
- * Free the data allocated by a previous match_record call.
- * If successfull, return non-zero and ser *local=NULL, otherwise
- * return 0.
- */
static gint
-free_match (GnomePilotConduitStandardAbs *conduit,
- EToDoLocalRecord **local,
- EToDoConduitContext *ctxt)
+free_match (GnomePilotConduitStandardAbs *conduit,
+ EToDoLocalRecord **local,
+ EToDoConduitContext *ctxt)
{
LOG ("free_match: %s\n", print_local (*local));
g_return_val_if_fail (local != NULL, -1);
g_return_val_if_fail (*local != NULL, -1);
+ gtk_object_unref (GTK_OBJECT ((*local)->comp));
g_free (*local);
*local = NULL;
return 0;
}
-/*
- Move to archive and set status to Nothing
- */
static gint
archive_local (GnomePilotConduitStandardAbs *conduit,
EToDoLocalRecord *local,
@@ -731,9 +780,6 @@ archive_local (GnomePilotConduitStandardAbs *conduit,
return -1;
}
-/*
- Store in archive and set status to Nothing
- */
static gint
archive_remote (GnomePilotConduitStandardAbs *conduit,
EToDoLocalRecord *local,
@@ -741,30 +787,29 @@ archive_remote (GnomePilotConduitStandardAbs *conduit,
EToDoConduitContext *ctxt)
{
LOG ("archive_remote: doing nothing with %s\n",
- print_local (local));
-
-/* g_return_val_if_fail(remote!=NULL,-1); */
-/* g_return_val_if_fail(local!=NULL,-1); */
-
+ print_local (local));
+
+ g_return_val_if_fail (remote != NULL, -1);
+ g_return_val_if_fail (local != NULL, -1);
+
return -1;
}
-/*
- Store and set status to Nothing
- */
static gint
store_remote (GnomePilotConduitStandardAbs *conduit,
PilotRecord *remote,
EToDoConduitContext *ctxt)
{
+ int ret;
+
g_return_val_if_fail (remote != NULL, -1);
LOG ("store_remote: copying pilot record %s to desktop\n",
print_remote (remote));
- remote->attr = GnomePilotRecordNothing;
+ ret = update_record (conduit, remote, ctxt);
- return update_record (conduit, remote, ctxt);
+ return ret;
}
static gint
@@ -784,59 +829,48 @@ iterate (GnomePilotConduitStandardAbs *conduit,
EToDoLocalRecord **local,
EToDoConduitContext *ctxt)
{
- static GSList *events,*iterator;
- static int hest;
+ static GList *uids, *iterator;
+ static int count;
g_return_val_if_fail (local != NULL, -1);
if (*local == NULL) {
LOG ("beginning iteration");
- events = get_calendar_objects (conduit, NULL, ctxt);
- hest = 0;
+ uids = ctxt->uids;
+ count = 0;
- if (events != NULL) {
- LOG ("iterating over %d records", g_slist_length (events));
+ if (uids != NULL) {
+ LOG ("iterating over %d records", g_list_length (uids));
+
*local = g_new0 (EToDoLocalRecord, 1);
+ local_record_from_uid (*local, uids->data, ctxt);
- local_record_from_comp_uid (*local,
- (gchar*)events->data,
- ctxt);
- iterator = events;
+ iterator = uids;
} else {
LOG ("no events");
(*local) = NULL;
+ return -1;
}
} else {
- LOG ("continuing iteration\n");
- hest++;
- if (g_slist_next (iterator) == NULL) {
- GSList *l;
+ count++;
+ if (g_list_next (iterator)) {
+ iterator = g_list_next (iterator);
- LOG ("ending");
- /** free stuff allocated for iteration */
- g_free((*local));
-
- LOG ("iterated over %d records", hest);
- for (l=events; l; l = l->next)
- g_free (l->data);
+ *local = g_new0 (EToDoLocalRecord, 1);
+ local_record_from_uid (*local, iterator->data, ctxt);
+ } else {
+ LOG ("iteration ending");
- g_slist_free (events);
+ /* Tell the pilot the iteration is over */
+ *local = NULL;
- /* ends iteration */
- (*local) = NULL;
return 0;
- } else {
- iterator = g_slist_next (iterator);
- local_record_from_comp_uid(*local,
- (gchar*)(iterator->data),
- ctxt);
}
}
return 1;
}
-
static gint
iterate_specific (GnomePilotConduitStandardAbs *conduit,
EToDoLocalRecord **local,
@@ -844,44 +878,88 @@ iterate_specific (GnomePilotConduitStandardAbs *conduit,
gint archived,
EToDoConduitContext *ctxt)
{
- (*local) = NULL; /* ??? */
+ static GList *changes, *iterator;
+ static int count;
- /* debugging */
- {
- const char *tmp = gnome_pilot_status_to_string (flag);
- LOG ("\niterate_specific: (flag = %s)... ", tmp);
- }
+ g_return_val_if_fail (local != NULL, 0);
- g_return_val_if_fail (local != NULL, -1);
+ /* FIX ME Hack - gnome-pilot does not recognize iterate_specific err values */
+ if (*local == NULL) {
+ LOG ("beginning iteration for %s\n", status_to_string (flag));
- /* iterate until a record meets the criteria */
- while (gnome_pilot_conduit_standard_abs_iterate (conduit,
- (LocalRecord**)local)) {
- if ((*local) == NULL)
+ switch (flag) {
+ case GnomePilotRecordNew:
+ changes = ctxt->added;
break;
- if (archived && ((*local)->local.archived == archived))
+ case GnomePilotRecordModified:
+ changes = ctxt->modified;
break;
- if (((*local)->local.attr == flag))
+ case GnomePilotRecordDeleted:
+ changes = ctxt->deleted;
break;
- }
+ }
+
+ count = 0;
+
+ if (changes != NULL) {
+ CalObjChange *coc = changes->data;
+
+ LOG ("iterating over %d records", g_list_length (changes));
+
+ *local = g_new0 (EToDoLocalRecord, 1);
+ local_record_from_uid (*local, coc->uid, ctxt);
- if ((*local))
- LOG (" found %s\n", print_local (*local));
- else
- LOG (" no more found.\n");
+ iterator = changes;
+ } else {
+ LOG ("no events");
+ (*local) = NULL;
+ return 0;
+ }
+ } else {
+ count++;
+ if (g_list_next (iterator)) {
+ CalObjChange *coc;
+
+ iterator = g_list_next (iterator);
+ coc = iterator->data;
+
+ *local = g_new0 (EToDoLocalRecord, 1);
+ local_record_from_uid (*local, coc->uid, ctxt);
+ } else {
+ LOG ("iteration ending");
- return (*local) == NULL ? 0 : 1;
+ /* Tell the pilot the iteration is over */
+ (*local) = NULL;
+
+ return 0;
+ }
+ }
+
+ return 1;
}
static gint
purge (GnomePilotConduitStandardAbs *conduit,
EToDoConduitContext *ctxt)
{
- LOG ("purge: doing nothing\n");
+ GList *l;
+ char *filename;
+ int ret = 0;
+
+ LOG ("purge\n");
+
+ /* FIX ME report an error */
+ for (l = ctxt->deleted; l != NULL; l = l->next) {
+ CalObjChange *coc = l->data;
+
+ cal_client_remove_object (ctxt->client, coc->uid);
+ }
- /* HEST, gem posterne her */
+ filename = map_name (ctxt);
+ ret = map_write (ctxt, filename);
+ g_free (filename);
- return -1;
+ return ret;
}
@@ -891,37 +969,28 @@ set_status (GnomePilotConduitStandardAbs *conduit,
gint status,
EToDoConduitContext *ctxt)
{
- gboolean success;
-
- LOG ("set_status: %s status is now '%s' for %s\n",
- print_local (local),
- gnome_pilot_status_to_string (status),
- cal_component_get_as_string (local->comp));
+ CalObjChange *coc;
g_return_val_if_fail (local != NULL, -1);
g_assert (local->comp != NULL);
-
- local->local.attr = status;
- if (status == GnomePilotRecordDeleted) {
- const char *uid;
- cal_component_get_uid (local->comp, &uid);
- success = cal_client_remove_object (ctxt->client, uid);
- } else {
- const char *uid;
- unsigned long *pilot_id;
- cal_component_get_uid (local->comp, &uid);
- cal_component_get_pilot_id (local->comp, &pilot_id);
+ LOG ("set_status: %s status is now '%s' for %s\n",
+ print_local (local),
+ status_to_string (status),
+ cal_component_get_as_string (local->comp));
- success = cal_client_update_object (ctxt->client, local->comp);
- cal_client_update_pilot_id (ctxt->client, (char *) uid,
- *pilot_id, status);
+ /* FIX ME New and modified? */
+ switch (status) {
+ case GnomePilotRecordNew:
+ break;
+ case GnomePilotRecordModified:
+ break;
+ case GnomePilotRecordDeleted:
+ coc = g_new0 (CalObjChange, 1);
+ ctxt->deleted = g_list_prepend (ctxt->deleted, coc);
+ break;
}
- if (!success) {
- WARN (_("Error while communicating with calendar server"));
- }
-
return 0;
}
@@ -938,10 +1007,12 @@ set_archived (GnomePilotConduitStandardAbs *conduit,
g_assert(local->comp!=NULL);
local->local.archived = archived;
- update_calendar_entry_in_repository(conduit,local->comp,ctxt);
+ update_comp (conduit, local->comp, ctxt);
+
/* FIXME: This should move the entry into a speciel
calendar file, eg. Archive, or (by config option), simply
delete it */
+
return 0;
}
@@ -952,24 +1023,11 @@ set_pilot_id (GnomePilotConduitStandardAbs *conduit,
EToDoConduitContext *ctxt)
{
const char *uid;
- unsigned long *pilot_status;
-
- LOG ("set_pilot_id: %s pilot ID is now '%d'\n",
- print_local (local), ID);
-
- g_return_val_if_fail(local!=NULL,-1);
- g_assert(local->comp!=NULL);
-
- local->local.ID = ID;
- cal_component_set_pilot_id (local->comp, (unsigned long *)&ID);
-
+ guint32 *pid = g_new (guint32, 1);
+
cal_component_get_uid (local->comp, &uid);
- cal_component_get_pilot_status (local->comp, &pilot_status);
-
- cal_client_update_pilot_id (ctxt->client,
- (char *) uid,
- local->local.ID,
- *pilot_status);
+ *pid = ID;
+ g_hash_table_insert (ctxt->map, pid, g_strdup (uid));
return 0;
}
@@ -980,80 +1038,13 @@ transmit (GnomePilotConduitStandardAbs *conduit,
PilotRecord **remote,
EToDoConduitContext *ctxt)
{
- PilotRecord *p;
- int *priority;
- struct icaltimetype *completed;
- CalComponentText summary;
- GSList *d_list = NULL;
- CalComponentText *description;
- CalComponentDateTime due;
- time_t due_time;
- CalComponentClassification classif;
-
LOG ("transmit: encoding local %s\n", print_local (local));
- g_return_val_if_fail (local != NULL,-1);
- g_return_val_if_fail (remote != NULL,-1);
- g_assert (local->comp != NULL);
-
- p = g_new0 (PilotRecord,1);
-
- p->ID = local->local.ID;
- p->attr = local->local.attr;
- p->archived = local->local.archived;
- p->secret = local->local.secret;
-
- local->todo = g_new0 (struct ToDo,1);
-
- /* STOP: don't replace these with g_strdup, since free_ToDo
- uses free to deallocate */
- cal_component_get_summary (local->comp, &summary);
- if (summary.value)
- local->todo->description = strdup ((char *) summary.value);
-
- cal_component_get_description_list (local->comp, &d_list);
- if (d_list) {
- description = (CalComponentText *) d_list->data;
- if (description && description->value)
- local->todo->note = strdup (description->value);
- else
- local->todo->note = NULL;
- } else {
- local->todo->note = NULL;
- }
-
- cal_component_get_due (local->comp, &due);
- if (due.value) {
- due_time = icaltime_as_timet (*due.value);
-
- local->todo->due = *localtime (&due_time);
- local->todo->indefinite = 0;
- } else {
- local->todo->indefinite = 1;
- }
-
- cal_component_get_completed (local->comp, &completed);
- if (completed) {
- local->todo->complete = 1;
- cal_component_free_icaltimetype (completed);
- }
-
- cal_component_get_priority (local->comp, &priority);
- if (priority) {
- local->todo->priority = *priority;
- cal_component_free_priority (priority);
- }
-
- cal_component_get_classification (local->comp, &classif);
- if (classif == CAL_COMPONENT_CLASS_PRIVATE)
- p->attr = p->attr & dlpRecAttrSecret;
-
- /* Generate pilot record structure */
- p->record = g_new0 (char,0xffff);
- p->length = pack_ToDo (local->todo, p->record, 0xffff);
-
- *remote = p;
+ *remote = local_record_to_pilot_record (local, ctxt);
+ if (!*remote)
+ return -1;
+
return 0;
}
@@ -1063,14 +1054,12 @@ free_transmit (GnomePilotConduitStandardAbs *conduit,
PilotRecord **remote,
EToDoConduitContext *ctxt)
{
- LOG ("free_transmit: freeing %s\n",
- print_local (local));
+ LOG ("free_transmit: freeing %s\n", print_local (local));
g_return_val_if_fail (local != NULL, -1);
g_return_val_if_fail (remote != NULL, -1);
- /* free_ToDo(local->todo); */ /* FIX ME is this needed? */
- g_free ((*remote)->record);
+ g_free (*remote);
*remote = NULL;
return 0;
@@ -1084,9 +1073,8 @@ compare (GnomePilotConduitStandardAbs *conduit,
EToDoConduitContext *ctxt)
{
/* used by the quick compare */
- PilotRecord *remoteOfLocal;
- int err;
- int retval;
+ PilotRecord *local_pilot;
+ int retval = 0;
LOG ("compare: local=%s remote=%s...\n",
print_local (local), print_remote (remote));
@@ -1094,31 +1082,21 @@ compare (GnomePilotConduitStandardAbs *conduit,
g_return_val_if_fail (local!=NULL,-1);
g_return_val_if_fail (remote!=NULL,-1);
- err = transmit(conduit,local,&remoteOfLocal,ctxt);
- if (err != 0) return err;
+ local_pilot = local_record_to_pilot_record (local, ctxt);
+ if (!local_pilot)
+ return -1;
- retval = 0;
- if (remote->length == remoteOfLocal->length) {
- if (memcmp (remoteOfLocal->record,
- remote->record, remote->length)!=0) {
- LOG (" compare failed on contents\n");
- retval = 1;
- }
- } else {
- LOG(" compare failed on length\n");
+ if (remote->length != local_pilot->length
+ || memcmp (local_pilot->record, remote->record, remote->length))
retval = 1;
- }
-
- if (retval == 0) {
+ if (retval == 0)
LOG (" match.\n");
- } else {
- /* debug spew */
- LOG (" local:%s\n", print_remote (remoteOfLocal));
- LOG (" remote:%s\n", print_remote (remote));
- }
-
- free_transmit(conduit,local,&remoteOfLocal,ctxt);
+ else
+ LOG (" did not match");
+
+ g_free (local_pilot);
+
return retval;
}
@@ -1134,6 +1112,8 @@ compare_backup (GnomePilotConduitStandardAbs *conduit,
g_return_val_if_fail(local!=NULL,-1);
g_return_val_if_fail(remote!=NULL,-1);
+ /* FIX ME - What the hell? */
+
return -1;
}
@@ -1142,25 +1122,21 @@ static gint
delete_all (GnomePilotConduitStandardAbs *conduit,
EToDoConduitContext *ctxt)
{
- GSList *events,*it;
- gboolean error;
+ GList *uids, *it;
gboolean success;
- events = get_calendar_objects(conduit,&error,ctxt);
-
LOG ("delete_all: deleting all objects from desktop\n");
- if (error == FALSE) return -1;
- for (it=events; it; it = g_slist_next (it)) {
+ uids = cal_client_get_uids (ctxt->client, CALOBJ_TYPE_TODO);
+
+ for (it = uids; it != NULL; it = g_list_next (it)) {
success = cal_client_remove_object (ctxt->client, it->data);
if (!success)
INFO ("Object did not exist");
-
- g_free (it->data);
}
+ cal_obj_uid_list_free (uids);
- g_slist_free (events);
return 0;
}
@@ -1176,7 +1152,7 @@ accept_all_cookies (CORBA_unsigned_long request_id,
GnomePilotConduit *
-conduit_get_gpilot_conduit (guint32 pilotId)
+conduit_get_gpilot_conduit (guint32 pilot_id)
{
GtkObject *retval;
EToDoConduitContext *ctxt;
@@ -1202,9 +1178,9 @@ conduit_get_gpilot_conduit (guint32 pilotId)
g_assert (retval != NULL);
gnome_pilot_conduit_construct (GNOME_PILOT_CONDUIT (retval),
- "ToDoConduit");
+ "e_todo_conduit");
- e_todo_context_new (&ctxt, pilotId);
+ e_todo_context_new (&ctxt, pilot_id);
gtk_object_set_data (GTK_OBJECT (retval), "todoconduit_context", ctxt);
gtk_signal_connect (retval, "match_record", (GtkSignalFunc) match_record, ctxt);
diff --git a/calendar/conduits/todo/todo-conduit.h b/calendar/conduits/todo/todo-conduit.h
index ee2576ddb7..9e9a02e6db 100644
--- a/calendar/conduits/todo/todo-conduit.h
+++ b/calendar/conduits/todo/todo-conduit.h
@@ -54,16 +54,28 @@ struct _EToDoLocalRecord {
/* This is the context for all the GnomeCal conduit methods. */
typedef struct _EToDoConduitContext EToDoConduitContext;
struct _EToDoConduitContext {
- struct ToDoAppInfo ai;
EToDoConduitCfg *cfg;
- CalClient *client;
+ struct ToDoAppInfo ai;
+
+ CalClient *client;
+ char *calendar_file;
gboolean calendar_load_tried;
gboolean calendar_load_success;
- char *calendar_file;
+ GList *uids;
+
+ GList *added;
+ GList *modified;
+ GList *deleted;
+
+ GHashTable *map;
};
#endif __TODO_CONDUIT_H__
+
+
+
+
diff --git a/calendar/idl/evolution-calendar.idl b/calendar/idl/evolution-calendar.idl
index 4b9b9a7b34..27c7971057 100644
--- a/calendar/idl/evolution-calendar.idl
+++ b/calendar/idl/evolution-calendar.idl
@@ -33,6 +33,11 @@ module Calendar {
const CalObjType TYPE_JOURNAL = 1 << 2;
const CalObjType TYPE_ANY = 0x07;
+ /* Types of object changes made */
+ typedef long CalObjChangeType;
+ const CalObjChangeType UPDATED = 1 << 0;
+ const CalObjChangeType REMOVED = 1 << 1;
+
/* Types of alarms */
enum AlarmType {
MAIL,
@@ -61,6 +66,12 @@ module Calendar {
typedef sequence<CalObjInstance> CalObjInstanceSeq;
+ /* An object change */
+ struct CalObjChange {
+ CalObjUID uid;
+ CalObjChangeType type;
+ };
+
/* An alarm trigger instance */
struct CalAlarmInstance {
CalObjUID uid;
@@ -71,6 +82,8 @@ module Calendar {
typedef sequence<CalAlarmInstance> CalAlarmInstanceSeq;
+ typedef sequence<CalObjChange> CalObjChangeSeq;
+
interface Listener;
/* Calendar client interface */
@@ -92,6 +105,9 @@ module Calendar {
/* Gets a list of UIDs based on object type */
CalObjUIDSeq get_uids (in CalObjType type);
+ /* Gets a list of UIDs that changed based on object type */
+ CalObjChangeSeq get_changed_uids (in CalObjType type, in Time_t since);
+
/* Gets a list of objects that occur or recur in the specified time range */
CalObjUIDSeq get_objects_in_range (in CalObjType type,
in Time_t start, in Time_t end)
diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c
index 06b75d52a6..c4a047a262 100644
--- a/calendar/pcs/cal-backend-file.c
+++ b/calendar/pcs/cal-backend-file.c
@@ -77,6 +77,7 @@ static void cal_backend_file_create (CalBackend *backend, GnomeVFSURI *uri);
static int cal_backend_file_get_n_objects (CalBackend *backend, CalObjType type);
static char *cal_backend_file_get_object (CalBackend *backend, const char *uid);
+static CalObjType cal_backend_file_get_type_by_uid (CalBackend *backend, const char *uid);
static GList *cal_backend_file_get_uids (CalBackend *backend, CalObjType type);
static GList *cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type,
time_t start, time_t end);
@@ -150,6 +151,7 @@ cal_backend_file_class_init (CalBackendFileClass *class)
backend_class->create = cal_backend_file_create;
backend_class->get_n_objects = cal_backend_file_get_n_objects;
backend_class->get_object = cal_backend_file_get_object;
+ backend_class->get_type_by_uid = cal_backend_file_get_type_by_uid;
backend_class->get_uids = cal_backend_file_get_uids;
backend_class->get_objects_in_range = cal_backend_file_get_objects_in_range;
backend_class->get_alarms_in_range = cal_backend_file_get_alarms_in_range;
@@ -791,6 +793,34 @@ cal_backend_file_get_object (CalBackend *backend, const char *uid)
return cal_component_get_as_string (comp);
}
+static CalObjType
+cal_backend_file_get_type_by_uid (CalBackend *backend, const char *uid)
+{
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
+ CalComponent *comp;
+ CalComponentVType type;
+
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
+
+ comp = lookup_component (cbfile, uid);
+ if (!comp)
+ return CAL_COMPONENT_NO_TYPE;
+
+ type = cal_component_get_vtype (comp);
+ switch (type) {
+ case CAL_COMPONENT_EVENT:
+ return CALOBJ_TYPE_EVENT;
+ case CAL_COMPONENT_TODO:
+ return CALOBJ_TYPE_TODO;
+ case CAL_COMPONENT_JOURNAL:
+ return CALOBJ_TYPE_JOURNAL;
+ default:
+ return CAL_COMPONENT_NO_TYPE;
+ }
+}
+
/* Builds a list of UIDs from a list of CalComponent objects */
static void
build_uids_list (GList **list, GList *components)
diff --git a/calendar/pcs/cal-backend-imc.c b/calendar/pcs/cal-backend-imc.c
deleted file mode 100644
index d50fc0d347..0000000000
--- a/calendar/pcs/cal-backend-imc.c
+++ /dev/null
@@ -1,1421 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* Evolution calendar - Internet Mail Consortium formats backend
- *
- * Copyright (C) 2000 Helix Code, Inc.
- *
- * Authors: Federico Mena-Quintero <federico@helixcode.com>
- * Seth Alves <alves@helixcode.com>
- * Miguel de Icaza <miguel@helixcode.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 <gtk/gtksignal.h>
-#include "cal-backend-imc.h"
-#include "cal-util/icalendar.h"
-
-
-
-/* Supported calendar formats from the IMC */
-typedef enum {
- CAL_FORMAT_UNKNOWN,
- CAL_FORMAT_VCALENDAR,
- CAL_FORMAT_ICALENDAR
-} CalendarFormat;
-
-/* Private part of the CalBackendIMC structure */
-typedef struct {
- /* URI where the calendar data is stored */
- GnomeVFSURI *uri;
-
- /* Format of this calendar (iCalendar or vCalendar) */
- CalendarFormat format;
-
- /* List of Cal objects with their listeners */
- GList *clients;
-
- /* All the iCalObject structures in the calendar, hashed by UID. The
- * hash key *is* icalobj->uid; it is not copied, so don't free it when
- * you remove an object from the hash table.
- */
- GHashTable *object_hash;
-
- /* All events, TODOs, and journals in the calendar */
- GList *events;
- GList *todos;
- GList *journals;
-
- /* Whether a calendar has been loaded */
- guint loaded : 1;
-
- /* Do we need to sync to permanent storage? */
- gboolean dirty : 1;
-} IMCPrivate;
-
-
-
-static void cal_backend_imc_class_init (CalBackendIMCClass *class);
-static void cal_backend_imc_init (CalBackendIMC *bimc);
-static void cal_backend_imc_destroy (GtkObject *object);
-
-static GnomeVFSURI *cal_backend_imc_get_uri (CalBackend *backend);
-static void cal_backend_imc_add_cal (CalBackend *backend, Cal *cal);
-static CalBackendLoadStatus cal_backend_imc_load (CalBackend *backend, GnomeVFSURI *uri);
-static void cal_backend_imc_create (CalBackend *backend, GnomeVFSURI *uri);
-
-static int cal_backend_imc_get_n_objects (CalBackend *backend, CalObjType type);
-static char *cal_backend_imc_get_object (CalBackend *backend, const char *uid);
-static GList *cal_backend_imc_get_uids (CalBackend *backend, CalObjType type);
-static GList *cal_backend_imc_get_events_in_range (CalBackend *backend, time_t start, time_t end);
-static GList *cal_backend_imc_get_alarms_in_range (CalBackend *backend, time_t start, time_t end);
-static gboolean cal_backend_imc_get_alarms_for_object (CalBackend *backend, const char *uid,
- time_t start, time_t end,
- GList **alarms);
-static gboolean cal_backend_imc_update_object (CalBackend *backend, const char *uid,
- const char *calobj);
-static gboolean cal_backend_imc_remove_object (CalBackend *backend, const char *uid);
-static char *cal_backend_imc_get_uid_by_pilot_id (CalBackend *backend, unsigned long int pilot_id);
-static void cal_backend_imc_update_pilot_id (CalBackend *backend,
- const char *uid,
- unsigned long int pilot_id,
- unsigned long int pilot_status);
-
-
-
-static void notify_update (CalBackendIMC *cbimc, const char *uid);
-
-static CalBackendClass *parent_class;
-
-
-
-/**
- * cal_backend_imc_get_type:
- * @void:
- *
- * Registers the #CalBackendIMC class if necessary, and returns the type ID
- * associated to it.
- *
- * Return value: The type ID of the #CalBackendIMC class.
- **/
-GtkType
-cal_backend_imc_get_type (void)
-{
- static GtkType cal_backend_imc_type = 0;
-
- if (!cal_backend_imc_type) {
- static const GtkTypeInfo cal_backend_imc_info = {
- "CalBackendIMC",
- sizeof (CalBackendIMC),
- sizeof (CalBackendIMCClass),
- (GtkClassInitFunc) cal_backend_imc_class_init,
- (GtkObjectInitFunc) cal_backend_imc_init,
- NULL, /* reserved_1 */
- NULL, /* reserved_2 */
- (GtkClassInitFunc) NULL
- };
-
- cal_backend_imc_type = gtk_type_unique (CAL_BACKEND_TYPE, &cal_backend_imc_info);
- }
-
- return cal_backend_imc_type;
-}
-
-/* Class initialization function for the IMC backend */
-static void
-cal_backend_imc_class_init (CalBackendIMCClass *class)
-{
- GtkObjectClass *object_class;
- CalBackendClass *backend_class;
-
- object_class = (GtkObjectClass *) class;
- backend_class = (CalBackendClass *) class;
-
- parent_class = gtk_type_class (CAL_BACKEND_TYPE);
-
- backend_class->get_uri = cal_backend_imc_get_uri;
- backend_class->add_cal = cal_backend_imc_add_cal;
- backend_class->load = cal_backend_imc_load;
- backend_class->create = cal_backend_imc_create;
- backend_class->get_n_objects = cal_backend_imc_get_n_objects;
- backend_class->get_object = cal_backend_imc_get_object;
- backend_class->get_uids = cal_backend_imc_get_uids;
- backend_class->get_events_in_range = cal_backend_imc_get_events_in_range;
- backend_class->get_alarms_in_range = cal_backend_imc_get_alarms_in_range;
- backend_class->get_alarms_for_object = cal_backend_imc_get_alarms_for_object;
- backend_class->update_object = cal_backend_imc_update_object;
- backend_class->remove_object = cal_backend_imc_remove_object;
- backend_class->get_uid_by_pilot_id = cal_backend_imc_get_uid_by_pilot_id;
- backend_class->update_pilot_id = cal_backend_imc_update_pilot_id;
-
- object_class->destroy = cal_backend_imc_destroy;
-}
-
-/* Object initialization function for the IMC backend */
-static void
-cal_backend_imc_init (CalBackendIMC *cbimc)
-{
- IMCPrivate *priv;
-
- priv = g_new0 (IMCPrivate, 1);
- cbimc->priv = priv;
-
- priv->format = CAL_FORMAT_UNKNOWN;
-}
-
-static void
-save_to_vcal (CalBackendIMC *cbimc, char *fname)
-{
- FILE *fp;
- IMCPrivate *priv;
- VObject *vcal;
- GList *l;
-
- priv = cbimc->priv;
-
- if (g_file_exists (fname)) {
- char *backup_name = g_strconcat (fname, "~", NULL);
-
- /* FIXME: do error checking on system calls!!!! */
-
- if (g_file_exists (backup_name))
- unlink (backup_name);
-
- rename (fname, backup_name);
- g_free (backup_name);
- }
-
- vcal = newVObject (VCCalProp);
- addPropValue (vcal, VCProdIdProp,
- "-//Helix Code//NONSGML Evolution Calendar//EN");
-
- /* Per the vCalendar spec, this must be "1.0" */
- addPropValue (vcal, VCVersionProp, "1.0");
-
- /* FIXME: this should really iterate over the object hash table instead
- * of the lists; that way we won't lose objects if they are of a type
- * that we don't support but are in the calendar anyways.
- */
-
- for (l = priv->events; l; l = l->next) {
- iCalObject *ical = l->data;
- VObject *vobject = ical_object_to_vobject (ical);
- addVObjectProp (vcal, vobject);
- }
-
- for (l = priv->todos; l; l = l->next) {
- iCalObject *ical = l->data;
- VObject *vobject = ical_object_to_vobject (ical);
- addVObjectProp (vcal, vobject);
- }
-
- for (l = priv->journals; l; l = l->next) {
- iCalObject *ical = l->data;
- VObject *vobject = ical_object_to_vobject (ical);
- addVObjectProp (vcal, vobject);
- }
-
- fp = fopen(fname,"w");
- if (fp) {
- writeVObject(fp, vcal);
- fclose(fp);
- }
- cleanVObject (vcal);
- cleanStrTbl ();
-}
-
-/* Saves a calendar */
-static void
-save (CalBackendIMC *cbimc)
-{
- char *str_uri;
- IMCPrivate *priv = cbimc->priv;
-
- str_uri = gnome_vfs_uri_to_string (priv->uri,
- (GNOME_VFS_URI_HIDE_USER_NAME
- | GNOME_VFS_URI_HIDE_PASSWORD
- | GNOME_VFS_URI_HIDE_HOST_NAME
- | GNOME_VFS_URI_HIDE_HOST_PORT
- | GNOME_VFS_URI_HIDE_TOPLEVEL_METHOD));
-
- if (!priv->dirty)
- return;
-
- switch (priv->format) {
- case CAL_FORMAT_VCALENDAR:
- save_to_vcal (cbimc, str_uri);
- break;
-
- case CAL_FORMAT_ICALENDAR:
- /*icalendar_calendar_save (cbimc, str_uri);*/
- /* FIX ME */
- break;
-
- default:
- g_message ("save(): Attempt to save a calendar with an unknown format!");
- break;
- }
-
- printf ("cal-backend-imc: '%s' saved\n", str_uri);
-
- g_free (str_uri);
-}
-
-/* g_hash_table_foreach() callback to destroy an iCalObject */
-static void
-free_ical_object (gpointer key, gpointer value, gpointer data)
-{
- iCalObject *ico;
-
- ico = value;
- ical_object_unref (ico);
-}
-
-/* Destroys an IMC backend's data */
-static void
-destroy (CalBackendIMC *cbimc)
-{
- IMCPrivate *priv;
-
- priv = cbimc->priv;
-
- if (priv->uri) {
- gnome_vfs_uri_unref (priv->uri);
- priv->uri = NULL;
- }
-
- g_assert (priv->clients == NULL);
-
- if (priv->object_hash) {
- g_hash_table_foreach (priv->object_hash, free_ical_object, NULL);
- g_hash_table_destroy (priv->object_hash);
- priv->object_hash = NULL;
- }
-
- g_list_free (priv->events);
- g_list_free (priv->todos);
- g_list_free (priv->journals);
-
- priv->events = NULL;
- priv->todos = NULL;
- priv->journals = NULL;
-
- priv->loaded = FALSE;
- priv->format = CAL_FORMAT_UNKNOWN;
-}
-
-/* Destroy handler for the IMC backend */
-static void
-cal_backend_imc_destroy (GtkObject *object)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (IS_CAL_BACKEND_IMC (object));
-
- cbimc = CAL_BACKEND_IMC (object);
- priv = cbimc->priv;
-
- /*
- if (priv->loaded)
- save (cbimc);
- */
-
- destroy (cbimc);
-
- g_free (priv);
- cbimc->priv = NULL;
-
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
-
-
-
-/* iCalObject manipulation functions */
-
-/* Looks up an object by its UID in the backend's object hash table */
-static iCalObject *
-lookup_object (CalBackendIMC *cbimc, const char *uid)
-{
- IMCPrivate *priv;
- iCalObject *ico;
-
- priv = cbimc->priv;
- ico = g_hash_table_lookup (priv->object_hash, uid);
-
- return ico;
-}
-
-/* Ensures that an iCalObject has a unique identifier. If it doesn't have one,
- * it will create one for it.
- */
-static void
-ensure_uid (iCalObject *ico)
-{
- char *buf;
- gulong str_time;
- static guint seqno = 0;
-
- if (ico->uid)
- return;
-
- str_time = (gulong) time (NULL);
-
- /* Is this good enough? */
-
- buf = g_strdup_printf ("Evolution-Calendar-%d-%ld-%u",
- (int) getpid(), str_time, seqno++);
- ico->uid = buf;
-}
-
-/* Adds an object to the calendar backend. Does *not* perform notification to
- * calendar clients.
- */
-static void
-add_object (CalBackendIMC *cbimc, iCalObject *ico)
-{
- IMCPrivate *priv;
-
- g_assert (ico != NULL);
-
- priv = cbimc->priv;
-
-#if 0
- /* FIXME: gnomecal old code */
- ico->new = 0;
-#endif
-
- ensure_uid (ico);
- g_hash_table_insert (priv->object_hash, ico->uid, ico);
-
- priv->dirty = TRUE;
-
- switch (ico->type) {
- case ICAL_EVENT:
- priv->events = g_list_prepend (priv->events, ico);
-#if 0
- /* FIXME: gnomecal old code */
- ical_object_try_alarms (ico);
-# ifdef DEBUGGING_MAIL_ALARM
- ico->malarm.trigger = 0;
- calendar_notify (0, ico);
-# endif
-#endif
- break;
-
- case ICAL_TODO:
- priv->todos = g_list_prepend (priv->todos, ico);
- break;
-
- case ICAL_JOURNAL:
- priv->journals = g_list_prepend (priv->journals, ico);
- break;
-
- default:
- g_assert_not_reached ();
- }
-
-#if 0
- /* FIXME: gnomecal old code */
- ico->last_mod = time (NULL);
-#endif
-}
-
-/* Removes an object from the backend's hash and lists. Does not perform
- * notification on the clients.
- */
-static void
-remove_object (CalBackendIMC *cbimc, iCalObject *ico)
-{
- IMCPrivate *priv;
- GList **list, *l;
-
- priv = cbimc->priv;
-
- g_assert (ico->uid != NULL);
- g_hash_table_remove (priv->object_hash, ico->uid);
-
- priv->dirty = TRUE;
-
- switch (ico->type) {
- case ICAL_EVENT:
- list = &priv->events;
- break;
-
- case ICAL_TODO:
- list = &priv->todos;
- break;
-
- case ICAL_JOURNAL:
- list = &priv->journals;
- break;
-
- default:
- /* Make the compiler shut up. */
- list = NULL;
- g_assert_not_reached ();
- }
-
- l = g_list_find (*list, ico);
- g_assert (l != NULL);
-
- *list = g_list_remove_link (*list, l);
- g_list_free_1 (l);
-
- ical_object_unref (ico);
-}
-
-/* Load a calendar from a VObject */
-static void
-load_from_vobject (CalBackendIMC *cbimc, VObject *vobject)
-{
- IMCPrivate *priv;
- VObjectIterator i;
-
- priv = cbimc->priv;
-
- g_assert (!priv->loaded);
- g_assert (priv->object_hash == NULL);
- priv->object_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
- initPropIterator (&i, vobject);
-
- while (moreIteration (&i)) {
- VObject *this;
- iCalObject *ical;
- const char *object_name;
-
- this = nextVObject (&i);
- object_name = vObjectName (this);
-#if 0
- /* FIXME? What is this used for in gnomecal? */
- if (strcmp (object_name, VCDCreatedProp) == 0) {
- cal->created = time_from_isodate (str_val (this));
- continue;
- }
-#endif
- if (strcmp (object_name, VCLocationProp) == 0)
- continue; /* FIXME: imlement */
-
- if (strcmp (object_name, VCProdIdProp) == 0)
- continue; /* FIXME: implement */
-
- if (strcmp (object_name, VCVersionProp) == 0)
- continue; /* FIXME: implement */
-
- if (strcmp (object_name, VCTimeZoneProp) == 0)
- continue; /* FIXME: implement */
-
- ical = ical_object_create_from_vobject (this, object_name);
-
- /* FIXME: some broken files (ahem, old KOrganizer files) may
- * have duplicated UIDs. This is Bad(tm). Deal with it by
- * creating new UIDs for them and spitting some messages to the
- * console.
- */
-
- if (ical)
- add_object (cbimc, ical);
- }
-}
-
-
-
-/* Calendar backend methods */
-
-/* Get_uri handler for the IMC backend */
-static GnomeVFSURI *
-cal_backend_imc_get_uri (CalBackend *backend)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (priv->loaded, NULL);
- g_assert (priv->uri != NULL);
-
- return priv->uri;
-}
-
-/* Callback used when a Cal is destroyed */
-static void
-cal_destroy_cb (GtkObject *object, gpointer data)
-{
- Cal *cal;
- Cal *lcal;
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- GList *l;
-
- fprintf (stderr, "cal_destroy_cb(): A Cal was destroyed!\n");
-
- cal = CAL (object);
-
- cbimc = CAL_BACKEND_IMC (data);
- priv = cbimc->priv;
-
- /* Find the cal in the list of clients */
-
- for (l = priv->clients; l; l = l->next) {
- lcal = CAL (l->data);
-
- if (lcal == cal)
- break;
- }
-
- g_assert (l != NULL);
-
- /* Disconnect */
-
- priv->clients = g_list_remove_link (priv->clients, l);
- g_list_free_1 (l);
-
- /* When all clients go away, notify the parent factory about it so that
- * it may decide whether to kill the backend or not.
- */
- if (!priv->clients)
- cal_backend_last_client_gone (CAL_BACKEND (cbimc));
-}
-
-/* Add_cal handler for the IMC backend */
-static void
-cal_backend_imc_add_cal (CalBackend *backend, Cal *cal)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_if_fail (priv->loaded);
- g_return_if_fail (cal != NULL);
- g_return_if_fail (IS_CAL (cal));
-
- /* We do not keep a reference to the Cal since the calendar user agent
- * owns it.
- */
-
- gtk_signal_connect (GTK_OBJECT (cal), "destroy",
- GTK_SIGNAL_FUNC (cal_destroy_cb),
- backend);
-
- priv->clients = g_list_prepend (priv->clients, cal);
-}
-
-static icalcomponent *
-icalendar_parse_file (char *fname)
-{
- FILE *fp;
- icalcomponent *comp = NULL;
- char *str;
- struct stat st;
- int n;
-
- fp = fopen (fname, "r");
- if (!fp) {
- /* FIXME: remove message */
- g_message ("icalendar_parse_file(): Cannot open open calendar file.");
- return NULL;
- }
-
- stat (fname, &st);
-
- str = g_malloc (st.st_size + 2);
-
- n = fread (str, 1, st.st_size, fp);
- if (n != st.st_size) {
- /* FIXME: remove message, return error code instead */
- g_message ("icalendar_parse_file(): Read error.");
- }
- str[n] = '\0';
-
- fclose (fp);
-
- comp = icalparser_parse_string (str);
- g_free (str);
-
- return comp;
-}
-
-static void
-icalendar_calendar_load (CalBackendIMC *cbimc, char *fname)
-{
- IMCPrivate *priv;
- icalcomponent *comp;
- icalcomponent *subcomp;
- iCalObject *ical;
-
- priv = cbimc->priv;
-
- g_assert (!priv->loaded);
- g_assert (priv->object_hash == NULL);
-
- priv->object_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
- comp = icalendar_parse_file (fname);
- subcomp = icalcomponent_get_first_component (comp,
- ICAL_ANY_COMPONENT);
- while (subcomp) {
- ical = ical_object_create_from_icalcomponent (subcomp);
- if (ical->type != ICAL_EVENT &&
- ical->type != ICAL_TODO &&
- ical->type != ICAL_JOURNAL) {
- g_message ("icalendar_calendar_load(): Skipping unsupported "
- "iCalendar component.");
- } else
- add_object (cbimc, ical);
-
- subcomp = icalcomponent_get_next_component (comp,
- ICAL_ANY_COMPONENT);
- }
-}
-
-/* ics is to be used to designate a file containing (an arbitrary set of)
- * calendaring and scheduling information.
- *
- * ifb is to be used to designate a file containing free or busy time
- * information.
- *
- * anything else is assumed to be a vcal file.
- *
- * FIXME: should we return UNKNOWN at some point?
- */
-static CalendarFormat
-cal_get_type_from_filename (char *str_uri)
-{
- int len;
-
- if (str_uri == NULL)
- return CAL_FORMAT_VCALENDAR;
-
- len = strlen (str_uri);
- if (len < 4)
- return CAL_FORMAT_VCALENDAR;
-
- if (str_uri[len - 4] == '.' && str_uri[len - 3] == 'i' &&
- str_uri[len - 2] == 'c' && str_uri[len - 1] == 's')
- return CAL_FORMAT_ICALENDAR;
-
- if (str_uri[len - 4] == '.' && str_uri[len - 3] == 'i' &&
- str_uri[len - 2] == 'f' && str_uri[len - 1] == 'b')
- return CAL_FORMAT_ICALENDAR;
-
- if (str_uri[len - 4] == '.' && str_uri[len - 3] == 'i' &&
- str_uri[len - 2] == 'c' && str_uri[len - 1] == 's')
- return CAL_FORMAT_ICALENDAR;
-
- if (len < 5)
- return CAL_FORMAT_VCALENDAR;
-
- if (str_uri[len - 5] == '.' && str_uri[len - 4] == 'i' &&
- str_uri[len - 3] == 'c' && str_uri[len - 2] == 'a' &&
- str_uri[len - 1] == 'l')
- return CAL_FORMAT_ICALENDAR;
-
- return CAL_FORMAT_VCALENDAR;
-}
-
-/* Load handler for the IMC backend */
-static CalBackendLoadStatus
-cal_backend_imc_load (CalBackend *backend, GnomeVFSURI *uri)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- VObject *vobject;
- char *str_uri;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (!priv->loaded, CAL_BACKEND_LOAD_ERROR);
- g_return_val_if_fail (uri != NULL, CAL_BACKEND_LOAD_ERROR);
-
- /* FIXME: this looks rather bad; maybe we should check for local files
- * and fail if they are remote.
- */
-
- str_uri = gnome_vfs_uri_to_string (uri,
- (GNOME_VFS_URI_HIDE_USER_NAME
- | GNOME_VFS_URI_HIDE_PASSWORD
- | GNOME_VFS_URI_HIDE_HOST_NAME
- | GNOME_VFS_URI_HIDE_HOST_PORT
- | GNOME_VFS_URI_HIDE_TOPLEVEL_METHOD));
-
- /* look at the extension on the filename and decide if this is a
- * iCalendar or vCalendar file.
- */
- priv->format = cal_get_type_from_filename (str_uri);
-
- /* load */
-
- switch (priv->format) {
- case CAL_FORMAT_VCALENDAR:
- vobject = Parse_MIME_FromFileName (str_uri);
-
- if (!vobject){
- g_free (str_uri);
- return CAL_BACKEND_LOAD_ERROR;
- }
-
- load_from_vobject (cbimc, vobject);
- cleanVObject (vobject);
- cleanStrTbl ();
- break;
-
- case CAL_FORMAT_ICALENDAR:
- icalendar_calendar_load (cbimc, str_uri);
- break;
-
- default:
- g_free (str_uri);
- return CAL_BACKEND_LOAD_ERROR;
- }
-
- g_free (str_uri);
-
- gnome_vfs_uri_ref (uri);
-
- priv->uri = uri;
- priv->loaded = TRUE;
-
- return CAL_BACKEND_LOAD_SUCCESS;
-}
-
-/* Create handler for the IMC backend */
-static void
-cal_backend_imc_create (CalBackend *backend, GnomeVFSURI *uri)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- char *str_uri;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_if_fail (!priv->loaded);
- g_return_if_fail (uri != NULL);
-
- /* Create the new calendar information */
-
- g_assert (priv->object_hash == NULL);
- priv->object_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
- priv->dirty = TRUE;
-
- /* Done */
-
- /* FIXME: this looks rather bad; maybe we should check for local files
- * and fail if they are remote.
- */
-
- str_uri = gnome_vfs_uri_to_string (uri,
- (GNOME_VFS_URI_HIDE_USER_NAME
- | GNOME_VFS_URI_HIDE_PASSWORD
- | GNOME_VFS_URI_HIDE_HOST_NAME
- | GNOME_VFS_URI_HIDE_HOST_PORT
- | GNOME_VFS_URI_HIDE_TOPLEVEL_METHOD));
-
- /* look at the extension on the filename and decide if this is a
- * iCalendar or vCalendar file.
- */
- priv->format = cal_get_type_from_filename (str_uri);
-
- g_free (str_uri);
-
- gnome_vfs_uri_ref (uri);
-
- priv->uri = uri;
- priv->loaded = TRUE;
-
- save (cbimc);
-}
-
-struct get_n_objects_closure {
- CalObjType type;
- int n;
-};
-
-/* Counts the number of objects of the specified type. Called from
- * g_hash_table_foreach().
- */
-static void
-count_objects (gpointer key, gpointer value, gpointer data)
-{
- iCalObject *ico;
- struct get_n_objects_closure *c;
- gboolean store;
-
- ico = value;
- c = data;
-
- store = FALSE;
-
- if (ico->type == ICAL_EVENT)
- store = (c->type & CALOBJ_TYPE_EVENT) != 0;
- else if (ico->type == ICAL_TODO)
- store = (c->type & CALOBJ_TYPE_TODO) != 0;
- else if (ico->type == ICAL_JOURNAL)
- store = (c->type & CALOBJ_TYPE_JOURNAL) != 0;
-
- if (store)
- c->n++;
-}
-
-/* Get_n_objects handler for the IMC backend */
-static int
-cal_backend_imc_get_n_objects (CalBackend *backend, CalObjType type)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- struct get_n_objects_closure c;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (priv->loaded, -1);
-
- c.type = type;
- c.n = 0;
-
- g_hash_table_foreach (priv->object_hash, count_objects, &c);
-
- return c.n;
-}
-
-/* Get_object handler for the IMC backend */
-static char *
-cal_backend_imc_get_object (CalBackend *backend, const char *uid)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- iCalObject *ico;
- char *buf;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (uid != NULL, NULL);
-
- g_return_val_if_fail (priv->loaded, NULL);
- g_assert (priv->object_hash != NULL);
-
- ico = lookup_object (cbimc, uid);
-
- if (!ico)
- return NULL;
-
- buf = ical_object_to_string (ico);
-
- return buf;
-}
-
-struct get_uids_closure {
- CalObjType type;
- GList *uid_list;
-};
-
-/* Builds a list of UIDs for objects that match the sought type. Called from
- * g_hash_table_foreach().
- */
-static void
-build_uids_list (gpointer key, gpointer value, gpointer data)
-{
- iCalObject *ico;
- struct get_uids_closure *c;
- gboolean store;
-
- ico = value;
- c = data;
-
- store = FALSE;
-
- if (ico->type == ICAL_EVENT)
- store = (c->type & CALOBJ_TYPE_EVENT) ? TRUE : FALSE;
- else if (ico->type == ICAL_TODO)
- store = (c->type & CALOBJ_TYPE_TODO) ? TRUE : FALSE;
- else if (ico->type == ICAL_JOURNAL)
- store = (c->type & CALOBJ_TYPE_JOURNAL) ? TRUE : FALSE;
-
- if (store)
- c->uid_list = g_list_prepend (c->uid_list, g_strdup (ico->uid));
-}
-
-/* Get_uids handler for the IMC backend */
-static GList *
-cal_backend_imc_get_uids (CalBackend *backend, CalObjType type)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- struct get_uids_closure c;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (priv->loaded, NULL);
-
- c.type = type;
- c.uid_list = NULL;
- g_hash_table_foreach (priv->object_hash, build_uids_list, &c);
-
- return c.uid_list;
-}
-
-
-
-static char *
-cal_backend_imc_get_uid_by_pilot_id (CalBackend *backend,
- unsigned long int pilot_id)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- GList *l;
- iCalObject *obj = NULL;
-
- g_return_val_if_fail (backend != NULL, NULL);
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
- g_return_val_if_fail (priv->loaded, NULL);
-
- for (l = priv->events; l; l = l->next){
- obj = l->data;
- if (obj->pilot_id == pilot_id)
- goto done;
- }
-
- for (l = priv->todos; l; l = l->next){
- obj = l->data;
- if (obj->pilot_id == pilot_id)
- goto done;
- }
-
- done:
- if (!obj || obj->pilot_id != pilot_id)
- return NULL;
-
- return g_strdup (obj->uid);
-}
-
-
-void
-cal_backend_imc_update_pilot_id (CalBackend *backend,
- const char *uid,
- unsigned long int pilot_id,
- unsigned long int pilot_status)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- iCalObject *obj;
-
- g_return_if_fail (backend != NULL);
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
- g_return_if_fail (priv->loaded);
-
- obj = lookup_object (cbimc, uid);
-
- obj->pilot_id = pilot_id;
- obj->pilot_status = pilot_status;
-
- save (cbimc);
-
- notify_update (cbimc, uid);
-}
-
-
-
-/* Allocates and fills in a new CalObjInstance structure */
-static CalObjInstance *
-build_cal_obj_instance (iCalObject *ico, time_t start, time_t end)
-{
- CalObjInstance *icoi;
-
- g_assert (ico->uid != NULL);
-
- icoi = g_new (CalObjInstance, 1);
- icoi->uid = g_strdup (ico->uid);
- icoi->start = start;
- icoi->end = end;
-
- return icoi;
-}
-
-struct build_event_list_closure {
- CalBackendIMC *cbimc;
- GList *event_list;
-};
-
-/* Builds a sorted list of event object instances. Used as a callback from
- * ical_object_generate_events().
- */
-static int
-build_event_list (iCalObject *ico, time_t start, time_t end, void *data)
-{
- CalObjInstance *icoi;
- struct build_event_list_closure *c;
-
- c = data;
-
- icoi = build_cal_obj_instance (ico, start, end);
- c->event_list = g_list_prepend (c->event_list, icoi);
-
- return TRUE;
-}
-
-/* Compares two CalObjInstance structures by their start times. Called from
- * g_list_sort().
- */
-static gint
-compare_instance_func (gconstpointer a, gconstpointer b)
-{
- const CalObjInstance *ca, *cb;
- time_t diff;
-
- ca = a;
- cb = b;
-
- diff = ca->start - cb->start;
- return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
-}
-
-/* Get_events_in_range handler for the IMC backend */
-static GList *
-cal_backend_imc_get_events_in_range (CalBackend *backend, time_t start, time_t end)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- struct build_event_list_closure c;
- GList *l;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (priv->loaded, NULL);
-
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
-
- c.cbimc = cbimc;
- c.event_list = NULL;
-
- for (l = priv->events; l; l = l->next) {
- iCalObject *ico;
-
- ico = l->data;
- ical_object_generate_events (ico, start, end,
- build_event_list, &c);
- }
-
- c.event_list = g_list_sort (c.event_list, compare_instance_func);
- return c.event_list;
-}
-
-struct build_alarm_list_closure {
- time_t start;
- time_t end;
- GList *alarms;
-};
-
-/* Computes the offset in minutes from an alarm trigger to the actual event */
-static int
-compute_alarm_offset (CalendarAlarm *a)
-{
- int ofs;
-
- if (!a->enabled)
- return -1;
-
- switch (a->units) {
- case ALARM_MINUTES:
- ofs = a->count * 60;
- break;
-
- case ALARM_HOURS:
- ofs = a->count * 3600;
- break;
-
- case ALARM_DAYS:
- ofs = a->count * 24 * 3600;
- break;
-
- default:
- ofs = -1;
- g_assert_not_reached ();
- }
-
- return ofs;
-}
-
-/* Allocates and fills in a new CalAlarmInstance structure */
-static CalAlarmInstance *
-build_cal_alarm_instance (iCalObject *ico, enum AlarmType type, time_t trigger, time_t occur)
-{
- CalAlarmInstance *ai;
-
- g_assert (ico->uid != NULL);
-
- ai = g_new (CalAlarmInstance, 1);
- ai->uid = g_strdup (ico->uid);
- ai->type = type;
- ai->trigger = trigger;
- ai->occur = occur;
-
- return ai;
-}
-
-/* Adds the specified alarm to the list if its trigger time falls within the
- * requested range.
- */
-static void
-try_add_alarm (time_t occur_start, iCalObject *ico, CalendarAlarm *alarm,
- struct build_alarm_list_closure *c)
-{
- int ofs;
- time_t trigger;
- CalAlarmInstance *ai;
-
- if (!alarm->enabled)
- return;
-
- ofs = compute_alarm_offset (alarm);
- g_assert (ofs != -1);
-
- trigger = occur_start - ofs;
-
- if (trigger < c->start || trigger > c->end)
- return;
-
- ai = build_cal_alarm_instance (ico, alarm->type, trigger, occur_start);
- c->alarms = g_list_prepend (c->alarms, ai);
-}
-
-/* Builds a list of alarm instances. Used as a callback from
- * ical_object_generate_events().
- */
-static int
-build_alarm_list (iCalObject *ico, time_t start, time_t end, void *data)
-{
- struct build_alarm_list_closure *c;
-
- c = data;
-
- try_add_alarm (start, ico, &ico->dalarm, c);
- try_add_alarm (start, ico, &ico->aalarm, c);
- try_add_alarm (start, ico, &ico->palarm, c);
- try_add_alarm (start, ico, &ico->malarm, c);
-
- return TRUE;
-}
-
-/* Adds all the alarm triggers that occur within the specified time range */
-static GList *
-add_alarms_for_object (GList *alarms, iCalObject *ico, time_t start, time_t end)
-{
- struct build_alarm_list_closure c;
- int dofs, aofs, pofs, mofs;
- int max_ofs;
-
- dofs = compute_alarm_offset (&ico->dalarm);
- aofs = compute_alarm_offset (&ico->aalarm);
- pofs = compute_alarm_offset (&ico->palarm);
- mofs = compute_alarm_offset (&ico->malarm);
-
- max_ofs = MAX (dofs, MAX (aofs, MAX (pofs, mofs)));
- if (max_ofs == -1)
- return alarms;
-
- c.start = start;
- c.end = end;
- c.alarms = alarms;
-
- ical_object_generate_events (ico, start, end, build_alarm_list, &c);
- return c.alarms;
-}
-
-/* Get_alarms_in_range handler for the IMC backend */
-static GList *
-cal_backend_imc_get_alarms_in_range (CalBackend *backend, time_t start, time_t end)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- GList *l;
- GList *alarms;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (priv->loaded, NULL);
-
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
-
- /* Only VEVENT and VTODO components can have alarms */
-
- alarms = NULL;
-
- for (l = priv->events; l; l = l->next)
- alarms = add_alarms_for_object (alarms, (iCalObject *) l->data, start, end);
-
- for (l = priv->todos; l; l = l->next)
- alarms = add_alarms_for_object (alarms, (iCalObject *) l->data, start, end);
-
- alarms = g_list_sort (alarms, compare_instance_func);
- return alarms;
-}
-
-/* Get_alarms_for_object handler for the IMC backend */
-static gboolean
-cal_backend_imc_get_alarms_for_object (CalBackend *backend, const char *uid,
- time_t start, time_t end,
- GList **alarms)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- iCalObject *ico;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (priv->loaded, FALSE);
- g_return_val_if_fail (uid != NULL, FALSE);
- g_return_val_if_fail (start != -1 && end != -1, FALSE);
- g_return_val_if_fail (start <= end, FALSE);
- g_return_val_if_fail (alarms != NULL, FALSE);
-
- *alarms = NULL;
-
- ico = lookup_object (cbimc, uid);
- if (!ico)
- return FALSE;
-
- /* Only VEVENT and VTODO components can have alarms */
-
- if (ico->type != ICAL_EVENT && ico->type != ICAL_TODO)
- return TRUE;
-
- *alarms = add_alarms_for_object (*alarms, ico, start, end);
- *alarms = g_list_sort (*alarms, compare_instance_func);
-
- return TRUE;
-}
-
-/* Notifies a backend's clients that an object was updated */
-static void
-notify_update (CalBackendIMC *cbimc, const char *uid)
-{
- IMCPrivate *priv;
- GList *l;
-
- priv = cbimc->priv;
-
- for (l = priv->clients; l; l = l->next) {
- Cal *cal;
-
- cal = CAL (l->data);
- cal_notify_update (cal, uid);
- }
-}
-
-/* Notifies a backend's clients that an object was removed */
-static void
-notify_remove (CalBackendIMC *cbimc, const char *uid)
-{
- IMCPrivate *priv;
- GList *l;
-
- priv = cbimc->priv;
-
- for (l = priv->clients; l; l = l->next) {
- Cal *cal;
-
- cal = CAL (l->data);
- cal_notify_remove (cal, uid);
- }
-}
-
-/* Update_object handler for the IMC backend */
-static gboolean
-cal_backend_imc_update_object (CalBackend *backend, const char *uid, const char *calobj)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- iCalObject *ico, *new_ico;
- CalObjFindStatus status;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (priv->loaded, FALSE);
-
- g_return_val_if_fail (uid != NULL, FALSE);
- g_return_val_if_fail (calobj != NULL, FALSE);
-
- /* Pull the object from the string */
-
- status = ical_object_find_in_string (uid, calobj, &new_ico);
-
- if (status != CAL_OBJ_FIND_SUCCESS)
- return FALSE;
-
- /* Update the object */
-
- ico = lookup_object (cbimc, uid);
-
- if (ico)
- remove_object (cbimc, ico);
-
- add_object (cbimc, new_ico);
- new_ico->pilot_status = ICAL_PILOT_SYNC_MOD;
- save (cbimc);
-
- /* FIXME: do the notification asynchronously */
-
- notify_update (cbimc, new_ico->uid);
-
- return TRUE;
-}
-
-/* Remove_object handler for the IMC backend */
-static gboolean
-cal_backend_imc_remove_object (CalBackend *backend, const char *uid)
-{
- CalBackendIMC *cbimc;
- IMCPrivate *priv;
- iCalObject *ico;
-
- cbimc = CAL_BACKEND_IMC (backend);
- priv = cbimc->priv;
-
- g_return_val_if_fail (priv->loaded, FALSE);
-
- g_return_val_if_fail (uid != NULL, FALSE);
-
- ico = lookup_object (cbimc, uid);
- if (!ico)
- return FALSE;
-
- remove_object (cbimc, ico);
-
- priv->dirty = TRUE;
- save (cbimc);
-
- /* FIXME: do the notification asynchronously */
- notify_remove (cbimc, uid);
-
- return TRUE;
-}
diff --git a/calendar/pcs/cal-backend-imc.h b/calendar/pcs/cal-backend-imc.h
deleted file mode 100644
index 954bbc52cc..0000000000
--- a/calendar/pcs/cal-backend-imc.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Evolution calendar - Internet Mail Consortium formats backend
- *
- * Copyright (C) 2000 Helix Code, Inc.
- *
- * Authors: Federico Mena-Quintero <federico@helixcode.com>
- * Seth Alves <alves@helixcode.com>
- * Miguel de Icaza <miguel@helixcode.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 CAL_BACKEND_IMC_H
-#define CAL_BACKEND_IMC_H
-
-#include <libgnome/gnome-defs.h>
-#include "cal-backend.h"
-
-BEGIN_GNOME_DECLS
-
-
-
-#define CAL_BACKEND_IMC_TYPE (cal_backend_imc_get_type ())
-#define CAL_BACKEND_IMC(obj) (GTK_CHECK_CAST ((obj), CAL_BACKEND_IMC_TYPE, CalBackendIMC))
-#define CAL_BACKEND_IMC_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), CAL_BACKEND_IMC_TYPE, \
- CalBackendIMCClass))
-#define IS_CAL_BACKEND_IMC(obj) (GTK_CHECK_TYPE ((obj), CAL_BACKEND_IMC_TYPE))
-#define IS_CAL_BACKEND_IMC_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), CAL_BACKEND_IMC_TYPE))
-
-typedef struct _CalBackendIMC CalBackendIMC;
-typedef struct _CalBackendIMCClass CalBackendIMCClass;
-
-struct _CalBackendIMC {
- CalBackend backend;
-
- /* Private data */
- gpointer priv;
-};
-
-struct _CalBackendIMCClass {
- CalBackendClass parent_class;
-};
-
-GtkType cal_backend_imc_get_type (void);
-
-
-
-END_GNOME_DECLS
-
-#endif
diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c
index ee2b38a52c..3c7698a4d5 100644
--- a/calendar/pcs/cal-backend.c
+++ b/calendar/pcs/cal-backend.c
@@ -21,7 +21,10 @@
*/
#include <config.h>
-#include <gtk/gtksignal.h>
+#include <gtk/gtk.h>
+#include <gnome-xml/parser.h>
+#include <gnome-xml/parserInternals.h>
+#include <gnome-xml/xmlmemory.h>
#include "cal-backend.h"
#include "libversit/vcc.h"
@@ -35,6 +38,11 @@ enum {
};
static void cal_backend_class_init (CalBackendClass *class);
+static void cal_backend_init (CalBackend *backend);
+static gboolean cal_backend_log_sync (CalBackend *backend);
+static GHashTable *cal_backend_get_log_entries (CalBackend *backend,
+ time_t since,
+ CalObjType type);
static GtkObjectClass *parent_class;
@@ -64,7 +72,7 @@ cal_backend_get_type (void)
sizeof (CalBackend),
sizeof (CalBackendClass),
(GtkClassInitFunc) cal_backend_class_init,
- (GtkObjectInitFunc) NULL,
+ (GtkObjectInitFunc) cal_backend_init,
NULL, /* reserved_1 */
NULL, /* reserved_2 */
(GtkClassInitFunc) NULL
@@ -98,6 +106,14 @@ cal_backend_class_init (CalBackendClass *class)
gtk_object_class_add_signals (object_class, cal_backend_signals, LAST_SIGNAL);
}
+/* Per instance initialization function */
+static void
+cal_backend_init (CalBackend *backend)
+{
+ backend->uri = NULL;
+ backend->entries = NULL;
+}
+
/**
@@ -150,12 +166,32 @@ cal_backend_add_cal (CalBackend *backend, Cal *cal)
CalBackendLoadStatus
cal_backend_load (CalBackend *backend, GnomeVFSURI *uri)
{
+ CalBackendLoadStatus result;
+
g_return_val_if_fail (backend != NULL, CAL_BACKEND_LOAD_ERROR);
g_return_val_if_fail (IS_CAL_BACKEND (backend), CAL_BACKEND_LOAD_ERROR);
g_return_val_if_fail (uri != NULL, CAL_BACKEND_LOAD_ERROR);
g_assert (CLASS (backend)->load != NULL);
- return (* CLASS (backend)->load) (backend, uri);
+ result = (* CLASS (backend)->load) (backend, uri);
+
+ /* Remember the URI for saving the log file in the same dir and add
+ * a timeout handler so for saving pending entries sometimes */
+ if (backend->uri)
+ gnome_vfs_uri_unref (backend->uri);
+
+ if (backend->timer)
+ gtk_timeout_remove (backend->timer);
+
+ if (result == CAL_BACKEND_LOAD_SUCCESS) {
+ backend->uri = uri;
+ gnome_vfs_uri_ref (uri);
+ backend->timer = gtk_timeout_add (60000,
+ (GtkFunction)cal_backend_log_sync,
+ backend);
+ }
+
+ return result;
}
/**
@@ -239,6 +275,43 @@ cal_backend_get_uids (CalBackend *backend, CalObjType type)
return (* CLASS (backend)->get_uids) (backend, type);
}
+
+static void
+cal_backend_foreach_changed (gpointer key, gpointer value, gpointer data)
+{
+ GList **list = data;
+
+ *list = g_list_append (*list, value);
+}
+
+/**
+ * cal_backend_get_changed_uids:
+ * @backend:
+ * @type:
+ * @since:
+ *
+ *
+ *
+ * Return value:
+ **/
+GList *
+cal_backend_get_changed_uids (CalBackend *backend, CalObjType type, time_t since)
+{
+ GHashTable *hash;
+ GList *uids = NULL;
+
+ g_return_val_if_fail (backend != NULL, NULL);
+ g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+
+ hash = cal_backend_get_log_entries (backend, type, since);
+
+ if (hash)
+ g_hash_table_foreach (hash, cal_backend_foreach_changed, &uids);
+
+ return uids;
+}
+
+
/**
* cal_backend_get_objects_in_range:
* @backend: A calendar backend.
@@ -337,7 +410,284 @@ void cal_backend_update_pilot_id (CalBackend *backend, const char *uid,
pilot_id, pilot_status);
}
+/* Internal logging stuff */
+typedef enum {
+ CAL_BACKEND_UPDATED,
+ CAL_BACKEND_REMOVED
+} CalBackendLogEntryType;
+
+typedef struct {
+ char *uid;
+ CalObjType type;
+
+ CalBackendLogEntryType event_type;
+
+ time_t time_stamp;
+} CalBackendLogEntry;
+
+typedef struct {
+ CalObjType type;
+ time_t since;
+
+ gboolean in_valid_timestamp;
+
+ GHashTable *hash;
+} CalBackendParseState;
+
+static gchar *
+cal_backend_log_name (CalBackend *backend)
+{
+ gchar *path, *filename;
+
+ path = gnome_vfs_uri_extract_dirname (backend->uri);
+ filename = g_strdup_printf ("%slog.xml", path);
+ g_free (path);
+
+ return filename;
+}
+
+static void
+cal_backend_set_node_timet (xmlNodePtr node, const char *name, time_t t)
+{
+ char *tstring;
+
+ tstring = g_strdup_printf ("%ld", t);
+ xmlSetProp (node, name, tstring);
+}
+
+static void
+cal_backend_log_entry (CalBackend *backend, const char *uid,
+ CalBackendLogEntryType type)
+{
+ CalBackendLogEntry *entry = g_new0 (CalBackendLogEntry, 1);
+ CalObjType cot;
+
+ g_assert (CLASS (backend)->get_type_by_uid != NULL);
+ cot = (* CLASS (backend)->get_type_by_uid) (backend, uid);
+
+ /* Only log todos and events */
+ if (cot != CALOBJ_TYPE_EVENT && cot != CALOBJ_TYPE_TODO)
+ return;
+
+ entry = g_new0 (CalBackendLogEntry, 1);
+ entry->uid = g_strdup (uid);
+ entry->type = cot;
+ entry->event_type = type;
+ entry->time_stamp = time (NULL);
+
+ /* Append so they get stored in chronological order */
+ backend->entries = g_slist_append (backend->entries, entry);
+}
+
+static gboolean
+cal_backend_log_sync (CalBackend *backend)
+{
+ xmlDocPtr doc;
+ xmlNodePtr tnode;
+ gchar *filename;
+ GSList *l;
+ int ret;
+ time_t start_time = (time_t) - 1;
+
+ if (backend->entries == NULL)
+ return TRUE;
+
+ filename = cal_backend_log_name (backend);
+
+ doc = xmlParseFile (filename);
+ if (doc == NULL) {
+ /* Create the document */
+ doc = xmlNewDoc ("1.0");
+ if (doc == NULL) {
+ g_warning ("Log file could not be created\n");
+ return FALSE;
+ }
+
+
+ doc->root = xmlNewDocNode(doc, NULL, "CalendarLog", NULL);
+ }
+
+ tnode = xmlNewChild (doc->root, NULL, "timestamp", NULL);
+ for (l = backend->entries; l != NULL; l = l->next) {
+ xmlNodePtr node;
+ CalBackendLogEntry *entry;
+
+ entry = (CalBackendLogEntry *)l->data;
+ node = xmlNewChild (tnode, NULL, "status", NULL);
+
+ xmlSetProp (node, "uid", entry->uid);
+
+ switch (entry->type) {
+ case CALOBJ_TYPE_EVENT:
+ xmlSetProp (node, "type", "event");
+ break;
+ case CALOBJ_TYPE_TODO:
+ xmlSetProp (node, "type", "todo");
+ break;
+ default:
+ }
+
+ switch (entry->event_type) {
+ case (CAL_BACKEND_UPDATED):
+ xmlSetProp (node, "operation", "updated");
+ break;
+ case (CAL_BACKEND_REMOVED):
+ xmlSetProp (node, "operation", "removed");
+ break;
+ }
+
+ if (start_time == (time_t) - 1
+ || entry->time_stamp < start_time)
+ start_time = entry->time_stamp;
+
+ g_free (entry);
+ }
+ cal_backend_set_node_timet (tnode, "start", start_time);
+ cal_backend_set_node_timet (tnode, "end", time (NULL));
+
+ g_slist_free (backend->entries);
+ backend->entries = NULL;
+
+ /* Write the file */
+ xmlSetDocCompressMode (doc, 0);
+ ret = xmlSaveFile (filename, doc);
+ if (ret < 0) {
+ g_warning ("Log file could not be saved\n");
+ return FALSE;
+ }
+
+ xmlFreeDoc (doc);
+
+ g_free (filename);
+
+ return TRUE;
+}
+
+static void
+cal_backend_log_sax_start_element (void *data, const xmlChar *name,
+ const xmlChar **attrs)
+{
+ CalBackendParseState *state = (CalBackendParseState *)data;
+
+ if (!strcmp (name, "timestamp")) {
+ while (attrs && *attrs != NULL) {
+ const xmlChar **val = attrs;
+
+ val++;
+ if (!strcmp (*attrs, "start")) {
+ time_t start = (time_t)strtoul (*val, NULL, 0);
+
+ if (start >= state->since)
+ state->in_valid_timestamp = TRUE;
+ break;
+ }
+ attrs = ++val;
+ }
+ }
+
+ if (!strcmp (name, "status")) {
+ CalObjChange *coc = g_new0 (CalObjChange, 1);
+ CalObjType cot = 0;
+
+ while (attrs && *attrs != NULL) {
+ const xmlChar **val = attrs;
+
+
+ val++;
+ if (!strcmp (*attrs, "uid"))
+ coc->uid = g_strdup (*val);
+
+ if (!strcmp (*attrs, "type")) {
+ if (!strcmp (*val, "event"))
+ cot = CALOBJ_TYPE_EVENT;
+ else if (!strcmp (*val, "todo"))
+ cot = CALOBJ_TYPE_TODO;
+ }
+
+ if (!strcmp (*attrs, "operation"))
+ coc->type = atoi (*val);
+
+ attrs = ++val;
+ }
+
+ if (state->type == CALOBJ_TYPE_ANY || state->type == cot)
+ g_hash_table_insert (state->hash, coc->uid, coc);
+ }
+}
+
+static void
+cal_backend_log_sax_end_element (void *data, const xmlChar *name)
+{
+ CalBackendParseState *state = (CalBackendParseState *)data;
+
+ if (!strcmp (name, "timestamp")) {
+ state->in_valid_timestamp = FALSE;
+ }
+}
+
+static int
+cal_backend_log_sax_parse (CalBackend *backend, xmlSAXHandler *handler,
+ CalBackendParseState *state)
+{
+ int ret = 0;
+ xmlParserCtxtPtr ctxt;
+ char *filename;
+
+ filename = cal_backend_log_name (backend);
+
+ if (!g_file_exists (filename))
+ return 0;
+
+ ctxt = xmlCreateFileParserCtxt (filename);
+ if (ctxt == NULL)
+ return -1;
+
+ ctxt->sax = handler;
+ ctxt->userData = (void *)state;
+
+ xmlParseDocument (ctxt);
+
+ if (ctxt->wellFormed)
+ ret = 0;
+ else
+ ret = -1;
+
+ if (handler != NULL)
+ ctxt->sax = NULL;
+ xmlFreeParserCtxt(ctxt);
+
+ return ret;
+}
+
+static GHashTable *
+cal_backend_get_log_entries (CalBackend *backend, time_t since,
+ CalObjType type)
+{
+ xmlSAXHandler handler;
+ CalBackendParseState state;
+ GHashTable *hash;
+
+ g_return_val_if_fail (backend != NULL, NULL);
+ g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+
+ if (!cal_backend_log_sync (backend))
+ return NULL;
+
+ hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ memset(&handler, 0, sizeof(xmlSAXHandler));
+ handler.startElement = cal_backend_log_sax_start_element;
+ handler.endElement = cal_backend_log_sax_end_element;
+ state.type = type;
+ state.since = since;
+ state.hash = hash;
+
+ if (cal_backend_log_sax_parse (backend, &handler, &state) < 0)
+ return NULL;
+
+ return hash;
+}
/**
* cal_backend_update_object:
@@ -355,13 +705,20 @@ void cal_backend_update_pilot_id (CalBackend *backend, const char *uid,
gboolean
cal_backend_update_object (CalBackend *backend, const char *uid, const char *calobj)
{
+ gboolean result;
+
g_return_val_if_fail (backend != NULL, FALSE);
g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE);
g_return_val_if_fail (uid != NULL, FALSE);
g_return_val_if_fail (calobj != NULL, FALSE);
g_assert (CLASS (backend)->update_object != NULL);
- return (* CLASS (backend)->update_object) (backend, uid, calobj);
+ result = (* CLASS (backend)->update_object) (backend, uid, calobj);
+
+ if (result)
+ cal_backend_log_entry (backend, uid, CAL_BACKEND_UPDATED);
+
+ return result;
}
/**
@@ -378,12 +735,19 @@ cal_backend_update_object (CalBackend *backend, const char *uid, const char *cal
gboolean
cal_backend_remove_object (CalBackend *backend, const char *uid)
{
+ gboolean result;
+
g_return_val_if_fail (backend != NULL, FALSE);
g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE);
g_return_val_if_fail (uid != NULL, FALSE);
g_assert (CLASS (backend)->remove_object != NULL);
- return (* CLASS (backend)->remove_object) (backend, uid);
+ result = (* CLASS (backend)->remove_object) (backend, uid);
+
+ if (result)
+ cal_backend_log_entry (backend, uid, CAL_BACKEND_REMOVED);
+
+ return result;
}
/**
@@ -400,4 +764,10 @@ cal_backend_last_client_gone (CalBackend *backend)
g_return_if_fail (IS_CAL_BACKEND (backend));
gtk_signal_emit (GTK_OBJECT (backend), cal_backend_signals[LAST_CLIENT_GONE]);
+
+ cal_backend_log_sync (backend);
}
+
+
+
+
diff --git a/calendar/pcs/cal-backend.h b/calendar/pcs/cal-backend.h
index cfc4cb8a99..77bba93835 100644
--- a/calendar/pcs/cal-backend.h
+++ b/calendar/pcs/cal-backend.h
@@ -26,6 +26,7 @@
#include <libgnome/gnome-defs.h>
#include <libgnomevfs/gnome-vfs.h>
#include <cal-util/cal-util.h>
+#include <cal-util/cal-component.h>
#include "calendar/pcs/evolution-calendar.h"
#include "cal-common.h"
#include "cal.h"
@@ -49,6 +50,10 @@ typedef enum {
struct _CalBackend {
GtkObject object;
+
+ GnomeVFSURI *uri;
+ GSList *entries;
+ guint timer;
};
struct _CalBackendClass {
@@ -65,6 +70,7 @@ struct _CalBackendClass {
int (* get_n_objects) (CalBackend *backend, CalObjType type);
char *(* get_object) (CalBackend *backend, const char *uid);
+ CalObjType(* get_type_by_uid) (CalBackend *backend, const char *uid);
GList *(* get_uids) (CalBackend *backend, CalObjType type);
GList *(* get_objects_in_range) (CalBackend *backend, CalObjType type,
time_t start, time_t end);
@@ -95,6 +101,8 @@ char *cal_backend_get_object (CalBackend *backend, const char *uid);
GList *cal_backend_get_uids (CalBackend *backend, CalObjType type);
+GList *cal_backend_get_changed_uids (CalBackend *backend, CalObjType type, time_t since);
+
GList *cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type,
time_t start, time_t end);
diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c
index 64eb29b023..cb302cf9be 100644
--- a/calendar/pcs/cal.c
+++ b/calendar/pcs/cal.c
@@ -278,6 +278,63 @@ Cal_get_uids (PortableServer_Servant servant,
return seq;
}
+static Evolution_Calendar_CalObjChangeSeq *
+build_change_seq (GList *changes)
+{
+ GList *l;
+ int n, i;
+ Evolution_Calendar_CalObjChangeSeq *seq;
+
+ n = g_list_length (changes);
+
+ seq = Evolution_Calendar_CalObjChangeSeq__alloc ();
+ CORBA_sequence_set_release (seq, TRUE);
+ seq->_length = n;
+ seq->_buffer = CORBA_sequence_Evolution_Calendar_CalObjChange_allocbuf (n);
+
+ /* Fill the sequence */
+ for (i = 0, l = changes; l; i++, l = l->next) {
+ CalObjChange *c;
+ Evolution_Calendar_CalObjChange *corba_c;
+
+ c = l->data;
+ corba_c = &seq->_buffer[i];
+
+ corba_c->uid = CORBA_string_dup (c->uid);
+ corba_c->type = c->type;
+ }
+
+ return seq;
+}
+
+/* Cal::get_changed_uids method */
+static Evolution_Calendar_CalObjChangeSeq *
+Cal_get_changed_uids (PortableServer_Servant servant,
+ Evolution_Calendar_CalObjType type,
+ Evolution_Calendar_Time_t since,
+ CORBA_Environment *ev)
+{
+ Cal *cal;
+ CalPrivate *priv;
+ GList *changes;
+ Evolution_Calendar_CalObjChangeSeq *seq;
+ int t;
+ time_t s;
+
+ cal = CAL (bonobo_object_from_servant (servant));
+ priv = cal->priv;
+
+ t = uncorba_obj_type (type);
+ s = (time_t) since;
+
+ changes = cal_backend_get_changed_uids (priv->backend, t, s);
+ seq = build_change_seq (changes);
+
+ cal_obj_change_list_free (changes);
+
+ return seq;
+}
+
/* Cal::get_objects_in_range method */
static Evolution_Calendar_CalObjUIDSeq *
Cal_get_objects_in_range (PortableServer_Servant servant,
@@ -558,6 +615,7 @@ cal_get_epv (void)
epv->get_n_objects = Cal_get_n_objects;
epv->get_object = Cal_get_object;
epv->get_uids = Cal_get_uids;
+ epv->get_changed_uids = Cal_get_changed_uids;
epv->get_objects_in_range = Cal_get_objects_in_range;
epv->get_alarms_in_range = Cal_get_alarms_in_range;
epv->get_alarms_for_object = Cal_get_alarms_for_object;