diff options
Diffstat (limited to 'calendar/gui/calendar-pilot-sync.c')
-rw-r--r-- | calendar/gui/calendar-pilot-sync.c | 304 |
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); |