aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/calendar-pilot-sync.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/calendar-pilot-sync.c')
-rw-r--r--calendar/gui/calendar-pilot-sync.c304
1 files changed, 277 insertions, 27 deletions
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);