aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog17
-rw-r--r--calendar/GnomeCal.idl20
-rw-r--r--calendar/TODO3
-rw-r--r--calendar/cal-util/calobj.c17
-rw-r--r--calendar/calendar-pilot-sync.c304
-rw-r--r--calendar/calendar.c32
-rw-r--r--calendar/calendar.h2
-rw-r--r--calendar/calobj.c17
-rw-r--r--calendar/corba-cal-factory.c4
-rw-r--r--calendar/corba-cal.c59
-rw-r--r--calendar/eventedit.c4
-rw-r--r--calendar/gui/GnomeCal.idl20
-rw-r--r--calendar/gui/calendar-pilot-sync.c304
-rw-r--r--calendar/gui/calendar.c32
-rw-r--r--calendar/gui/calendar.h2
-rw-r--r--calendar/gui/corba-cal-factory.c4
-rw-r--r--calendar/gui/corba-cal.c59
-rw-r--r--calendar/gui/eventedit.c4
-rw-r--r--calendar/pcs/calobj.c17
19 files changed, 833 insertions, 88 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 8d7fed8098..c6e61d4ee0 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,10 +1,23 @@
1999-07-28 Miguel de Icaza <miguel@gnu.org>
- * calendar-pilot-sync.c: New file. Implements PalmPilot
- syncronization with the Gnome Calendar.
+ * calobj.c (ical_gen_uid): Use the hostname, not the domain name.
+ (ical_gen_uid): Add a serial number. Isodates can be small.
+
+ * corba-cal.c (cal_repo_update_pilot_id): New method to update the
+ pilot status.
+ (cal_repo_get_updated_objects): New method. Returns a list of
+ modified and not-sycned objects
+
+ * calendar-pilot-sync.c (sync_cal_to_pilot): New function to sync
+ from the GnomeCalendar to the pilot.
+ (sync_object_to_pilot): Sync a single event to the pilot.
+ (try_alarm): Alarm syncing code.
1999-07-27 Miguel de Icaza <miguel@gnu.org>
+ * calendar-pilot-sync.c: New file. Implements PalmPilot
+ syncronization with the Gnome Calendar.
+
* calobj.c (ical_object_new_from_string): New function. Creates
an iCalObject from a vCalendar string that is supposed to contain
only one vEvent.
diff --git a/calendar/GnomeCal.idl b/calendar/GnomeCal.idl
index bfeb502518..5c158284a3 100644
--- a/calendar/GnomeCal.idl
+++ b/calendar/GnomeCal.idl
@@ -11,7 +11,7 @@ module GNOME {
* @uid: Unique Identifier for the object
*
* Returns a vCalendar object for the object
- * that matches the UID @uid
+ * that matches the UID @uid.
*/
string get_object (in string uid)
raises (NotFound);
@@ -44,6 +44,23 @@ module GNOME {
void update_object (in string uid, in string object);
/*
+ * update_pilot_id:
+ * @uid: Unique identifier for the event we want to update
+ * @pilot_id: new ID assigned by the pilot
+ * @pilot_status: Status to flag the event with
+ */
+ void update_pilot_id (in string uid, in long pilot_id, in long pilot_status)
+ raises (NotFound);
+
+ /*
+ * get_updated_objects:
+ *
+ * Returns a vCalendar with all the objects that have been
+ * modified since the last Pilot Sync
+ */
+ string get_updated_objects ();
+
+ /*
* done:
*
* Informs the calendar that we are done using it,
@@ -53,3 +70,4 @@ module GNOME {
};
};
};
+
diff --git a/calendar/TODO b/calendar/TODO
index bb964e908d..822ec2eb35 100644
--- a/calendar/TODO
+++ b/calendar/TODO
@@ -1,8 +1,11 @@
Pilot:
* Better support for untimed events (we have none now).
+
* Add syncing from Desktop to Pilot.
+* Hash objects based on their UIDs.
+
BUGS:
- Recurrence end date is wrong. An event that repeats daily will not
diff --git a/calendar/cal-util/calobj.c b/calendar/cal-util/calobj.c
index 08c8d8c63a..f1bec05c2b 100644
--- a/calendar/cal-util/calobj.c
+++ b/calendar/cal-util/calobj.c
@@ -18,23 +18,28 @@
static char *
ical_gen_uid (void)
{
- static char *domain;
+ static char *hostname;
time_t t = time (NULL);
+ static int serial;
- if (!domain){
+ if (!hostname){
char buffer [128];
- getdomainname (buffer, sizeof (buffer)-1);
- domain = g_strdup (domain);
+ gethostname (buffer, sizeof (buffer)-1);
+ if (hostname)
+ hostname = g_strdup (hostname);
+ else
+ hostname = g_strdup ("localhost");
}
return g_strdup_printf (
- "%s-%d-%d-%d@%s",
+ "%s-%d-%d-%d-%d@%s",
isodate_from_time_t (t),
getpid (),
getgid (),
getppid (),
- domain);
+ serial++,
+ hostname);
}
iCalObject *
diff --git a/calendar/calendar-pilot-sync.c b/calendar/calendar-pilot-sync.c
index 6ed92d540a..bbacd312eb 100644
--- a/calendar/calendar-pilot-sync.c
+++ b/calendar/calendar-pilot-sync.c
@@ -31,11 +31,28 @@ char *pilot_port = "/dev/pilot";
CORBA_Environment ev;
+/* Our pi-socket address where we connect to */
struct pi_sockaddr addr;
+/* The Pilot DB identifier for DateBook */
+int db;
+
+/* True if you want to dump the flags bits from the records */
+int debug_attrs = 0;
+
+int only_desktop_to_pilot = 0;
+
+int only_pilot_to_desktop = 0;
+
const struct poptOption calendar_sync_options [] = {
{ "pilot", 0, POPT_ARG_STRING, &pilot_port, 0,
N_("Specifies the port on which the Pilot is"), N_("PORT") },
+ { "debug-attrs", 0, POPT_ARG_INT, &debug_attrs, 0,
+ N_("If you want to debug the attributes on records"), NULL },
+ { "only-desktop", 0, POPT_ARG_INT, &only_desktop_to_pilot, 0,
+ N_("Only syncs from desktop to pilot"), NULL },
+ { "only-pilot", 0, POPT_ARG_INT, &only_pilot_to_desktop, 0,
+ N_("Only syncs from pilot to desktop"), NULL },
{ NULL, '\0', 0, NULL, 0 }
};
@@ -68,7 +85,6 @@ static GNOME_Calendar_Repository
locate_calendar_server (void)
{
GNOME_Calendar_Repository repo;
- GNOME_stringlist list;
repo = goad_server_activate_with_id (
NULL, "IDL:GNOME:Calendar:Repository:1.0",
@@ -112,6 +128,7 @@ update_record (GNOME_Calendar_Repository repo, int id, struct Appointment *a, in
g_get_user_name (),
a->description ? a->description : "");
+ printf ("requesting %d [%s]\n", id, a->description);
vcal_string = GNOME_Calendar_Repository_get_object_by_pilot_id (repo, id, &ev);
if (ev._major == CORBA_USER_EXCEPTION){
@@ -124,12 +141,14 @@ update_record (GNOME_Calendar_Repository repo, int id, struct Appointment *a, in
obj->related = NULL;
obj->pilot_id = id;
obj->pilot_status = ICAL_PILOT_SYNC_NONE;
- printf (_("Object did not exist, creating a new one"));
- } else
+ printf (_("\tObject did not exist, creating a new one\n"));
+ } else {
+ printf ("\tFound\n");
obj = ical_object_new_from_string (vcal_string);
+ }
if (obj->pilot_status == ICAL_PILOT_SYNC_MOD){
- printf (_("Object has been modified on desktop and on the pilot, desktop takes precedence"));
+ printf (_("\tObject has been modified on desktop and on the pilot, desktop takes precedence\n"));
ical_object_destroy (obj);
return;
}
@@ -261,12 +280,220 @@ update_record (GNOME_Calendar_Repository repo, int id, struct Appointment *a, in
ical_object_destroy (obj);
}
+/*
+ * Sets the alarm for Appointment based on @alarm
+ */
+static int
+try_alarm (CalendarAlarm *alarm, struct Appointment *a)
+{
+ if (!alarm->enabled)
+ return 0;
+
+ a->advance = alarm->count;
+ switch (alarm->type){
+ case ALARM_DAYS:
+ a->advanceUnits = advDays;
+ break;
+
+ case ALARM_HOURS:
+ a->advanceUnits = advHours;
+ break;
+
+ case ALARM_MINUTES:
+ a->advanceUnits = advMinutes;
+ break;
+
+ default:
+ return 0;
+ }
+ a->alarm = 1;
+ return 1;
+}
+
+static void
+sync_object_to_pilot (GNOME_Calendar_Repository repo, iCalObject *obj, int pilot_fd)
+{
+ char buffer [65536];
+ struct Appointment *a;
+ int wd, i, idx, attr, cat, rec_len;
+ recordid_t new_id;
+ GList *l;
+
+ a = g_new0 (struct Appointment, 1);
+
+ attr = 0;
+ cat = 0;
+ idx = 0;
+
+ if (obj->pilot_id){
+ rec_len = dlp_ReadRecordById (pilot_fd, db, obj->pilot_id,
+ buffer, &idx, &rec_len, &attr, &cat);
+
+ if (rec_len > 0)
+ unpack_Appointment (a, buffer, rec_len);
+ }
+ /* a contains the appointment either cleared or with the data from the Pilot */
+ a->begin = *localtime (&obj->dtstart);
+ a->end = *localtime (&obj->dtend);
+
+ /* FIXME: add support for timeless */
+ a->event = 0;
+
+ /* Alarms, try the various ones. Probably we should only do Audio?
+ * Otherwise going gnomecal->pilot->gnomecal would get the gnomecal
+ * with *possibly* an alarm that was not originally defined.
+ */
+ a->alarm = 0;
+ if (try_alarm (&obj->aalarm, a) == 0)
+ if (try_alarm (&obj->dalarm, a) == 0)
+ try_alarm (&obj->palarm, a);
+
+ /* Recurrence */
+ if (obj->recur){
+ a->repeatFrequency = obj->recur->interval;
+
+ switch (obj->recur->type){
+ case RECUR_MONTHLY_BY_POS:
+ a->repeatType = repeatMonthlyByDay;
+ a->repeatFrequency = obj->recur->u.month_pos;
+ a->repeatDay = obj->recur->weekday * 7;
+ break;
+
+ case RECUR_MONTHLY_BY_DAY:
+ a->repeatType = repeatMonthlyByDate;
+ a->repeatFrequency = obj->recur->u.month_day;
+ break;
+
+ case RECUR_YEARLY_BY_DAY:
+ a->repeatType = repeatYearly;
+ break;
+
+ case RECUR_WEEKLY:
+ for (wd = 0; wd < 7; wd++)
+ if (obj->recur->weekday & (1 << wd))
+ a->repeatDays [wd] = 1;
+ a->repeatType = repeatWeekly;
+ break;
+ case RECUR_DAILY:
+
+ default:
+ a->repeatType = repeatNone;
+ break;
+ }
+ a->repeatEnd = *localtime (&obj->recur->_enddate);
+ }
+
+ /*
+ * Pilot uses a repeat-daily for a multi-day event, adjust for that case
+ */
+ if ((a->end.tm_mday != a->begin.tm_mday) ||
+ (a->end.tm_mon != a->begin.tm_mon) ||
+ (a->end.tm_year != a->begin.tm_year)){
+
+ a->repeatEnd = a->end;
+ a->repeatForever = 0;
+ a->repeatFrequency = 0;
+ a->repeatType = repeatDaily;
+ a->end.tm_mday = a->begin.tm_mday;
+ a->end.tm_mon = a->begin.tm_mon;
+ a->end.tm_year = a->begin.tm_year;
+ }
+
+ /*
+ * Exceptions
+ */
+ a->exceptions = g_list_length (obj->exdate);
+ a->exception = (struct tm *) malloc (sizeof (struct tm) * a->exceptions);
+ for (i = 0, l = obj->exdate; l; l = l->next, i++){
+ time_t *exdate = l->data;
+
+ a->exception [i] = *localtime (exdate);
+ }
+
+ /*
+ * Description and note.
+ *
+ * We use strdup to be correct. free_Appointment assumes we used
+ * malloc.
+ */
+ if (obj->comment)
+ a->note = strdup (obj->comment);
+ else
+ a->note = 0;
+
+ if (obj->summary)
+ a->description = strdup (obj->summary);
+ else
+ a->description = strdup (_("No description"));
+
+ if (strcmp (obj->class, "PUBLIC") != 0)
+ attr |= dlpRecAttrSecret;
+ else
+ attr &= ~dlpRecAttrSecret;
+
+ /*
+ * Mark as archived. FIXME: is this the case?
+ */
+ attr |= dlpRecAttrArchived;
+
+ /*
+ * Send the appointment to the pilot
+ */
+ rec_len = pack_Appointment (a, buffer, sizeof (buffer));
+ attr &= ~dlpRecAttrDirty;
+
+ printf ("Status=%d\n",
+ dlp_WriteRecord (
+ pilot_fd, db, attr,
+ obj->pilot_id, cat, buffer, rec_len, &new_id));
+ GNOME_Calendar_Repository_update_pilot_id (repo, obj->uid, new_id, ICAL_PILOT_SYNC_NONE, &ev);
+
+ free_Appointment (a);
+ g_free (a);
+}
+
+static void
+sync_cal_to_pilot (GNOME_Calendar_Repository repo, Calendar *cal, int pilot_fd)
+{
+ GList *l;
+
+ for (l = cal->events; l; l = l->next){
+ iCalObject *obj = l->data;
+
+ if (obj->pilot_status != ICAL_PILOT_SYNC_MOD){
+ g_warning ("Strange, we were supposed to get only a dirty object");
+ continue;
+ }
+
+ sync_object_to_pilot (repo, obj, pilot_fd);
+ }
+}
+
+static void
+dump_attr (int flags)
+{
+ if (flags & dlpRecAttrDeleted)
+ fprintf(stderr, " Deleted");
+ if (flags & dlpRecAttrDirty)
+ fprintf(stderr, " Dirty");
+ if (flags & dlpRecAttrBusy)
+ fprintf(stderr, " Busy");
+ if (flags & dlpRecAttrSecret)
+ fprintf(stderr, " Secret");
+ if (flags & dlpRecAttrArchived)
+ fprintf(stderr, " Archive");
+ fprintf (stderr, "\n");
+}
+
static void
sync_pilot (GNOME_Calendar_Repository repo, int pilot_fd)
{
struct PilotUser user_info;
- int db,record;
+ int record;
unsigned char buffer [65536];
+ Calendar *dirty_cal;
+ char *vcalendar_string;
+ char *error;
printf (_("Syncing with the pilot..."));
dlp_ReadUserInfo (pilot_fd, &user_info);
@@ -285,36 +512,59 @@ sync_pilot (GNOME_Calendar_Repository repo, int pilot_fd)
* 1. Pull all the records from the Pilot, and make any updates
* required on the desktop side
*/
- for (record = 0;; record++){
- struct Appointment a;
- int rec_len, attr, size;
- recordid_t id;
-
- rec_len = dlp_ReadRecordByIndex (pilot_fd, db, record, buffer, &id, &size, &attr, 0);
-
- if (rec_len < 0)
- break;
+ if (!only_desktop_to_pilot){
+ for (record = 0;; record++){
+ struct Appointment a;
+ int rec_len, attr, size;
+ recordid_t id;
+
+ rec_len = dlp_ReadRecordByIndex (
+ pilot_fd, db,
+ record, buffer, &id, &size, &attr, 0);
- printf ("processing record %d\n", record);
- unpack_Appointment (&a, buffer, rec_len);
-
- /* If the object was deleted, remove it from the database */
- if (attr & dlpRecAttrDeleted){
- delete_record (repo, id);
- continue;
- }
+ if (rec_len < 0)
+ break;
+
+ printf ("processing record %d\n", record);
+ unpack_Appointment (&a, buffer, rec_len);
+
+ if (debug_attrs)
+ dump_attr (attr);
+
+ /* If the object was deleted, remove it from the database */
+ if (attr & dlpRecAttrDeleted){
+ printf ("Deleteing\n");
+ delete_record (repo, id);
+ free_Appointment (&a);
+ continue;
+ }
- if (attr & dlpRecAttrDirty){
- printf ("updating record\n");
- update_record (repo, id, &a, attr);
+ if (attr & dlpRecAttrArchived)
+ continue;
+
+ if (attr & dlpRecAttrDirty){
+ printf ("updating record\n");
+ update_record (repo, id, &a, attr);
+ }
+
+ free_Appointment (&a);
}
-
- free_Appointment (&a);
}
+
/*
* 2. Pull all the records from the Calendar, and move any new items
* to the pilot
*/
+ if (!only_pilot_to_desktop){
+ vcalendar_string = GNOME_Calendar_Repository_get_updated_objects (repo, &ev);
+ dirty_cal = calendar_new ("Temporal");
+ error = calendar_load_from_memory (dirty_cal, vcalendar_string);
+ if (!error)
+ sync_cal_to_pilot (repo, dirty_cal, pilot_fd);
+ calendar_destroy (dirty_cal);
+ }
+
+
dlp_CloseDB (pilot_fd, db);
dlp_AddSyncLogEntry (pilot_fd, _("Synced DateBook from Pilot to GnomeCal"));
pi_close (pilot_fd);
diff --git a/calendar/calendar.c b/calendar/calendar.c
index b67f875fdc..30e4e0168c 100644
--- a/calendar/calendar.c
+++ b/calendar/calendar.c
@@ -72,7 +72,7 @@ add_object_alarms (iCalObject *obj, time_t start, time_t end, void *closure)
#define max(a,b) ((a > b) ? a : b)
-void
+static void
ical_object_try_alarms (iCalObject *obj)
{
int ao, po, od, mo;
@@ -169,7 +169,7 @@ calendar_destroy (Calendar *cal)
g_free (cal);
}
-char *
+static char *
ice (time_t t)
{
static char buffer [100];
@@ -323,6 +323,34 @@ calendar_load (Calendar *cal, char *fname)
return NULL;
}
+/*
+ * calendar_load_from_memory:
+ * @cal: calendar on which we load the information
+ * @buffer: A buffer that contains a vCalendar file
+ *
+ * Loads the information from the vCalendar information in @buffer
+ * into the Calendar
+ */
+char *
+calendar_load_from_memory (Calendar *cal, const char *buffer)
+{
+ VObject *vcal;
+
+ g_return_val_if_fail (buffer != NULL, NULL);
+
+ cal->filename = g_strdup ("memory-based-calendar");
+ vcal = Parse_MIME (buffer, strlen (buffer));
+ if (!vcal)
+ return "Could not load the calendar";
+
+ cal->file_time = time (NULL);
+ calendar_load_from_vobject (cal, vcal);
+ cleanVObject (vcal);
+ cleanStrTbl ();
+
+ return NULL;
+}
+
static VObject *
vcalendar_create_from_calendar (Calendar *cal)
{
diff --git a/calendar/calendar.h b/calendar/calendar.h
index 2ea2753057..aa25fba67c 100644
--- a/calendar/calendar.h
+++ b/calendar/calendar.h
@@ -44,6 +44,8 @@ char *calendar_get_as_vcal_string (Calendar *cal);
char *calendar_string_from_object (iCalObject *object);
char *calendar_load (Calendar *cal, char *fname);
+char *calendar_load_from_memory (Calendar *cal, const char *buffer);
+void calendar_load_from_vobject (Calendar *cal, VObject *vcal);
void calendar_save (Calendar *cal, char *fname);
void calendar_add_object (Calendar *cal, iCalObject *obj);
void calendar_remove_object (Calendar *cal, iCalObject *obj);
diff --git a/calendar/calobj.c b/calendar/calobj.c
index 08c8d8c63a..f1bec05c2b 100644
--- a/calendar/calobj.c
+++ b/calendar/calobj.c
@@ -18,23 +18,28 @@
static char *
ical_gen_uid (void)
{
- static char *domain;
+ static char *hostname;
time_t t = time (NULL);
+ static int serial;
- if (!domain){
+ if (!hostname){
char buffer [128];
- getdomainname (buffer, sizeof (buffer)-1);
- domain = g_strdup (domain);
+ gethostname (buffer, sizeof (buffer)-1);
+ if (hostname)
+ hostname = g_strdup (hostname);
+ else
+ hostname = g_strdup ("localhost");
}
return g_strdup_printf (
- "%s-%d-%d-%d@%s",
+ "%s-%d-%d-%d-%d@%s",
isodate_from_time_t (t),
getpid (),
getgid (),
getppid (),
- domain);
+ serial++,
+ hostname);
}
iCalObject *
diff --git a/calendar/corba-cal-factory.c b/calendar/corba-cal-factory.c
index 49a2c5ac76..c10929376b 100644
--- a/calendar/corba-cal-factory.c
+++ b/calendar/corba-cal-factory.c
@@ -35,7 +35,7 @@ static GNOME_GenericFactory calendar_factory;
static CORBA_boolean
calendar_supports (PortableServer_Servant servant,
- const CORBA_char * obj_goad_id,
+ CORBA_char * obj_goad_id,
CORBA_Environment * ev)
{
if (strcmp (obj_goad_id, "IDL:GNOME:Calendar:Repository:1.0") == 0)
@@ -46,7 +46,7 @@ calendar_supports (PortableServer_Servant servant,
static CORBA_Object
calendar_create_object (PortableServer_Servant servant,
- const CORBA_char *goad_id,
+ CORBA_char *goad_id,
const GNOME_stringlist *params,
CORBA_Environment *ev)
{
diff --git a/calendar/corba-cal.c b/calendar/corba-cal.c
index d78685bf90..8f92057d42 100644
--- a/calendar/corba-cal.c
+++ b/calendar/corba-cal.c
@@ -81,6 +81,7 @@ cal_repo_get_object_by_pilot_id (PortableServer_Servant servant,
CORBA_char *ret;
obj = calendar_object_find_by_pilot (gcal->cal, pilot_id);
+ printf ("Looking for [%d]\n", pilot_id);
if (obj == NULL){
CORBA_exception_set (ev,
CORBA_USER_EXCEPTION,
@@ -148,6 +149,7 @@ cal_repo_update_object (PortableServer_Servant servant,
obj = calendar_object_find_event (gcal->cal, uid);
if (obj != NULL){
+ printf ("ELIMINATING: %s -> %s\n", obj->uid, new_object->uid);
calendar_remove_object (gcal->cal, obj);
}
@@ -155,6 +157,60 @@ cal_repo_update_object (PortableServer_Servant servant,
}
static void
+cal_repo_update_pilot_id (PortableServer_Servant servant,
+ CORBA_char *uid,
+ CORBA_long pilot_id,
+ CORBA_long pilot_status,
+ CORBA_Environment *ev)
+{
+ GnomeCalendar *gcal = gnomecal_from_servant (servant);
+ iCalObject *obj;
+
+ obj = calendar_object_find_event (gcal->cal, uid);
+ if (obj == NULL){
+ CORBA_exception_set (
+ ev,
+ CORBA_USER_EXCEPTION,
+ ex_GNOME_Calendar_Repository_NotFound,
+ "");
+ return;
+ }
+
+ obj->pilot_id = pilot_id;
+ obj->pilot_status = pilot_status;
+}
+
+static CORBA_char *
+cal_repo_get_updated_objects (PortableServer_Servant servant,
+ CORBA_Environment *ev)
+{
+ GnomeCalendar *gcal = gnomecal_from_servant (servant);
+ Calendar *dirty_cal;
+ GList *l;
+ CORBA_char *res;
+ char *str;
+
+ dirty_cal = calendar_new ("Temporal");
+
+ for (l = gcal->cal->events; l; l = l->next){
+ iCalObject *obj = l->data;
+
+ if (obj->pilot_status != ICAL_PILOT_SYNC_MOD)
+ continue;
+
+ obj = ical_object_duplicate (l->data);
+
+ calendar_add_object (dirty_cal, obj);
+ }
+ str = calendar_get_as_vcal_string (dirty_cal);
+ res = CORBA_string_dup (str);
+ g_free (str);
+ calendar_destroy (dirty_cal);
+
+ return res;
+}
+
+static void
cal_repo_done (PortableServer_Servant servant,
CORBA_Environment *ev)
{
@@ -171,6 +227,9 @@ init_calendar_repo_class (void)
calendar_repository_epv.get_id_from_pilot_id = cal_repo_get_id_from_pilot_id;
calendar_repository_epv.delete_object = cal_repo_delete_object;
calendar_repository_epv.update_object = cal_repo_update_object;
+ calendar_repository_epv.get_updated_objects = cal_repo_get_updated_objects;
+ calendar_repository_epv.update_pilot_id = cal_repo_update_pilot_id;
+
calendar_repository_epv.done = cal_repo_done;
calendar_repository_vepv.GNOME_Calendar_Repository_epv =
diff --git a/calendar/eventedit.c b/calendar/eventedit.c
index a73775b375..8a36b94638 100644
--- a/calendar/eventedit.c
+++ b/calendar/eventedit.c
@@ -59,7 +59,7 @@ event_editor_class_init (EventEditorClass *class)
object_class->destroy = event_editor_destroy;
}
-GtkWidget *
+static GtkWidget *
adjust (GtkWidget *w, gfloat x, gfloat y, gfloat xs, gfloat ys)
{
GtkWidget *a = gtk_alignment_new (x, y, xs, ys);
@@ -432,7 +432,7 @@ ee_classification_widgets (EventEditor *ee)
* Retrieves the information from the CalendarAlarm widgets and stores them
* on the CalendarAlarm generic values
*/
-void
+static void
ee_store_alarm (CalendarAlarm *alarm, enum AlarmType type)
{
GtkWidget *item;
diff --git a/calendar/gui/GnomeCal.idl b/calendar/gui/GnomeCal.idl
index bfeb502518..5c158284a3 100644
--- a/calendar/gui/GnomeCal.idl
+++ b/calendar/gui/GnomeCal.idl
@@ -11,7 +11,7 @@ module GNOME {
* @uid: Unique Identifier for the object
*
* Returns a vCalendar object for the object
- * that matches the UID @uid
+ * that matches the UID @uid.
*/
string get_object (in string uid)
raises (NotFound);
@@ -44,6 +44,23 @@ module GNOME {
void update_object (in string uid, in string object);
/*
+ * update_pilot_id:
+ * @uid: Unique identifier for the event we want to update
+ * @pilot_id: new ID assigned by the pilot
+ * @pilot_status: Status to flag the event with
+ */
+ void update_pilot_id (in string uid, in long pilot_id, in long pilot_status)
+ raises (NotFound);
+
+ /*
+ * get_updated_objects:
+ *
+ * Returns a vCalendar with all the objects that have been
+ * modified since the last Pilot Sync
+ */
+ string get_updated_objects ();
+
+ /*
* done:
*
* Informs the calendar that we are done using it,
@@ -53,3 +70,4 @@ module GNOME {
};
};
};
+
diff --git a/calendar/gui/calendar-pilot-sync.c b/calendar/gui/calendar-pilot-sync.c
index 6ed92d540a..bbacd312eb 100644
--- a/calendar/gui/calendar-pilot-sync.c
+++ b/calendar/gui/calendar-pilot-sync.c
@@ -31,11 +31,28 @@ char *pilot_port = "/dev/pilot";
CORBA_Environment ev;
+/* Our pi-socket address where we connect to */
struct pi_sockaddr addr;
+/* The Pilot DB identifier for DateBook */
+int db;
+
+/* True if you want to dump the flags bits from the records */
+int debug_attrs = 0;
+
+int only_desktop_to_pilot = 0;
+
+int only_pilot_to_desktop = 0;
+
const struct poptOption calendar_sync_options [] = {
{ "pilot", 0, POPT_ARG_STRING, &pilot_port, 0,
N_("Specifies the port on which the Pilot is"), N_("PORT") },
+ { "debug-attrs", 0, POPT_ARG_INT, &debug_attrs, 0,
+ N_("If you want to debug the attributes on records"), NULL },
+ { "only-desktop", 0, POPT_ARG_INT, &only_desktop_to_pilot, 0,
+ N_("Only syncs from desktop to pilot"), NULL },
+ { "only-pilot", 0, POPT_ARG_INT, &only_pilot_to_desktop, 0,
+ N_("Only syncs from pilot to desktop"), NULL },
{ NULL, '\0', 0, NULL, 0 }
};
@@ -68,7 +85,6 @@ static GNOME_Calendar_Repository
locate_calendar_server (void)
{
GNOME_Calendar_Repository repo;
- GNOME_stringlist list;
repo = goad_server_activate_with_id (
NULL, "IDL:GNOME:Calendar:Repository:1.0",
@@ -112,6 +128,7 @@ update_record (GNOME_Calendar_Repository repo, int id, struct Appointment *a, in
g_get_user_name (),
a->description ? a->description : "");
+ printf ("requesting %d [%s]\n", id, a->description);
vcal_string = GNOME_Calendar_Repository_get_object_by_pilot_id (repo, id, &ev);
if (ev._major == CORBA_USER_EXCEPTION){
@@ -124,12 +141,14 @@ update_record (GNOME_Calendar_Repository repo, int id, struct Appointment *a, in
obj->related = NULL;
obj->pilot_id = id;
obj->pilot_status = ICAL_PILOT_SYNC_NONE;
- printf (_("Object did not exist, creating a new one"));
- } else
+ printf (_("\tObject did not exist, creating a new one\n"));
+ } else {
+ printf ("\tFound\n");
obj = ical_object_new_from_string (vcal_string);
+ }
if (obj->pilot_status == ICAL_PILOT_SYNC_MOD){
- printf (_("Object has been modified on desktop and on the pilot, desktop takes precedence"));
+ printf (_("\tObject has been modified on desktop and on the pilot, desktop takes precedence\n"));
ical_object_destroy (obj);
return;
}
@@ -261,12 +280,220 @@ update_record (GNOME_Calendar_Repository repo, int id, struct Appointment *a, in
ical_object_destroy (obj);
}
+/*
+ * Sets the alarm for Appointment based on @alarm
+ */
+static int
+try_alarm (CalendarAlarm *alarm, struct Appointment *a)
+{
+ if (!alarm->enabled)
+ return 0;
+
+ a->advance = alarm->count;
+ switch (alarm->type){
+ case ALARM_DAYS:
+ a->advanceUnits = advDays;
+ break;
+
+ case ALARM_HOURS:
+ a->advanceUnits = advHours;
+ break;
+
+ case ALARM_MINUTES:
+ a->advanceUnits = advMinutes;
+ break;
+
+ default:
+ return 0;
+ }
+ a->alarm = 1;
+ return 1;
+}
+
+static void
+sync_object_to_pilot (GNOME_Calendar_Repository repo, iCalObject *obj, int pilot_fd)
+{
+ char buffer [65536];
+ struct Appointment *a;
+ int wd, i, idx, attr, cat, rec_len;
+ recordid_t new_id;
+ GList *l;
+
+ a = g_new0 (struct Appointment, 1);
+
+ attr = 0;
+ cat = 0;
+ idx = 0;
+
+ if (obj->pilot_id){
+ rec_len = dlp_ReadRecordById (pilot_fd, db, obj->pilot_id,
+ buffer, &idx, &rec_len, &attr, &cat);
+
+ if (rec_len > 0)
+ unpack_Appointment (a, buffer, rec_len);
+ }
+ /* a contains the appointment either cleared or with the data from the Pilot */
+ a->begin = *localtime (&obj->dtstart);
+ a->end = *localtime (&obj->dtend);
+
+ /* FIXME: add support for timeless */
+ a->event = 0;
+
+ /* Alarms, try the various ones. Probably we should only do Audio?
+ * Otherwise going gnomecal->pilot->gnomecal would get the gnomecal
+ * with *possibly* an alarm that was not originally defined.
+ */
+ a->alarm = 0;
+ if (try_alarm (&obj->aalarm, a) == 0)
+ if (try_alarm (&obj->dalarm, a) == 0)
+ try_alarm (&obj->palarm, a);
+
+ /* Recurrence */
+ if (obj->recur){
+ a->repeatFrequency = obj->recur->interval;
+
+ switch (obj->recur->type){
+ case RECUR_MONTHLY_BY_POS:
+ a->repeatType = repeatMonthlyByDay;
+ a->repeatFrequency = obj->recur->u.month_pos;
+ a->repeatDay = obj->recur->weekday * 7;
+ break;
+
+ case RECUR_MONTHLY_BY_DAY:
+ a->repeatType = repeatMonthlyByDate;
+ a->repeatFrequency = obj->recur->u.month_day;
+ break;
+
+ case RECUR_YEARLY_BY_DAY:
+ a->repeatType = repeatYearly;
+ break;
+
+ case RECUR_WEEKLY:
+ for (wd = 0; wd < 7; wd++)
+ if (obj->recur->weekday & (1 << wd))
+ a->repeatDays [wd] = 1;
+ a->repeatType = repeatWeekly;
+ break;
+ case RECUR_DAILY:
+
+ default:
+ a->repeatType = repeatNone;
+ break;
+ }
+ a->repeatEnd = *localtime (&obj->recur->_enddate);
+ }
+
+ /*
+ * Pilot uses a repeat-daily for a multi-day event, adjust for that case
+ */
+ if ((a->end.tm_mday != a->begin.tm_mday) ||
+ (a->end.tm_mon != a->begin.tm_mon) ||
+ (a->end.tm_year != a->begin.tm_year)){
+
+ a->repeatEnd = a->end;
+ a->repeatForever = 0;
+ a->repeatFrequency = 0;
+ a->repeatType = repeatDaily;
+ a->end.tm_mday = a->begin.tm_mday;
+ a->end.tm_mon = a->begin.tm_mon;
+ a->end.tm_year = a->begin.tm_year;
+ }
+
+ /*
+ * Exceptions
+ */
+ a->exceptions = g_list_length (obj->exdate);
+ a->exception = (struct tm *) malloc (sizeof (struct tm) * a->exceptions);
+ for (i = 0, l = obj->exdate; l; l = l->next, i++){
+ time_t *exdate = l->data;
+
+ a->exception [i] = *localtime (exdate);
+ }
+
+ /*
+ * Description and note.
+ *
+ * We use strdup to be correct. free_Appointment assumes we used
+ * malloc.
+ */
+ if (obj->comment)
+ a->note = strdup (obj->comment);
+ else
+ a->note = 0;
+
+ if (obj->summary)
+ a->description = strdup (obj->summary);
+ else
+ a->description = strdup (_("No description"));
+
+ if (strcmp (obj->class, "PUBLIC") != 0)
+ attr |= dlpRecAttrSecret;
+ else
+ attr &= ~dlpRecAttrSecret;
+
+ /*
+ * Mark as archived. FIXME: is this the case?
+ */
+ attr |= dlpRecAttrArchived;
+
+ /*
+ * Send the appointment to the pilot
+ */
+ rec_len = pack_Appointment (a, buffer, sizeof (buffer));
+ attr &= ~dlpRecAttrDirty;
+
+ printf ("Status=%d\n",
+ dlp_WriteRecord (
+ pilot_fd, db, attr,
+ obj->pilot_id, cat, buffer, rec_len, &new_id));
+ GNOME_Calendar_Repository_update_pilot_id (repo, obj->uid, new_id, ICAL_PILOT_SYNC_NONE, &ev);
+
+ free_Appointment (a);
+ g_free (a);
+}
+
+static void
+sync_cal_to_pilot (GNOME_Calendar_Repository repo, Calendar *cal, int pilot_fd)
+{
+ GList *l;
+
+ for (l = cal->events; l; l = l->next){
+ iCalObject *obj = l->data;
+
+ if (obj->pilot_status != ICAL_PILOT_SYNC_MOD){
+ g_warning ("Strange, we were supposed to get only a dirty object");
+ continue;
+ }
+
+ sync_object_to_pilot (repo, obj, pilot_fd);
+ }
+}
+
+static void
+dump_attr (int flags)
+{
+ if (flags & dlpRecAttrDeleted)
+ fprintf(stderr, " Deleted");
+ if (flags & dlpRecAttrDirty)
+ fprintf(stderr, " Dirty");
+ if (flags & dlpRecAttrBusy)
+ fprintf(stderr, " Busy");
+ if (flags & dlpRecAttrSecret)
+ fprintf(stderr, " Secret");
+ if (flags & dlpRecAttrArchived)
+ fprintf(stderr, " Archive");
+ fprintf (stderr, "\n");
+}
+
static void
sync_pilot (GNOME_Calendar_Repository repo, int pilot_fd)
{
struct PilotUser user_info;
- int db,record;
+ int record;
unsigned char buffer [65536];
+ Calendar *dirty_cal;
+ char *vcalendar_string;
+ char *error;
printf (_("Syncing with the pilot..."));
dlp_ReadUserInfo (pilot_fd, &user_info);
@@ -285,36 +512,59 @@ sync_pilot (GNOME_Calendar_Repository repo, int pilot_fd)
* 1. Pull all the records from the Pilot, and make any updates
* required on the desktop side
*/
- for (record = 0;; record++){
- struct Appointment a;
- int rec_len, attr, size;
- recordid_t id;
-
- rec_len = dlp_ReadRecordByIndex (pilot_fd, db, record, buffer, &id, &size, &attr, 0);
-
- if (rec_len < 0)
- break;
+ if (!only_desktop_to_pilot){
+ for (record = 0;; record++){
+ struct Appointment a;
+ int rec_len, attr, size;
+ recordid_t id;
+
+ rec_len = dlp_ReadRecordByIndex (
+ pilot_fd, db,
+ record, buffer, &id, &size, &attr, 0);
- printf ("processing record %d\n", record);
- unpack_Appointment (&a, buffer, rec_len);
-
- /* If the object was deleted, remove it from the database */
- if (attr & dlpRecAttrDeleted){
- delete_record (repo, id);
- continue;
- }
+ if (rec_len < 0)
+ break;
+
+ printf ("processing record %d\n", record);
+ unpack_Appointment (&a, buffer, rec_len);
+
+ if (debug_attrs)
+ dump_attr (attr);
+
+ /* If the object was deleted, remove it from the database */
+ if (attr & dlpRecAttrDeleted){
+ printf ("Deleteing\n");
+ delete_record (repo, id);
+ free_Appointment (&a);
+ continue;
+ }
- if (attr & dlpRecAttrDirty){
- printf ("updating record\n");
- update_record (repo, id, &a, attr);
+ if (attr & dlpRecAttrArchived)
+ continue;
+
+ if (attr & dlpRecAttrDirty){
+ printf ("updating record\n");
+ update_record (repo, id, &a, attr);
+ }
+
+ free_Appointment (&a);
}
-
- free_Appointment (&a);
}
+
/*
* 2. Pull all the records from the Calendar, and move any new items
* to the pilot
*/
+ if (!only_pilot_to_desktop){
+ vcalendar_string = GNOME_Calendar_Repository_get_updated_objects (repo, &ev);
+ dirty_cal = calendar_new ("Temporal");
+ error = calendar_load_from_memory (dirty_cal, vcalendar_string);
+ if (!error)
+ sync_cal_to_pilot (repo, dirty_cal, pilot_fd);
+ calendar_destroy (dirty_cal);
+ }
+
+
dlp_CloseDB (pilot_fd, db);
dlp_AddSyncLogEntry (pilot_fd, _("Synced DateBook from Pilot to GnomeCal"));
pi_close (pilot_fd);
diff --git a/calendar/gui/calendar.c b/calendar/gui/calendar.c
index b67f875fdc..30e4e0168c 100644
--- a/calendar/gui/calendar.c
+++ b/calendar/gui/calendar.c
@@ -72,7 +72,7 @@ add_object_alarms (iCalObject *obj, time_t start, time_t end, void *closure)
#define max(a,b) ((a > b) ? a : b)
-void
+static void
ical_object_try_alarms (iCalObject *obj)
{
int ao, po, od, mo;
@@ -169,7 +169,7 @@ calendar_destroy (Calendar *cal)
g_free (cal);
}
-char *
+static char *
ice (time_t t)
{
static char buffer [100];
@@ -323,6 +323,34 @@ calendar_load (Calendar *cal, char *fname)
return NULL;
}
+/*
+ * calendar_load_from_memory:
+ * @cal: calendar on which we load the information
+ * @buffer: A buffer that contains a vCalendar file
+ *
+ * Loads the information from the vCalendar information in @buffer
+ * into the Calendar
+ */
+char *
+calendar_load_from_memory (Calendar *cal, const char *buffer)
+{
+ VObject *vcal;
+
+ g_return_val_if_fail (buffer != NULL, NULL);
+
+ cal->filename = g_strdup ("memory-based-calendar");
+ vcal = Parse_MIME (buffer, strlen (buffer));
+ if (!vcal)
+ return "Could not load the calendar";
+
+ cal->file_time = time (NULL);
+ calendar_load_from_vobject (cal, vcal);
+ cleanVObject (vcal);
+ cleanStrTbl ();
+
+ return NULL;
+}
+
static VObject *
vcalendar_create_from_calendar (Calendar *cal)
{
diff --git a/calendar/gui/calendar.h b/calendar/gui/calendar.h
index 2ea2753057..aa25fba67c 100644
--- a/calendar/gui/calendar.h
+++ b/calendar/gui/calendar.h
@@ -44,6 +44,8 @@ char *calendar_get_as_vcal_string (Calendar *cal);
char *calendar_string_from_object (iCalObject *object);
char *calendar_load (Calendar *cal, char *fname);
+char *calendar_load_from_memory (Calendar *cal, const char *buffer);
+void calendar_load_from_vobject (Calendar *cal, VObject *vcal);
void calendar_save (Calendar *cal, char *fname);
void calendar_add_object (Calendar *cal, iCalObject *obj);
void calendar_remove_object (Calendar *cal, iCalObject *obj);
diff --git a/calendar/gui/corba-cal-factory.c b/calendar/gui/corba-cal-factory.c
index 49a2c5ac76..c10929376b 100644
--- a/calendar/gui/corba-cal-factory.c
+++ b/calendar/gui/corba-cal-factory.c
@@ -35,7 +35,7 @@ static GNOME_GenericFactory calendar_factory;
static CORBA_boolean
calendar_supports (PortableServer_Servant servant,
- const CORBA_char * obj_goad_id,
+ CORBA_char * obj_goad_id,
CORBA_Environment * ev)
{
if (strcmp (obj_goad_id, "IDL:GNOME:Calendar:Repository:1.0") == 0)
@@ -46,7 +46,7 @@ calendar_supports (PortableServer_Servant servant,
static CORBA_Object
calendar_create_object (PortableServer_Servant servant,
- const CORBA_char *goad_id,
+ CORBA_char *goad_id,
const GNOME_stringlist *params,
CORBA_Environment *ev)
{
diff --git a/calendar/gui/corba-cal.c b/calendar/gui/corba-cal.c
index d78685bf90..8f92057d42 100644
--- a/calendar/gui/corba-cal.c
+++ b/calendar/gui/corba-cal.c
@@ -81,6 +81,7 @@ cal_repo_get_object_by_pilot_id (PortableServer_Servant servant,
CORBA_char *ret;
obj = calendar_object_find_by_pilot (gcal->cal, pilot_id);
+ printf ("Looking for [%d]\n", pilot_id);
if (obj == NULL){
CORBA_exception_set (ev,
CORBA_USER_EXCEPTION,
@@ -148,6 +149,7 @@ cal_repo_update_object (PortableServer_Servant servant,
obj = calendar_object_find_event (gcal->cal, uid);
if (obj != NULL){
+ printf ("ELIMINATING: %s -> %s\n", obj->uid, new_object->uid);
calendar_remove_object (gcal->cal, obj);
}
@@ -155,6 +157,60 @@ cal_repo_update_object (PortableServer_Servant servant,
}
static void
+cal_repo_update_pilot_id (PortableServer_Servant servant,
+ CORBA_char *uid,
+ CORBA_long pilot_id,
+ CORBA_long pilot_status,
+ CORBA_Environment *ev)
+{
+ GnomeCalendar *gcal = gnomecal_from_servant (servant);
+ iCalObject *obj;
+
+ obj = calendar_object_find_event (gcal->cal, uid);
+ if (obj == NULL){
+ CORBA_exception_set (
+ ev,
+ CORBA_USER_EXCEPTION,
+ ex_GNOME_Calendar_Repository_NotFound,
+ "");
+ return;
+ }
+
+ obj->pilot_id = pilot_id;
+ obj->pilot_status = pilot_status;
+}
+
+static CORBA_char *
+cal_repo_get_updated_objects (PortableServer_Servant servant,
+ CORBA_Environment *ev)
+{
+ GnomeCalendar *gcal = gnomecal_from_servant (servant);
+ Calendar *dirty_cal;
+ GList *l;
+ CORBA_char *res;
+ char *str;
+
+ dirty_cal = calendar_new ("Temporal");
+
+ for (l = gcal->cal->events; l; l = l->next){
+ iCalObject *obj = l->data;
+
+ if (obj->pilot_status != ICAL_PILOT_SYNC_MOD)
+ continue;
+
+ obj = ical_object_duplicate (l->data);
+
+ calendar_add_object (dirty_cal, obj);
+ }
+ str = calendar_get_as_vcal_string (dirty_cal);
+ res = CORBA_string_dup (str);
+ g_free (str);
+ calendar_destroy (dirty_cal);
+
+ return res;
+}
+
+static void
cal_repo_done (PortableServer_Servant servant,
CORBA_Environment *ev)
{
@@ -171,6 +227,9 @@ init_calendar_repo_class (void)
calendar_repository_epv.get_id_from_pilot_id = cal_repo_get_id_from_pilot_id;
calendar_repository_epv.delete_object = cal_repo_delete_object;
calendar_repository_epv.update_object = cal_repo_update_object;
+ calendar_repository_epv.get_updated_objects = cal_repo_get_updated_objects;
+ calendar_repository_epv.update_pilot_id = cal_repo_update_pilot_id;
+
calendar_repository_epv.done = cal_repo_done;
calendar_repository_vepv.GNOME_Calendar_Repository_epv =
diff --git a/calendar/gui/eventedit.c b/calendar/gui/eventedit.c
index a73775b375..8a36b94638 100644
--- a/calendar/gui/eventedit.c
+++ b/calendar/gui/eventedit.c
@@ -59,7 +59,7 @@ event_editor_class_init (EventEditorClass *class)
object_class->destroy = event_editor_destroy;
}
-GtkWidget *
+static GtkWidget *
adjust (GtkWidget *w, gfloat x, gfloat y, gfloat xs, gfloat ys)
{
GtkWidget *a = gtk_alignment_new (x, y, xs, ys);
@@ -432,7 +432,7 @@ ee_classification_widgets (EventEditor *ee)
* Retrieves the information from the CalendarAlarm widgets and stores them
* on the CalendarAlarm generic values
*/
-void
+static void
ee_store_alarm (CalendarAlarm *alarm, enum AlarmType type)
{
GtkWidget *item;
diff --git a/calendar/pcs/calobj.c b/calendar/pcs/calobj.c
index 08c8d8c63a..f1bec05c2b 100644
--- a/calendar/pcs/calobj.c
+++ b/calendar/pcs/calobj.c
@@ -18,23 +18,28 @@
static char *
ical_gen_uid (void)
{
- static char *domain;
+ static char *hostname;
time_t t = time (NULL);
+ static int serial;
- if (!domain){
+ if (!hostname){
char buffer [128];
- getdomainname (buffer, sizeof (buffer)-1);
- domain = g_strdup (domain);
+ gethostname (buffer, sizeof (buffer)-1);
+ if (hostname)
+ hostname = g_strdup (hostname);
+ else
+ hostname = g_strdup ("localhost");
}
return g_strdup_printf (
- "%s-%d-%d-%d@%s",
+ "%s-%d-%d-%d-%d@%s",
isodate_from_time_t (t),
getpid (),
getgid (),
getppid (),
- domain);
+ serial++,
+ hostname);
}
iCalObject *