From e49e9cc1755266dade86ce33662ceff466f5ca07 Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Wed, 28 Jul 1999 08:41:12 +0000 Subject: New file. Implements PalmPilot syncronization with the Gnome Calendar. 1999-07-28 Miguel de Icaza * calendar-pilot-sync.c: New file. Implements PalmPilot syncronization with the Gnome Calendar. 1999-07-27 Miguel de Icaza * calobj.c (ical_object_new_from_string): New function. Creates an iCalObject from a vCalendar string that is supposed to contain only one vEvent. * calendar.c: (calendar_save): Split this routine in two. * gnome-cal.c (gnome_calendar_new): Create the corba server here. * main.c: Include gnorba.h, and corba-cal-factory.h here (close_cmd): Kill the calendar server on shutdown. * calobj.c (load_recur_yearly_day): Added a fixme comment. WE need to handle intervals in the years. * calendar.c (calendar_object_find_in_list, calendar_object_find, calendar_object_find_todo, calendar_object_find_event): New functions for looking up information. * main.c (gnome_calendar_locate): New function. * corba-cal.c (calendar_create_object): New file. Implements the corba server. * calendar.c (calendar_object_changed): Flag pilot-status as changed. * calobj.c (ical_object_to_vobject): Save pilot information for syncing. (ical_object_create_from_vobject): Load syncing information for pilot. Do it in a way compatible with KOrganizer. 1999-07-26 Miguel de Icaza * calobj.c (ical_object_create_from_vobject): Generate unique IDs on Vevents we load that lack it. WE need this for the old gnome calendar generated files (ie, before now :-). svn path=/trunk/; revision=1038 --- calendar/ChangeLog | 45 +++++ calendar/Makefile.am | 48 ++++- calendar/TODO | 5 + calendar/cal-util/calobj.c | 62 +++++++ calendar/cal-util/calobj.h | 11 ++ calendar/calendar-pilot-sync.c | 360 +++++++++++++++++++++++++++++++++++++ calendar/calendar.c | 139 +++++++++++++- calendar/calendar.h | 11 ++ calendar/calobj.c | 62 +++++++ calendar/calobj.h | 11 ++ calendar/gnome-cal.c | 2 + calendar/gnome-cal.h | 2 + calendar/gui/Makefile.am | 48 ++++- calendar/gui/calendar-pilot-sync.c | 360 +++++++++++++++++++++++++++++++++++++ calendar/gui/calendar.c | 139 +++++++++++++- calendar/gui/calendar.h | 11 ++ calendar/gui/gnome-cal.c | 2 + calendar/gui/gnome-cal.h | 2 + calendar/gui/main.c | 49 ++++- calendar/gui/main.h | 3 + calendar/main.c | 49 ++++- calendar/main.h | 3 + calendar/pcs/calobj.c | 62 +++++++ calendar/pcs/calobj.h | 11 ++ 24 files changed, 1461 insertions(+), 36 deletions(-) create mode 100644 calendar/calendar-pilot-sync.c create mode 100644 calendar/gui/calendar-pilot-sync.c diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 9dac365862..8d7fed8098 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,48 @@ +1999-07-28 Miguel de Icaza + + * calendar-pilot-sync.c: New file. Implements PalmPilot + syncronization with the Gnome Calendar. + +1999-07-27 Miguel de Icaza + + * calobj.c (ical_object_new_from_string): New function. Creates + an iCalObject from a vCalendar string that is supposed to contain + only one vEvent. + + * calendar.c: + (calendar_save): Split this routine in two. + + * gnome-cal.c (gnome_calendar_new): Create the corba server here. + + * main.c: Include gnorba.h, and corba-cal-factory.h here + (close_cmd): Kill the calendar server on shutdown. + + * calobj.c (load_recur_yearly_day): Added a fixme comment. WE + need to handle intervals in the years. + + * calendar.c (calendar_object_find_in_list, calendar_object_find, + calendar_object_find_todo, calendar_object_find_event): New + functions for looking up information. + + * main.c (gnome_calendar_locate): New function. + + * corba-cal.c (calendar_create_object): New file. Implements the + corba server. + + * calendar.c (calendar_object_changed): Flag pilot-status as changed. + + * calobj.c (ical_object_to_vobject): Save pilot information for syncing. + (ical_object_create_from_vobject): Load syncing information for + pilot. Do it in a way compatible with KOrganizer. + +1999-07-26 Miguel de Icaza + + * calobj.c (ical_object_create_from_vobject): Generate unique IDs + on Vevents we load that lack it. WE need this for the old + gnome calendar generated files (ie, before now :-). + + Required to sync with the Palm + 1999-07-26 Miguel de Icaza * calobj.c (ical_object_create_from_vobject): Generate unique IDs diff --git a/calendar/Makefile.am b/calendar/Makefile.am index 151ce8d64b..e4fa401aad 100644 --- a/calendar/Makefile.am +++ b/calendar/Makefile.am @@ -1,17 +1,36 @@ SUBDIRS = doc +idldir = $(datadir)/idl +idl_DATA = GnomeCal.idl + +gnorbadir = $(sysconfdir)/CORBA/servers +gnorba_DATA = gnomecal.gnorba + help_base = $(datadir)/gnome/help/cal -CFLAGS += -Wall +CFLAGS += -Wall -Wunused -Wpointer-arith -Wmissing-declarations INCLUDES = \ -I$(includedir) \ $(GNOME_INCLUDEDIR) \ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" -bin_PROGRAMS = gnomecal +bin_PROGRAMS = gnomecal calendar-pilot-sync + +GNOMECAL_CORBA_GENERATED = \ + GnomeCal.h \ + GnomeCal.c \ + GnomeCal-common.c \ + GnomeCal-skels.c \ + GnomeCal-stubs.c + +$(GNOMECAL_CORBA_GENERATED): GnomeCal.idl + orbit-idl GnomeCal.idl gnomecal_SOURCES = \ + GnomeCal-common.c \ + GnomeCal-skels.c \ + GnomeCal.h \ alarm.c \ alarm.h \ calendar.c \ @@ -21,6 +40,10 @@ gnomecal_SOURCES = \ eventedit.c \ eventedit.h \ getdate.y \ + corba-cal.c \ + corba-cal.h \ + corba-cal-factory.c \ + corba-cal-factory.h \ gncal-day-panel.c \ gncal-day-panel.h \ gncal-day-view.c \ @@ -57,11 +80,28 @@ gnomecal_SOURCES = \ year-view.c \ year-view.h +calendar_pilot_sync_SOURCES = \ + GnomeCal-common.c \ + GnomeCal-stubs.c \ + alarm.c \ + calendar-pilot-sync.c \ + calobj.c \ + calobj.h \ + calendar.c \ + calendar.h \ + timeutil.c \ + timeutil.h + LINK_FLAGS = \ $(GNOME_LIBDIR) \ $(GNOMEGNORBA_LIBS) \ $(INTLLIBS) ../libversit/libversit.a +PILOT_LIBS = -lpisock + +calendar_pilot_sync_LDADD = \ + $(PILOT_LIBS) \ + $(LINK_FLAGS) #gncal_LDADD = $(LINK_FLAGS) @@ -70,7 +110,9 @@ gnomecal_LDADD = $(LINK_FLAGS) EXTRA_DIST = \ gncal.desktop \ bell.xpm \ - recur.xpm + recur.xpm \ + $(idl_DATA) \ + $(gnorba_DATA) Productivitydir = $(datadir)/gnome/apps/Applications diff --git a/calendar/TODO b/calendar/TODO index 5271b15909..bb964e908d 100644 --- a/calendar/TODO +++ b/calendar/TODO @@ -1,3 +1,8 @@ +Pilot: + +* Better support for untimed events (we have none now). +* Add syncing from Desktop to Pilot. + 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 2618470808..08c8d8c63a 100644 --- a/calendar/cal-util/calobj.c +++ b/calendar/cal-util/calobj.c @@ -47,6 +47,9 @@ ical_object_new (void) ico->seq = -1; ico->dtstamp = time (NULL); ico->uid = ical_gen_uid (); + + ico->pilot_id = 0; + ico->pilot_status = ICAL_PILOT_SYNC_MOD; return ico; } @@ -372,6 +375,8 @@ load_recur_yearly_day (iCalObject *o, char **str) { /* Skip as we do not support multiple days and we do expect * the dtstart to agree with the value on this field + * + * FIXME: we should support every-n-years */ skip_numbers (str); } @@ -782,6 +787,22 @@ ical_object_create_from_vobject (VObject *o, const char *object_name) } free (the_str); } + + /* + * Pilot + */ + if (has (o, XPilotIdProp)){ + ical->pilot_id = atoi (str_val (vo)); + free (the_str); + } else + ical->pilot_id = 0; + + if (has (o, XPilotStatusProp)){ + ical->pilot_status = atoi (str_val (vo)); + free (the_str); + } else + ical->pilot_status = ICAL_PILOT_SYNC_MOD; + return ical; } @@ -1047,6 +1068,17 @@ ical_object_to_vobject (iCalObject *ical) addPropValue (alarm, VCProcedureNameProp, ical->palarm.data); if ((alarm = save_alarm (o, &ical->malarm, ical))) addPropValue (alarm, VCEmailAddressProp, ical->malarm.data); + + /* Pilot */ + { + char buffer [20]; + + sprintf (buffer, "%d", ical->pilot_id); + addPropValue (o, XPilotIdProp, buffer); + sprintf (buffer, "%d", ical->pilot_status); + addPropValue (o, XPilotStatusProp, buffer); + } + return o; } @@ -1426,3 +1458,33 @@ alarm_compute_offset (CalendarAlarm *a) } return a->offset; } + +iCalObject * +ical_object_new_from_string (const char *vcal_string) +{ + iCalObject *ical = NULL; + VObject *cal, *event; + VObjectIterator i; + char *object_name; + + cal = Parse_MIME (vcal_string, strlen (vcal_string)); + + initPropIterator (&i, cal); + + while (moreIteration (&i)){ + event = nextVObject (&i); + + object_name = vObjectName (event); + + if (strcmp (object_name, VCEventProp) == 0){ + ical = ical_object_create_from_vobject (event, object_name); + break; + } + } + + cleanVObject (cal); + cleanStrTbl (); + + return ical; +} + diff --git a/calendar/cal-util/calobj.h b/calendar/cal-util/calobj.h index 9532b1325f..07ba3f1cc7 100644 --- a/calendar/cal-util/calobj.h +++ b/calendar/cal-util/calobj.h @@ -65,6 +65,12 @@ typedef struct { int len; } iCalValue; +typedef enum { + ICAL_PILOT_SYNC_NONE = 0, + ICAL_PILOT_SYNC_MOD = 1, + ICAL_PILOT_SYNC_DEL = 3 +} iCalPilotState; + typedef struct { int valid; /* true if the Geography was specified */ double latitude; @@ -172,6 +178,10 @@ typedef struct { int new; void *user_data; /* Generic data pointer */ + + /* Pilot */ + int pilot_status; /* Status information */ + int pilot_id; /* Pilot ID */ } iCalObject; /* The callback for the recurrence generator */ @@ -179,6 +189,7 @@ typedef int (*calendarfn) (iCalObject *, time_t, time_t, void *); iCalObject *ical_new (char *comment, char *organizer, char *summary); iCalObject *ical_object_new (void); +iCalObject *ical_object_new_from_string (const char *vcalendar_string); void ical_object_destroy (iCalObject *ico); iCalObject *ical_object_create_from_vobject (VObject *obj, const char *object_name); VObject *ical_object_to_vobject (iCalObject *ical); diff --git a/calendar/calendar-pilot-sync.c b/calendar/calendar-pilot-sync.c new file mode 100644 index 0000000000..6ed92d540a --- /dev/null +++ b/calendar/calendar-pilot-sync.c @@ -0,0 +1,360 @@ +/* + * calendar-pilot-sync.c: + * + * (C) 1999 International GNOME Support + * + * Author: + * Miguel de Icaza (miguel@gnome-support.com) + * + */ +#include +#include +#include +#include +#include +#include +#include +#include "calobj.h" +#include "calendar.h" +#include "timeutil.h" +#include "GnomeCal.h" +#include "pi-source.h" +#include "pi-socket.h" +#include "pi-datebook.h" +#include "pi-dlp.h" + +/* the CORBA ORB */ +CORBA_ORB orb; + +/* The default port to communicate with */ +char *pilot_port = "/dev/pilot"; + +CORBA_Environment ev; + +struct pi_sockaddr addr; + +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") }, + { NULL, '\0', 0, NULL, 0 } +}; + +static int +setup_connection (void) +{ + int socket; + int ret, news; + + if (!(socket = pi_socket(PI_AF_SLP, PI_SOCK_STREAM, PI_PF_PADP))) + g_error (_("Can not create Pilot socket\n")); + + addr.pi_family = PI_AF_SLP; + strncpy ((void *) &addr.pi_device, pilot_port, sizeof (addr.pi_device)); + + ret = pi_bind (socket, (struct sockaddr *)&addr, sizeof (addr)); + if (ret == -1) + g_error (_("Can not bind to device %s\n"), pilot_port); + + if (pi_listen (socket, 1) == -1) + g_error (_("Failed to get a connection from the Pilot device")); + + if ((news = pi_accept (socket, 0, 0)) == -1) + g_error (_("pi_accept failed")); + + return news; +} + +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", + 0, NULL); + + if (repo == CORBA_OBJECT_NIL) + g_error ("Can not communicate with GnomeCalendar server"); + + if (ev._major != CORBA_NO_EXCEPTION){ + printf ("Exception: %s\n", CORBA_exception_id (&ev)); + abort (); + } + + return repo; +} + +static void +delete_record (GNOME_Calendar_Repository repo, int id) +{ + char *uid; + + uid = GNOME_Calendar_Repository_get_id_from_pilot_id (repo, id, &ev); + + /* The record was already deleted */ + if (ev._major != CORBA_NO_EXCEPTION) + return; + + GNOME_Calendar_Repository_delete_object (repo, uid, &ev); + CORBA_free (uid); +} + +static void +update_record (GNOME_Calendar_Repository repo, int id, struct Appointment *a, int attr) +{ + char *vcal_string; + iCalObject *obj; + int i; + char *str; + + obj = ical_new (a->note ? a->note : "", + g_get_user_name (), + a->description ? a->description : ""); + + vcal_string = GNOME_Calendar_Repository_get_object_by_pilot_id (repo, id, &ev); + + if (ev._major == CORBA_USER_EXCEPTION){ + time_t now = time (NULL); + + obj->created = now; + obj->last_mod = now; + obj->priority = 0; + obj->transp = 0; + obj->related = NULL; + obj->pilot_id = id; + obj->pilot_status = ICAL_PILOT_SYNC_NONE; + printf (_("Object did not exist, creating a new one")); + } else + 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")); + ical_object_destroy (obj); + return; + } + + /* + * Begin and end + */ + obj->dtstart = mktime (&a->begin); + obj->dtend = mktime (&a->end); + + /* Special case: daily repetitions are converted to a multi-day event */ + if (a->repeatType == repeatDaily){ + time_t newt = time_add_day (obj->dtend, a->repeatFrequency); + + obj->dtend = newt; + } + + /* + * Alarm + */ + if (a->alarm){ + obj->aalarm.type = ALARM_AUDIO; + obj->aalarm.enabled = 1; + obj->aalarm.count = a->advance; + + switch (a->advanceUnits){ + case advMinutes: + obj->aalarm.units = ALARM_MINUTES; + break; + + case advHours: + obj->aalarm.units = ALARM_HOURS; + break; + + case advDays: + obj->aalarm.units = ALARM_DAYS; + break; + default: + } + } + + /* + * Recurrence + */ + if (a->repeatFrequency && a->repeatType != repeatDaily){ + obj->recur = g_new0 (Recurrence, 1); + + switch (a->repeatType){ + case repeatDaily: + /* + * In the Pilot daily repetitions are actually + * multi-day events + */ + g_warning ("Should not have got here"); + break; + + case repeatMonthlyByDate: + obj->recur->type = RECUR_MONTHLY_BY_DAY; + obj->recur->u.month_day = a->repeatFrequency; + break; + + case repeatWeekly: + { + int wd; + + obj->recur->type = RECUR_WEEKLY; + for (wd = 0; wd < 7; wd++) + if (a->repeatDays [wd]) + obj->recur->weekday |= 1 << wd; + + if (obj->recur->weekday == 0){ + struct tm *tm = localtime (&obj->dtstart); + + obj->recur->weekday = 1 << tm->tm_wday; + } + break; + } + + case repeatMonthlyByDay: + obj->recur->type = RECUR_MONTHLY_BY_POS; + obj->recur->u.month_pos = a->repeatFrequency; + obj->recur->weekday = (a->repeatDay / 7); + break; + + case repeatYearly: + obj->recur->type = RECUR_YEARLY_BY_DAY; + break; + + default: + g_warning ("Unhandled repeate case"); + } + + if (a->repeatForever) + obj->recur->duration = 0; + else + obj->recur->_enddate = mktime (&a->repeatEnd); + } + + /* + * Load exception dates + */ + obj->exdate = NULL; + for (i = 0; i < a->exceptions; i++){ + time_t *t = g_new (time_t, 1); + + *t = mktime (&(a->exception [i])); + obj->exdate = g_list_prepend (obj->exdate, t); + } + + g_free (obj->class); + + if (attr & dlpRecAttrSecret) + obj->class = g_strdup ("PRIVATE"); + else + obj->class = g_strdup ("PUBLIC"); + + /* + * Now, convert the in memory iCalObject to a full vCalendar we can send + */ + str = calendar_string_from_object (obj); + + GNOME_Calendar_Repository_update_object (repo, obj->uid, str, &ev); + + free (str); + + /* + * Shutdown + */ + ical_object_destroy (obj); +} + +static void +sync_pilot (GNOME_Calendar_Repository repo, int pilot_fd) +{ + struct PilotUser user_info; + int db,record; + unsigned char buffer [65536]; + + printf (_("Syncing with the pilot...")); + dlp_ReadUserInfo (pilot_fd, &user_info); + + /* This informs the user of the progress on the Pilot */ + dlp_OpenConduit (pilot_fd); + + if (dlp_OpenDB (pilot_fd, 0, 0x80 | 0x40, "DatebookDB", &db) < 0){ + g_warning (_("Could not open DatebookDB on the Pilot")); + dlp_AddSyncLogEntry (pilot_fd, _("Unable to open DatebookDB")); + pi_close (pilot_fd); + exit (1); + } + + /* + * 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; + + 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 (attr & dlpRecAttrDirty){ + printf ("updating record\n"); + update_record (repo, id, &a, attr); + } + + free_Appointment (&a); + } + /* + * 2. Pull all the records from the Calendar, and move any new items + * to the pilot + */ + dlp_CloseDB (pilot_fd, db); + dlp_AddSyncLogEntry (pilot_fd, _("Synced DateBook from Pilot to GnomeCal")); + pi_close (pilot_fd); +} + +int +main (int argc, char *argv []) +{ + int link; + GNOME_Calendar_Repository repository; + + CORBA_exception_init (&ev); + orb = gnome_CORBA_init_with_popt_table ( + "calendar-pilot-sync", VERSION, &argc, argv, + calendar_sync_options, 0, NULL, 0, &ev); + + printf ("Please, press HotSync button on the palm..."); + fflush (stdout); + link = setup_connection (); + printf ("Connected\n"); + + printf ("Launching GnomeCal..."); + fflush (stdout); + repository = locate_calendar_server (); + printf ("Done\n"); + + printf ("Syncing...\n"); + sync_pilot (repository, link); + printf ("Done Syncing\n"); + + GNOME_Calendar_Repository_done (repository, &ev); + + CORBA_exception_free (&ev); + + return 0; +} + +/* Just a stub to link with */ +void +calendar_notify (time_t time, CalendarAlarm *which, void *data) +{ +} + diff --git a/calendar/calendar.c b/calendar/calendar.c index ff7ae8ee5d..b67f875fdc 100644 --- a/calendar/calendar.c +++ b/calendar/calendar.c @@ -4,7 +4,7 @@ * This keeps track of a given calendar. Eventually this will abtract everything * related to getting calendars/saving calendars locally or to a remote Calendar Service * - * Copyright (C) 1998 the Free Software Foundation + * Copyright (C) 1998, 1999 the Free Software Foundation * * Authors: * Miguel de Icaza (miguel@gnu.org) @@ -323,18 +323,14 @@ calendar_load (Calendar *cal, char *fname) return NULL; } -void -calendar_save (Calendar *cal, char *fname) +static VObject * +vcalendar_create_from_calendar (Calendar *cal) { VObject *vcal; GList *l; time_t now = time (NULL); - struct stat s; struct tm *tm; - if (fname == NULL) - fname = cal->filename; - /* WE call localtime for the side effect of setting tzname */ tm = localtime (&now); @@ -366,6 +362,19 @@ calendar_save (Calendar *cal, char *fname) addVObjectProp (vcal, obj); } + return vcal; +} + +void +calendar_save (Calendar *cal, char *fname) +{ + VObject *vcal; + struct stat s; + + if (fname == NULL) + fname = cal->filename; + + vcal = vcalendar_create_from_calendar (cal); if (g_file_exists (fname)){ char *backup_name = g_strconcat (fname, "~", NULL); @@ -375,6 +384,7 @@ calendar_save (Calendar *cal, char *fname) rename (fname, backup_name); g_free (backup_name); } + writeVObjectToFile (fname, vcal); stat (fname, &s); @@ -384,6 +394,23 @@ calendar_save (Calendar *cal, char *fname) cleanStrTbl (); } +char * +calendar_get_as_vcal_string (Calendar *cal) +{ + VObject *vcal; + char *result; + + g_return_val_if_fail (cal != NULL, NULL); + + vcal = vcalendar_create_from_calendar (cal); + result = writeMemVObject (NULL, 0, vcal); + + cleanVObject (vcal); + cleanStrTbl (); + + return result; +} + static gint calendar_object_compare_by_start (gconstpointer a, gconstpointer b) { @@ -440,6 +467,8 @@ calendar_object_changed (Calendar *cal, iCalObject *obj, int flags) while (alarm_kill (obj)) ; ical_object_try_alarms (obj); + + obj->pilot_status = ICAL_PILOT_SYNC_MOD; } static void @@ -466,3 +495,99 @@ calendar_init_alarms (Calendar *cal) alarm_add (&day_change_alarm, calendar_day_change, cal); } +static iCalObject * +calendar_object_find_in_list (Calendar *cal, GList *list, const char *uid) +{ + GList *l; + + for (l = list; l; l = l->next){ + iCalObject *obj = l->data; + + if (strcmp (obj->uid, uid) == 0) + return obj; + } + + return NULL; +} + +iCalObject * +calendar_object_find_event (Calendar *cal, const char *uid) +{ + g_return_val_if_fail (cal != NULL, NULL); + g_return_val_if_fail (uid != NULL, NULL); + + return calendar_object_find_in_list (cal, cal->events, uid); +} + +iCalObject * +calendar_object_find_todo (Calendar *cal, const char *uid) +{ + g_return_val_if_fail (cal != NULL, NULL); + g_return_val_if_fail (uid != NULL, NULL); + + return calendar_object_find_in_list (cal, cal->todo, uid); +} + +iCalObject * +calendar_object_find (Calendar *cal, const char *uid) +{ + iCalObject *obj; + + g_return_val_if_fail (cal != NULL, NULL); + g_return_val_if_fail (uid != NULL, NULL); + + obj = calendar_object_find_in_list (cal, cal->todo, uid); + + if (obj == NULL) + obj = calendar_object_find_in_list (cal, cal->events, uid); + + return obj; +} + +iCalObject * +calendar_object_find_by_pilot (Calendar *cal, int pilot_id) +{ + GList *l; + + g_return_val_if_fail (cal != NULL, NULL); + + for (l = cal->events; l; l = l->next){ + iCalObject *obj = l->data; + + if (obj->pilot_id == pilot_id) + return obj; + } + + for (l = cal->todo; l; l = l->next){ + iCalObject *obj = l->data; + + if (obj->pilot_id == pilot_id) + return obj; + } + + return NULL; +} + +/* + * calendar_string_from_object: + * + * Returns the iCalObject @object armored around a vCalendar + * object as a string. + */ +char * +calendar_string_from_object (iCalObject *object) +{ + Calendar *cal; + char *str; + + g_return_val_if_fail (object != NULL, NULL); + + cal = calendar_new ("Temporal"); + calendar_add_object (cal, object); + str = calendar_get_as_vcal_string (cal); + calendar_remove_object (cal, object); + + calendar_destroy (cal); + + return str; +} diff --git a/calendar/calendar.h b/calendar/calendar.h index 8dc0c517c3..2ea2753057 100644 --- a/calendar/calendar.h +++ b/calendar/calendar.h @@ -26,6 +26,8 @@ typedef struct { /* If the calendar was last modified */ int modified; void *temp; + + void *corba_server; } Calendar; /* This is only used by the calendar_get_events_in_range routine to get @@ -38,6 +40,9 @@ typedef struct { } CalendarObject; Calendar *calendar_new (char *title); +char *calendar_get_as_vcal_string (Calendar *cal); +char *calendar_string_from_object (iCalObject *object); + char *calendar_load (Calendar *cal, char *fname); void calendar_save (Calendar *cal, char *fname); void calendar_add_object (Calendar *cal, iCalObject *obj); @@ -63,6 +68,12 @@ void calendar_destroy_event_list (GList *l); void calendar_object_changed (Calendar *cal, iCalObject *obj, int flags); void calendar_notify (time_t time, CalendarAlarm *which, void *data); + +iCalObject *calendar_object_find_event (Calendar *cal, const char *uid); +iCalObject *calendar_object_find_todo (Calendar *cal, const char *uid); +iCalObject *calendar_object_find (Calendar *cal, const char *uid); +iCalObject *calendar_object_find_by_pilot (Calendar *cal, int pilot_id); + END_GNOME_DECLS #endif diff --git a/calendar/calobj.c b/calendar/calobj.c index 2618470808..08c8d8c63a 100644 --- a/calendar/calobj.c +++ b/calendar/calobj.c @@ -47,6 +47,9 @@ ical_object_new (void) ico->seq = -1; ico->dtstamp = time (NULL); ico->uid = ical_gen_uid (); + + ico->pilot_id = 0; + ico->pilot_status = ICAL_PILOT_SYNC_MOD; return ico; } @@ -372,6 +375,8 @@ load_recur_yearly_day (iCalObject *o, char **str) { /* Skip as we do not support multiple days and we do expect * the dtstart to agree with the value on this field + * + * FIXME: we should support every-n-years */ skip_numbers (str); } @@ -782,6 +787,22 @@ ical_object_create_from_vobject (VObject *o, const char *object_name) } free (the_str); } + + /* + * Pilot + */ + if (has (o, XPilotIdProp)){ + ical->pilot_id = atoi (str_val (vo)); + free (the_str); + } else + ical->pilot_id = 0; + + if (has (o, XPilotStatusProp)){ + ical->pilot_status = atoi (str_val (vo)); + free (the_str); + } else + ical->pilot_status = ICAL_PILOT_SYNC_MOD; + return ical; } @@ -1047,6 +1068,17 @@ ical_object_to_vobject (iCalObject *ical) addPropValue (alarm, VCProcedureNameProp, ical->palarm.data); if ((alarm = save_alarm (o, &ical->malarm, ical))) addPropValue (alarm, VCEmailAddressProp, ical->malarm.data); + + /* Pilot */ + { + char buffer [20]; + + sprintf (buffer, "%d", ical->pilot_id); + addPropValue (o, XPilotIdProp, buffer); + sprintf (buffer, "%d", ical->pilot_status); + addPropValue (o, XPilotStatusProp, buffer); + } + return o; } @@ -1426,3 +1458,33 @@ alarm_compute_offset (CalendarAlarm *a) } return a->offset; } + +iCalObject * +ical_object_new_from_string (const char *vcal_string) +{ + iCalObject *ical = NULL; + VObject *cal, *event; + VObjectIterator i; + char *object_name; + + cal = Parse_MIME (vcal_string, strlen (vcal_string)); + + initPropIterator (&i, cal); + + while (moreIteration (&i)){ + event = nextVObject (&i); + + object_name = vObjectName (event); + + if (strcmp (object_name, VCEventProp) == 0){ + ical = ical_object_create_from_vobject (event, object_name); + break; + } + } + + cleanVObject (cal); + cleanStrTbl (); + + return ical; +} + diff --git a/calendar/calobj.h b/calendar/calobj.h index 9532b1325f..07ba3f1cc7 100644 --- a/calendar/calobj.h +++ b/calendar/calobj.h @@ -65,6 +65,12 @@ typedef struct { int len; } iCalValue; +typedef enum { + ICAL_PILOT_SYNC_NONE = 0, + ICAL_PILOT_SYNC_MOD = 1, + ICAL_PILOT_SYNC_DEL = 3 +} iCalPilotState; + typedef struct { int valid; /* true if the Geography was specified */ double latitude; @@ -172,6 +178,10 @@ typedef struct { int new; void *user_data; /* Generic data pointer */ + + /* Pilot */ + int pilot_status; /* Status information */ + int pilot_id; /* Pilot ID */ } iCalObject; /* The callback for the recurrence generator */ @@ -179,6 +189,7 @@ typedef int (*calendarfn) (iCalObject *, time_t, time_t, void *); iCalObject *ical_new (char *comment, char *organizer, char *summary); iCalObject *ical_object_new (void); +iCalObject *ical_object_new_from_string (const char *vcalendar_string); void ical_object_destroy (iCalObject *ico); iCalObject *ical_object_create_from_vobject (VObject *obj, const char *object_name); VObject *ical_object_to_vobject (iCalObject *ical); diff --git a/calendar/gnome-cal.c b/calendar/gnome-cal.c index 86900dd343..1b6c80e236 100644 --- a/calendar/gnome-cal.c +++ b/calendar/gnome-cal.c @@ -226,6 +226,8 @@ gnome_calendar_new (char *title) gcal->current_display = time_day_begin (time (NULL)); gcal->cal = calendar_new (title); setup_widgets (gcal); + gnome_calendar_create_corba_server (gcal); + return retval; } diff --git a/calendar/gnome-cal.h b/calendar/gnome-cal.h index ae4e5292da..da53f29882 100644 --- a/calendar/gnome-cal.h +++ b/calendar/gnome-cal.h @@ -63,6 +63,8 @@ void gnome_calendar_object_changed (GnomeCalendar *gcal, iCalObject *obj, int flags); +GnomeCalendar *gnome_calendar_locate (const char *pathname); + /* Notifies the calendar that the time format has changed and it must update all its views */ void gnome_calendar_time_format_changed (GnomeCalendar *gcal); diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 151ce8d64b..e4fa401aad 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -1,17 +1,36 @@ SUBDIRS = doc +idldir = $(datadir)/idl +idl_DATA = GnomeCal.idl + +gnorbadir = $(sysconfdir)/CORBA/servers +gnorba_DATA = gnomecal.gnorba + help_base = $(datadir)/gnome/help/cal -CFLAGS += -Wall +CFLAGS += -Wall -Wunused -Wpointer-arith -Wmissing-declarations INCLUDES = \ -I$(includedir) \ $(GNOME_INCLUDEDIR) \ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" -bin_PROGRAMS = gnomecal +bin_PROGRAMS = gnomecal calendar-pilot-sync + +GNOMECAL_CORBA_GENERATED = \ + GnomeCal.h \ + GnomeCal.c \ + GnomeCal-common.c \ + GnomeCal-skels.c \ + GnomeCal-stubs.c + +$(GNOMECAL_CORBA_GENERATED): GnomeCal.idl + orbit-idl GnomeCal.idl gnomecal_SOURCES = \ + GnomeCal-common.c \ + GnomeCal-skels.c \ + GnomeCal.h \ alarm.c \ alarm.h \ calendar.c \ @@ -21,6 +40,10 @@ gnomecal_SOURCES = \ eventedit.c \ eventedit.h \ getdate.y \ + corba-cal.c \ + corba-cal.h \ + corba-cal-factory.c \ + corba-cal-factory.h \ gncal-day-panel.c \ gncal-day-panel.h \ gncal-day-view.c \ @@ -57,11 +80,28 @@ gnomecal_SOURCES = \ year-view.c \ year-view.h +calendar_pilot_sync_SOURCES = \ + GnomeCal-common.c \ + GnomeCal-stubs.c \ + alarm.c \ + calendar-pilot-sync.c \ + calobj.c \ + calobj.h \ + calendar.c \ + calendar.h \ + timeutil.c \ + timeutil.h + LINK_FLAGS = \ $(GNOME_LIBDIR) \ $(GNOMEGNORBA_LIBS) \ $(INTLLIBS) ../libversit/libversit.a +PILOT_LIBS = -lpisock + +calendar_pilot_sync_LDADD = \ + $(PILOT_LIBS) \ + $(LINK_FLAGS) #gncal_LDADD = $(LINK_FLAGS) @@ -70,7 +110,9 @@ gnomecal_LDADD = $(LINK_FLAGS) EXTRA_DIST = \ gncal.desktop \ bell.xpm \ - recur.xpm + recur.xpm \ + $(idl_DATA) \ + $(gnorba_DATA) Productivitydir = $(datadir)/gnome/apps/Applications diff --git a/calendar/gui/calendar-pilot-sync.c b/calendar/gui/calendar-pilot-sync.c new file mode 100644 index 0000000000..6ed92d540a --- /dev/null +++ b/calendar/gui/calendar-pilot-sync.c @@ -0,0 +1,360 @@ +/* + * calendar-pilot-sync.c: + * + * (C) 1999 International GNOME Support + * + * Author: + * Miguel de Icaza (miguel@gnome-support.com) + * + */ +#include +#include +#include +#include +#include +#include +#include +#include "calobj.h" +#include "calendar.h" +#include "timeutil.h" +#include "GnomeCal.h" +#include "pi-source.h" +#include "pi-socket.h" +#include "pi-datebook.h" +#include "pi-dlp.h" + +/* the CORBA ORB */ +CORBA_ORB orb; + +/* The default port to communicate with */ +char *pilot_port = "/dev/pilot"; + +CORBA_Environment ev; + +struct pi_sockaddr addr; + +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") }, + { NULL, '\0', 0, NULL, 0 } +}; + +static int +setup_connection (void) +{ + int socket; + int ret, news; + + if (!(socket = pi_socket(PI_AF_SLP, PI_SOCK_STREAM, PI_PF_PADP))) + g_error (_("Can not create Pilot socket\n")); + + addr.pi_family = PI_AF_SLP; + strncpy ((void *) &addr.pi_device, pilot_port, sizeof (addr.pi_device)); + + ret = pi_bind (socket, (struct sockaddr *)&addr, sizeof (addr)); + if (ret == -1) + g_error (_("Can not bind to device %s\n"), pilot_port); + + if (pi_listen (socket, 1) == -1) + g_error (_("Failed to get a connection from the Pilot device")); + + if ((news = pi_accept (socket, 0, 0)) == -1) + g_error (_("pi_accept failed")); + + return news; +} + +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", + 0, NULL); + + if (repo == CORBA_OBJECT_NIL) + g_error ("Can not communicate with GnomeCalendar server"); + + if (ev._major != CORBA_NO_EXCEPTION){ + printf ("Exception: %s\n", CORBA_exception_id (&ev)); + abort (); + } + + return repo; +} + +static void +delete_record (GNOME_Calendar_Repository repo, int id) +{ + char *uid; + + uid = GNOME_Calendar_Repository_get_id_from_pilot_id (repo, id, &ev); + + /* The record was already deleted */ + if (ev._major != CORBA_NO_EXCEPTION) + return; + + GNOME_Calendar_Repository_delete_object (repo, uid, &ev); + CORBA_free (uid); +} + +static void +update_record (GNOME_Calendar_Repository repo, int id, struct Appointment *a, int attr) +{ + char *vcal_string; + iCalObject *obj; + int i; + char *str; + + obj = ical_new (a->note ? a->note : "", + g_get_user_name (), + a->description ? a->description : ""); + + vcal_string = GNOME_Calendar_Repository_get_object_by_pilot_id (repo, id, &ev); + + if (ev._major == CORBA_USER_EXCEPTION){ + time_t now = time (NULL); + + obj->created = now; + obj->last_mod = now; + obj->priority = 0; + obj->transp = 0; + obj->related = NULL; + obj->pilot_id = id; + obj->pilot_status = ICAL_PILOT_SYNC_NONE; + printf (_("Object did not exist, creating a new one")); + } else + 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")); + ical_object_destroy (obj); + return; + } + + /* + * Begin and end + */ + obj->dtstart = mktime (&a->begin); + obj->dtend = mktime (&a->end); + + /* Special case: daily repetitions are converted to a multi-day event */ + if (a->repeatType == repeatDaily){ + time_t newt = time_add_day (obj->dtend, a->repeatFrequency); + + obj->dtend = newt; + } + + /* + * Alarm + */ + if (a->alarm){ + obj->aalarm.type = ALARM_AUDIO; + obj->aalarm.enabled = 1; + obj->aalarm.count = a->advance; + + switch (a->advanceUnits){ + case advMinutes: + obj->aalarm.units = ALARM_MINUTES; + break; + + case advHours: + obj->aalarm.units = ALARM_HOURS; + break; + + case advDays: + obj->aalarm.units = ALARM_DAYS; + break; + default: + } + } + + /* + * Recurrence + */ + if (a->repeatFrequency && a->repeatType != repeatDaily){ + obj->recur = g_new0 (Recurrence, 1); + + switch (a->repeatType){ + case repeatDaily: + /* + * In the Pilot daily repetitions are actually + * multi-day events + */ + g_warning ("Should not have got here"); + break; + + case repeatMonthlyByDate: + obj->recur->type = RECUR_MONTHLY_BY_DAY; + obj->recur->u.month_day = a->repeatFrequency; + break; + + case repeatWeekly: + { + int wd; + + obj->recur->type = RECUR_WEEKLY; + for (wd = 0; wd < 7; wd++) + if (a->repeatDays [wd]) + obj->recur->weekday |= 1 << wd; + + if (obj->recur->weekday == 0){ + struct tm *tm = localtime (&obj->dtstart); + + obj->recur->weekday = 1 << tm->tm_wday; + } + break; + } + + case repeatMonthlyByDay: + obj->recur->type = RECUR_MONTHLY_BY_POS; + obj->recur->u.month_pos = a->repeatFrequency; + obj->recur->weekday = (a->repeatDay / 7); + break; + + case repeatYearly: + obj->recur->type = RECUR_YEARLY_BY_DAY; + break; + + default: + g_warning ("Unhandled repeate case"); + } + + if (a->repeatForever) + obj->recur->duration = 0; + else + obj->recur->_enddate = mktime (&a->repeatEnd); + } + + /* + * Load exception dates + */ + obj->exdate = NULL; + for (i = 0; i < a->exceptions; i++){ + time_t *t = g_new (time_t, 1); + + *t = mktime (&(a->exception [i])); + obj->exdate = g_list_prepend (obj->exdate, t); + } + + g_free (obj->class); + + if (attr & dlpRecAttrSecret) + obj->class = g_strdup ("PRIVATE"); + else + obj->class = g_strdup ("PUBLIC"); + + /* + * Now, convert the in memory iCalObject to a full vCalendar we can send + */ + str = calendar_string_from_object (obj); + + GNOME_Calendar_Repository_update_object (repo, obj->uid, str, &ev); + + free (str); + + /* + * Shutdown + */ + ical_object_destroy (obj); +} + +static void +sync_pilot (GNOME_Calendar_Repository repo, int pilot_fd) +{ + struct PilotUser user_info; + int db,record; + unsigned char buffer [65536]; + + printf (_("Syncing with the pilot...")); + dlp_ReadUserInfo (pilot_fd, &user_info); + + /* This informs the user of the progress on the Pilot */ + dlp_OpenConduit (pilot_fd); + + if (dlp_OpenDB (pilot_fd, 0, 0x80 | 0x40, "DatebookDB", &db) < 0){ + g_warning (_("Could not open DatebookDB on the Pilot")); + dlp_AddSyncLogEntry (pilot_fd, _("Unable to open DatebookDB")); + pi_close (pilot_fd); + exit (1); + } + + /* + * 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; + + 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 (attr & dlpRecAttrDirty){ + printf ("updating record\n"); + update_record (repo, id, &a, attr); + } + + free_Appointment (&a); + } + /* + * 2. Pull all the records from the Calendar, and move any new items + * to the pilot + */ + dlp_CloseDB (pilot_fd, db); + dlp_AddSyncLogEntry (pilot_fd, _("Synced DateBook from Pilot to GnomeCal")); + pi_close (pilot_fd); +} + +int +main (int argc, char *argv []) +{ + int link; + GNOME_Calendar_Repository repository; + + CORBA_exception_init (&ev); + orb = gnome_CORBA_init_with_popt_table ( + "calendar-pilot-sync", VERSION, &argc, argv, + calendar_sync_options, 0, NULL, 0, &ev); + + printf ("Please, press HotSync button on the palm..."); + fflush (stdout); + link = setup_connection (); + printf ("Connected\n"); + + printf ("Launching GnomeCal..."); + fflush (stdout); + repository = locate_calendar_server (); + printf ("Done\n"); + + printf ("Syncing...\n"); + sync_pilot (repository, link); + printf ("Done Syncing\n"); + + GNOME_Calendar_Repository_done (repository, &ev); + + CORBA_exception_free (&ev); + + return 0; +} + +/* Just a stub to link with */ +void +calendar_notify (time_t time, CalendarAlarm *which, void *data) +{ +} + diff --git a/calendar/gui/calendar.c b/calendar/gui/calendar.c index ff7ae8ee5d..b67f875fdc 100644 --- a/calendar/gui/calendar.c +++ b/calendar/gui/calendar.c @@ -4,7 +4,7 @@ * This keeps track of a given calendar. Eventually this will abtract everything * related to getting calendars/saving calendars locally or to a remote Calendar Service * - * Copyright (C) 1998 the Free Software Foundation + * Copyright (C) 1998, 1999 the Free Software Foundation * * Authors: * Miguel de Icaza (miguel@gnu.org) @@ -323,18 +323,14 @@ calendar_load (Calendar *cal, char *fname) return NULL; } -void -calendar_save (Calendar *cal, char *fname) +static VObject * +vcalendar_create_from_calendar (Calendar *cal) { VObject *vcal; GList *l; time_t now = time (NULL); - struct stat s; struct tm *tm; - if (fname == NULL) - fname = cal->filename; - /* WE call localtime for the side effect of setting tzname */ tm = localtime (&now); @@ -366,6 +362,19 @@ calendar_save (Calendar *cal, char *fname) addVObjectProp (vcal, obj); } + return vcal; +} + +void +calendar_save (Calendar *cal, char *fname) +{ + VObject *vcal; + struct stat s; + + if (fname == NULL) + fname = cal->filename; + + vcal = vcalendar_create_from_calendar (cal); if (g_file_exists (fname)){ char *backup_name = g_strconcat (fname, "~", NULL); @@ -375,6 +384,7 @@ calendar_save (Calendar *cal, char *fname) rename (fname, backup_name); g_free (backup_name); } + writeVObjectToFile (fname, vcal); stat (fname, &s); @@ -384,6 +394,23 @@ calendar_save (Calendar *cal, char *fname) cleanStrTbl (); } +char * +calendar_get_as_vcal_string (Calendar *cal) +{ + VObject *vcal; + char *result; + + g_return_val_if_fail (cal != NULL, NULL); + + vcal = vcalendar_create_from_calendar (cal); + result = writeMemVObject (NULL, 0, vcal); + + cleanVObject (vcal); + cleanStrTbl (); + + return result; +} + static gint calendar_object_compare_by_start (gconstpointer a, gconstpointer b) { @@ -440,6 +467,8 @@ calendar_object_changed (Calendar *cal, iCalObject *obj, int flags) while (alarm_kill (obj)) ; ical_object_try_alarms (obj); + + obj->pilot_status = ICAL_PILOT_SYNC_MOD; } static void @@ -466,3 +495,99 @@ calendar_init_alarms (Calendar *cal) alarm_add (&day_change_alarm, calendar_day_change, cal); } +static iCalObject * +calendar_object_find_in_list (Calendar *cal, GList *list, const char *uid) +{ + GList *l; + + for (l = list; l; l = l->next){ + iCalObject *obj = l->data; + + if (strcmp (obj->uid, uid) == 0) + return obj; + } + + return NULL; +} + +iCalObject * +calendar_object_find_event (Calendar *cal, const char *uid) +{ + g_return_val_if_fail (cal != NULL, NULL); + g_return_val_if_fail (uid != NULL, NULL); + + return calendar_object_find_in_list (cal, cal->events, uid); +} + +iCalObject * +calendar_object_find_todo (Calendar *cal, const char *uid) +{ + g_return_val_if_fail (cal != NULL, NULL); + g_return_val_if_fail (uid != NULL, NULL); + + return calendar_object_find_in_list (cal, cal->todo, uid); +} + +iCalObject * +calendar_object_find (Calendar *cal, const char *uid) +{ + iCalObject *obj; + + g_return_val_if_fail (cal != NULL, NULL); + g_return_val_if_fail (uid != NULL, NULL); + + obj = calendar_object_find_in_list (cal, cal->todo, uid); + + if (obj == NULL) + obj = calendar_object_find_in_list (cal, cal->events, uid); + + return obj; +} + +iCalObject * +calendar_object_find_by_pilot (Calendar *cal, int pilot_id) +{ + GList *l; + + g_return_val_if_fail (cal != NULL, NULL); + + for (l = cal->events; l; l = l->next){ + iCalObject *obj = l->data; + + if (obj->pilot_id == pilot_id) + return obj; + } + + for (l = cal->todo; l; l = l->next){ + iCalObject *obj = l->data; + + if (obj->pilot_id == pilot_id) + return obj; + } + + return NULL; +} + +/* + * calendar_string_from_object: + * + * Returns the iCalObject @object armored around a vCalendar + * object as a string. + */ +char * +calendar_string_from_object (iCalObject *object) +{ + Calendar *cal; + char *str; + + g_return_val_if_fail (object != NULL, NULL); + + cal = calendar_new ("Temporal"); + calendar_add_object (cal, object); + str = calendar_get_as_vcal_string (cal); + calendar_remove_object (cal, object); + + calendar_destroy (cal); + + return str; +} diff --git a/calendar/gui/calendar.h b/calendar/gui/calendar.h index 8dc0c517c3..2ea2753057 100644 --- a/calendar/gui/calendar.h +++ b/calendar/gui/calendar.h @@ -26,6 +26,8 @@ typedef struct { /* If the calendar was last modified */ int modified; void *temp; + + void *corba_server; } Calendar; /* This is only used by the calendar_get_events_in_range routine to get @@ -38,6 +40,9 @@ typedef struct { } CalendarObject; Calendar *calendar_new (char *title); +char *calendar_get_as_vcal_string (Calendar *cal); +char *calendar_string_from_object (iCalObject *object); + char *calendar_load (Calendar *cal, char *fname); void calendar_save (Calendar *cal, char *fname); void calendar_add_object (Calendar *cal, iCalObject *obj); @@ -63,6 +68,12 @@ void calendar_destroy_event_list (GList *l); void calendar_object_changed (Calendar *cal, iCalObject *obj, int flags); void calendar_notify (time_t time, CalendarAlarm *which, void *data); + +iCalObject *calendar_object_find_event (Calendar *cal, const char *uid); +iCalObject *calendar_object_find_todo (Calendar *cal, const char *uid); +iCalObject *calendar_object_find (Calendar *cal, const char *uid); +iCalObject *calendar_object_find_by_pilot (Calendar *cal, int pilot_id); + END_GNOME_DECLS #endif diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c index 86900dd343..1b6c80e236 100644 --- a/calendar/gui/gnome-cal.c +++ b/calendar/gui/gnome-cal.c @@ -226,6 +226,8 @@ gnome_calendar_new (char *title) gcal->current_display = time_day_begin (time (NULL)); gcal->cal = calendar_new (title); setup_widgets (gcal); + gnome_calendar_create_corba_server (gcal); + return retval; } diff --git a/calendar/gui/gnome-cal.h b/calendar/gui/gnome-cal.h index ae4e5292da..da53f29882 100644 --- a/calendar/gui/gnome-cal.h +++ b/calendar/gui/gnome-cal.h @@ -63,6 +63,8 @@ void gnome_calendar_object_changed (GnomeCalendar *gcal, iCalObject *obj, int flags); +GnomeCalendar *gnome_calendar_locate (const char *pathname); + /* Notifies the calendar that the time format has changed and it must update all its views */ void gnome_calendar_time_format_changed (GnomeCalendar *gcal); diff --git a/calendar/gui/main.c b/calendar/gui/main.c index 2167d026f3..7a1888898b 100644 --- a/calendar/gui/main.c +++ b/calendar/gui/main.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -20,7 +21,7 @@ #include "gnome-cal.h" #include "main.h" #include "timeutil.h" - +#include "corba-cal-factory.h" #define COOKIE_USER_HOME_DIR ((char *) -1) @@ -66,8 +67,6 @@ int active_calendars = 0; /* A list of all of the calendars started */ GList *all_calendars = NULL; -static void new_calendar (char *full_name, char *calendar_file, char *geometry, char *view, gboolean hidden); - /* For dumping part of a calendar */ static time_t from_t, to_t; @@ -203,10 +202,29 @@ display_objedit_today (GtkWidget *widget, GnomeCalendar *gcal) gtk_widget_show (ee); } +GnomeCalendar * +gnome_calendar_locate (const char *pathname) +{ + GList *l; + + if (pathname == NULL || pathname [0] == 0) + pathname = user_calendar_file; + + for (l = all_calendars; l; l = l->next){ + GnomeCalendar *gcal = l->data; + + if (strcmp (gcal->cal->filename, pathname) == 0){ + return gcal; + } + } + return NULL; +} + static void close_cmd (GtkWidget *widget, GnomeCalendar *gcal) { all_calendars = g_list_remove (all_calendars, gcal); + if (gcal->cal->modified){ if (!gcal->cal->filename) save_calendar_cmd (widget, gcal); @@ -217,8 +235,10 @@ close_cmd (GtkWidget *widget, GnomeCalendar *gcal) gtk_widget_destroy (GTK_WIDGET (gcal)); active_calendars--; - if (active_calendars == 0) + if (active_calendars == 0){ + unregister_calendar_services (); gtk_main_quit (); + } } void @@ -551,7 +571,7 @@ calendar_close_event (GtkWidget *widget, GdkEvent *event, GnomeCalendar *gcal) return TRUE; } -static void +GnomeCalendar * new_calendar (char *full_name, char *calendar_file, char *geometry, char *page, gboolean hidden) { GtkWidget *toplevel; @@ -559,7 +579,8 @@ new_calendar (char *full_name, char *calendar_file, char *geometry, char *page, int xpos, ypos, width, height; /* i18n: This "%s%s" indicates possession. Languages where the order is - the inverse should translate it to "%2$s%1$s". */ + * the inverse should translate it to "%2$s%1$s". + */ g_snprintf(title, 128, _("%s%s"), full_name, _("'s calendar")); toplevel = gnome_calendar_new (title); @@ -606,6 +627,8 @@ new_calendar (char *full_name, char *calendar_file, char *geometry, char *page, } gtk_widget_show (toplevel); + + return GNOME_CALENDAR (toplevel); } static void @@ -839,13 +862,23 @@ int main(int argc, char *argv[]) { GnomeClient *client; + CORBA_Environment ev; bindtextdomain (PACKAGE, GNOMELOCALEDIR); textdomain (PACKAGE); - gnome_init_with_popt_table ("calendar", VERSION, argc, argv, - options, 0, NULL); + CORBA_exception_init (&ev); + + gnome_CORBA_init_with_popt_table ( + "calendar", VERSION, &argc, argv, + options, 0, NULL, GNORBA_INIT_SERVER_FUNC, &ev); + orb = gnome_CORBA_ORB (); + poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references (orb, "RootPOA", &ev); + if (ev._major == CORBA_NO_EXCEPTION){ + init_corba_server (); + } + if (show_events) dump_events (); if (show_todo) diff --git a/calendar/gui/main.h b/calendar/gui/main.h index 96ffcaf33d..584ce2e83c 100644 --- a/calendar/gui/main.h +++ b/calendar/gui/main.h @@ -75,4 +75,7 @@ char *color_spec_from_prop (ColorProp propnum); void save_default_calendar (GnomeCalendar *gcal); +GnomeCalendar *new_calendar (char *full_name, char *calendar_file, + char *geometry, char *page, gboolean hidden); + #endif diff --git a/calendar/main.c b/calendar/main.c index 2167d026f3..7a1888898b 100644 --- a/calendar/main.c +++ b/calendar/main.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -20,7 +21,7 @@ #include "gnome-cal.h" #include "main.h" #include "timeutil.h" - +#include "corba-cal-factory.h" #define COOKIE_USER_HOME_DIR ((char *) -1) @@ -66,8 +67,6 @@ int active_calendars = 0; /* A list of all of the calendars started */ GList *all_calendars = NULL; -static void new_calendar (char *full_name, char *calendar_file, char *geometry, char *view, gboolean hidden); - /* For dumping part of a calendar */ static time_t from_t, to_t; @@ -203,10 +202,29 @@ display_objedit_today (GtkWidget *widget, GnomeCalendar *gcal) gtk_widget_show (ee); } +GnomeCalendar * +gnome_calendar_locate (const char *pathname) +{ + GList *l; + + if (pathname == NULL || pathname [0] == 0) + pathname = user_calendar_file; + + for (l = all_calendars; l; l = l->next){ + GnomeCalendar *gcal = l->data; + + if (strcmp (gcal->cal->filename, pathname) == 0){ + return gcal; + } + } + return NULL; +} + static void close_cmd (GtkWidget *widget, GnomeCalendar *gcal) { all_calendars = g_list_remove (all_calendars, gcal); + if (gcal->cal->modified){ if (!gcal->cal->filename) save_calendar_cmd (widget, gcal); @@ -217,8 +235,10 @@ close_cmd (GtkWidget *widget, GnomeCalendar *gcal) gtk_widget_destroy (GTK_WIDGET (gcal)); active_calendars--; - if (active_calendars == 0) + if (active_calendars == 0){ + unregister_calendar_services (); gtk_main_quit (); + } } void @@ -551,7 +571,7 @@ calendar_close_event (GtkWidget *widget, GdkEvent *event, GnomeCalendar *gcal) return TRUE; } -static void +GnomeCalendar * new_calendar (char *full_name, char *calendar_file, char *geometry, char *page, gboolean hidden) { GtkWidget *toplevel; @@ -559,7 +579,8 @@ new_calendar (char *full_name, char *calendar_file, char *geometry, char *page, int xpos, ypos, width, height; /* i18n: This "%s%s" indicates possession. Languages where the order is - the inverse should translate it to "%2$s%1$s". */ + * the inverse should translate it to "%2$s%1$s". + */ g_snprintf(title, 128, _("%s%s"), full_name, _("'s calendar")); toplevel = gnome_calendar_new (title); @@ -606,6 +627,8 @@ new_calendar (char *full_name, char *calendar_file, char *geometry, char *page, } gtk_widget_show (toplevel); + + return GNOME_CALENDAR (toplevel); } static void @@ -839,13 +862,23 @@ int main(int argc, char *argv[]) { GnomeClient *client; + CORBA_Environment ev; bindtextdomain (PACKAGE, GNOMELOCALEDIR); textdomain (PACKAGE); - gnome_init_with_popt_table ("calendar", VERSION, argc, argv, - options, 0, NULL); + CORBA_exception_init (&ev); + + gnome_CORBA_init_with_popt_table ( + "calendar", VERSION, &argc, argv, + options, 0, NULL, GNORBA_INIT_SERVER_FUNC, &ev); + orb = gnome_CORBA_ORB (); + poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references (orb, "RootPOA", &ev); + if (ev._major == CORBA_NO_EXCEPTION){ + init_corba_server (); + } + if (show_events) dump_events (); if (show_todo) diff --git a/calendar/main.h b/calendar/main.h index 96ffcaf33d..584ce2e83c 100644 --- a/calendar/main.h +++ b/calendar/main.h @@ -75,4 +75,7 @@ char *color_spec_from_prop (ColorProp propnum); void save_default_calendar (GnomeCalendar *gcal); +GnomeCalendar *new_calendar (char *full_name, char *calendar_file, + char *geometry, char *page, gboolean hidden); + #endif diff --git a/calendar/pcs/calobj.c b/calendar/pcs/calobj.c index 2618470808..08c8d8c63a 100644 --- a/calendar/pcs/calobj.c +++ b/calendar/pcs/calobj.c @@ -47,6 +47,9 @@ ical_object_new (void) ico->seq = -1; ico->dtstamp = time (NULL); ico->uid = ical_gen_uid (); + + ico->pilot_id = 0; + ico->pilot_status = ICAL_PILOT_SYNC_MOD; return ico; } @@ -372,6 +375,8 @@ load_recur_yearly_day (iCalObject *o, char **str) { /* Skip as we do not support multiple days and we do expect * the dtstart to agree with the value on this field + * + * FIXME: we should support every-n-years */ skip_numbers (str); } @@ -782,6 +787,22 @@ ical_object_create_from_vobject (VObject *o, const char *object_name) } free (the_str); } + + /* + * Pilot + */ + if (has (o, XPilotIdProp)){ + ical->pilot_id = atoi (str_val (vo)); + free (the_str); + } else + ical->pilot_id = 0; + + if (has (o, XPilotStatusProp)){ + ical->pilot_status = atoi (str_val (vo)); + free (the_str); + } else + ical->pilot_status = ICAL_PILOT_SYNC_MOD; + return ical; } @@ -1047,6 +1068,17 @@ ical_object_to_vobject (iCalObject *ical) addPropValue (alarm, VCProcedureNameProp, ical->palarm.data); if ((alarm = save_alarm (o, &ical->malarm, ical))) addPropValue (alarm, VCEmailAddressProp, ical->malarm.data); + + /* Pilot */ + { + char buffer [20]; + + sprintf (buffer, "%d", ical->pilot_id); + addPropValue (o, XPilotIdProp, buffer); + sprintf (buffer, "%d", ical->pilot_status); + addPropValue (o, XPilotStatusProp, buffer); + } + return o; } @@ -1426,3 +1458,33 @@ alarm_compute_offset (CalendarAlarm *a) } return a->offset; } + +iCalObject * +ical_object_new_from_string (const char *vcal_string) +{ + iCalObject *ical = NULL; + VObject *cal, *event; + VObjectIterator i; + char *object_name; + + cal = Parse_MIME (vcal_string, strlen (vcal_string)); + + initPropIterator (&i, cal); + + while (moreIteration (&i)){ + event = nextVObject (&i); + + object_name = vObjectName (event); + + if (strcmp (object_name, VCEventProp) == 0){ + ical = ical_object_create_from_vobject (event, object_name); + break; + } + } + + cleanVObject (cal); + cleanStrTbl (); + + return ical; +} + diff --git a/calendar/pcs/calobj.h b/calendar/pcs/calobj.h index 9532b1325f..07ba3f1cc7 100644 --- a/calendar/pcs/calobj.h +++ b/calendar/pcs/calobj.h @@ -65,6 +65,12 @@ typedef struct { int len; } iCalValue; +typedef enum { + ICAL_PILOT_SYNC_NONE = 0, + ICAL_PILOT_SYNC_MOD = 1, + ICAL_PILOT_SYNC_DEL = 3 +} iCalPilotState; + typedef struct { int valid; /* true if the Geography was specified */ double latitude; @@ -172,6 +178,10 @@ typedef struct { int new; void *user_data; /* Generic data pointer */ + + /* Pilot */ + int pilot_status; /* Status information */ + int pilot_id; /* Pilot ID */ } iCalObject; /* The callback for the recurrence generator */ @@ -179,6 +189,7 @@ typedef int (*calendarfn) (iCalObject *, time_t, time_t, void *); iCalObject *ical_new (char *comment, char *organizer, char *summary); iCalObject *ical_object_new (void); +iCalObject *ical_object_new_from_string (const char *vcalendar_string); void ical_object_destroy (iCalObject *ico); iCalObject *ical_object_create_from_vobject (VObject *obj, const char *object_name); VObject *ical_object_to_vobject (iCalObject *ical); -- cgit v1.2.3