From 3561e168465b99a2e31053a4a41ea05f9d485b9e Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Sat, 9 Sep 2000 01:00:05 +0000 Subject: New function with the loading/creation state machine. It is carefully 2000-09-08 Federico Mena Quintero * gui/gnome-cal.c (cal_loaded_cb): New function with the loading/creation state machine. It is carefully modelled after the state machine that started the Universe, so bow before it. (gnome_calendar_construct): Do not connect to cal_loaded here. (connect_load): The closure for the cal_loaded callback is a bit tricky, so provide a function to create it and connect to the signal. (disconnect_load): Disconnect from the signal and free the closure. (gnome_calendar_load_cb): Removed obsolete buggy function. (gnome_calendar_open): Use the new mechanism. * gui/control-factory.c (set_prop): The default filename is now calendar.ics. svn path=/trunk/; revision=5280 --- calendar/ChangeLog | 17 +++ calendar/gui/control-factory.c | 2 +- calendar/gui/gnome-cal.c | 283 +++++++++++++++++++++++++++-------------- calendar/gui/gnome-cal.h | 6 +- 4 files changed, 212 insertions(+), 96 deletions(-) diff --git a/calendar/ChangeLog b/calendar/ChangeLog index ee58b99707..cd4612f212 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,20 @@ +2000-09-08 Federico Mena Quintero + + * gui/gnome-cal.c (cal_loaded_cb): New function with the + loading/creation state machine. It is carefully modelled after + the state machine that started the Universe, so bow before it. + (gnome_calendar_construct): Do not connect to cal_loaded here. + (connect_load): The closure for the cal_loaded callback is a bit + tricky, so provide a function to create it and connect to the + signal. + (disconnect_load): Disconnect from the signal and free the + closure. + (gnome_calendar_load_cb): Removed obsolete buggy function. + (gnome_calendar_open): Use the new mechanism. + + * gui/control-factory.c (set_prop): The default filename is now + calendar.ics. + 2000-09-08 JP Rosevear * conduits/calendar/calendar-conduit.c (transmit): Use diff --git a/calendar/gui/control-factory.c b/calendar/gui/control-factory.c index 3b2f931127..104eb3a4c9 100644 --- a/calendar/gui/control-factory.c +++ b/calendar/gui/control-factory.c @@ -98,7 +98,7 @@ set_prop (BonoboPropertyBag *bag, case PROPERTY_CALENDAR_URI_IDX: printf ("set_prop: '%s'\n", BONOBO_ARG_GET_STRING (arg)); - filename = g_strdup_printf ("%s/calendar.vcf", + filename = g_strdup_printf ("%s/calendar.ics", BONOBO_ARG_GET_STRING (arg)); calendar_set_uri (gcal, filename); g_free (filename); diff --git a/calendar/gui/gnome-cal.c b/calendar/gui/gnome-cal.c index 2b1f14f1c6..58b6bdad55 100644 --- a/calendar/gui/gnome-cal.c +++ b/calendar/gui/gnome-cal.c @@ -40,9 +40,9 @@ typedef enum { /* States for the calendar loading and creation state machine */ typedef enum { LOAD_STATE_NOT_LOADED, - LOAD_STATE_LOAD_WAIT, - LOAD_STATE_CREATE_WAIT, - LOAD_STATE_CREATE_LOAD_WAIT, + LOAD_STATE_WAIT_LOAD, + LOAD_STATE_WAIT_LOAD_BEFORE_CREATE, + LOAD_STATE_WAIT_CREATE, LOAD_STATE_LOADED } LoadState; @@ -282,6 +282,8 @@ gnome_calendar_init (GnomeCalendar *gcal) priv = g_new0 (GnomeCalendarPrivate, 1); gcal->priv = priv; + priv->load_state = LOAD_STATE_NOT_LOADED; + priv->object_editor_hash = g_hash_table_new (g_str_hash, g_str_equal); priv->alarms = g_hash_table_new (g_str_hash, g_str_equal); @@ -343,6 +345,8 @@ gnome_calendar_destroy (GtkObject *object) gcal = GNOME_CALENDAR (object); priv = gcal->priv; + priv->load_state = LOAD_STATE_NOT_LOADED; + if (priv->client) { gtk_object_unref (GTK_OBJECT (priv->client)); priv->client = NULL; @@ -1039,10 +1043,11 @@ load_alarms (GnomeCalendar *gcal) } } -#ifndef NO_WARNINGS -/* FIXME: rename this function */ +/* Loads the initial data into the calendar; this should be called right after + * the cal_loaded signal from the client is invoked. + */ static void -gnome_calendar_update_all (GnomeCalendar *gcal) +initial_load (GnomeCalendar *gcal) { GnomeCalendarPrivate *priv; @@ -1051,7 +1056,6 @@ gnome_calendar_update_all (GnomeCalendar *gcal) load_alarms (gcal); gnome_calendar_tag_calendar (gcal, priv->date_navigator); } -#endif /* Removes any queued alarms for the specified UID */ static void @@ -1110,20 +1114,176 @@ add_alarms_for_object (GnomeCalendar *gcal, const char *uid) cal_alarm_instance_list_free (alarms); } +struct load_create_closure { + GnomeCalendar *gcal; + char *uri; +}; + +static void cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data); + +/* Connects to the cal_loaded signal of the client while creating the proper + * closure for the callback. + */ +static struct load_create_closure * +connect_load (GnomeCalendar *gcal, const char *uri) +{ + GnomeCalendarPrivate *priv; + struct load_create_closure *c; + + priv = gcal->priv; + + c = g_new (struct load_create_closure, 1); + c->gcal = gcal; + c->uri = g_strdup (uri); + + gtk_signal_connect (GTK_OBJECT (priv->client), "cal_loaded", + GTK_SIGNAL_FUNC (cal_loaded_cb), c); + + return c; +} + +/* Disconnects from the cal_loaded signal of the client; also frees the callback + * closure data. + */ +static void +disconnect_load (GnomeCalendar *gcal, struct load_create_closure *c) +{ + GnomeCalendarPrivate *priv; + + priv = gcal->priv; + + gtk_signal_disconnect_by_func (GTK_OBJECT (priv->client), + GTK_SIGNAL_FUNC (cal_loaded_cb), + c); + + g_free (c->uri); + g_free (c); +} + +/* Displays an error to indicate that loading a calendar failed */ +static void +load_error (GnomeCalendar *gcal, const char *uri) +{ + char *msg; + + msg = g_strdup_printf (_("Could not load the calendar in `%s'"), uri); + gnome_error_dialog_parented (msg, GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gcal)))); + g_free (msg); +} + +/* Displays an error to indicate that creating a calendar failed */ +static void +create_error (GnomeCalendar *gcal, const char *uri) +{ + char *msg; + + msg = g_strdup_printf (_("Could not create a calendar in `%s'"), uri); + gnome_error_dialog_parented (msg, GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gcal)))); + g_free (msg); +} + +/* Displays an error to indicate that the specified URI method is not supported */ +static void +method_error (GnomeCalendar *gcal, const char *uri) +{ + char *msg; + + msg = g_strdup_printf (_("The method required to load `%s' is not supported"), uri); + gnome_error_dialog_parented (msg, GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (gcal)))); + g_free (msg); +} + /* Callback from the calendar client when a calendar is loaded */ static void cal_loaded_cb (CalClient *client, CalClientLoadStatus status, gpointer data) { + struct load_create_closure *c; GnomeCalendar *gcal; GnomeCalendarPrivate *priv; + char *uri; - gcal = GNOME_CALENDAR (data); + c = data; + + gcal = c->gcal; + uri = g_strdup (c->uri); priv = gcal->priv; + disconnect_load (gcal, c); + c = NULL; + switch (priv->load_state) { + case LOAD_STATE_WAIT_LOAD: + if (status == CAL_CLIENT_LOAD_SUCCESS) { + priv->load_state = LOAD_STATE_LOADED; + initial_load (gcal); + } else if (status == CAL_CLIENT_LOAD_ERROR) { + priv->load_state = LOAD_STATE_NOT_LOADED; + load_error (gcal, uri); + } else if (status == CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED) { + priv->load_state = LOAD_STATE_NOT_LOADED; + method_error (gcal, uri); + } else + g_assert_not_reached (); + + break; + + case LOAD_STATE_WAIT_LOAD_BEFORE_CREATE: + if (status == CAL_CLIENT_LOAD_SUCCESS) { + priv->load_state = LOAD_STATE_LOADED; + initial_load (gcal); + } else if (status == CAL_CLIENT_LOAD_ERROR) { + priv->load_state = LOAD_STATE_WAIT_CREATE; + + c = connect_load (gcal, uri); + if (!cal_client_create_calendar (priv->client, uri)) { + priv->load_state = LOAD_STATE_NOT_LOADED; + disconnect_load (gcal, c); + c = NULL; + + g_message ("cal_loaded_cb(): Could not issue the create request"); + } + } else if (status == CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED) { + priv->load_state = LOAD_STATE_NOT_LOADED; + method_error (gcal, uri); + } else + g_assert_not_reached (); + + break; + + case LOAD_STATE_WAIT_CREATE: + if (status == CAL_CLIENT_LOAD_SUCCESS) { + priv->load_state = LOAD_STATE_LOADED; + initial_load (gcal); + } else if (status == CAL_CLIENT_LOAD_ERROR) { + priv->load_state = LOAD_STATE_NOT_LOADED; + create_error (gcal, uri); + } else if (status == CAL_CLIENT_LOAD_IN_USE) { + /* Someone created the URI while we were issuing the + * create request, so we just try to reload. + */ + priv->load_state = LOAD_STATE_WAIT_LOAD; + + c = connect_load (gcal, uri); + if (!cal_client_load_calendar (priv->client, uri)) { + priv->load_state = LOAD_STATE_NOT_LOADED; + disconnect_load (gcal, c); + c = NULL; + + g_message ("cal_loaded_cb(): Could not issue the load request"); + } + } else if (status == CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED) { + priv->load_state = LOAD_STATE_NOT_LOADED; + method_error (gcal, uri); + } else + g_assert_not_reached (); + + break; + default: - /* FIXME */ + g_assert_not_reached (); } + + g_free (uri); } /* Callback from the calendar client when an object is updated */ @@ -1172,8 +1332,6 @@ gnome_calendar_construct (GnomeCalendar *gcal) if (!priv->client) return NULL; - gtk_signal_connect (GTK_OBJECT (priv->client), "cal_loaded", - GTK_SIGNAL_FUNC (cal_loaded_cb), gcal); gtk_signal_connect (GTK_OBJECT (priv->client), "obj_updated", GTK_SIGNAL_FUNC (obj_updated_cb), gcal); gtk_signal_connect (GTK_OBJECT (priv->client), "obj_removed", @@ -1228,97 +1386,38 @@ gnome_calendar_get_cal_client (GnomeCalendar *gcal) return priv->client; } -typedef struct { - GnomeCalendar *gcal; - char *uri; - GnomeCalendarOpenMode gcom; - guint signal_handle; -} load_or_create_data; - - -static void -gnome_calendar_load_cb (CalClient *cal_client, - CalClientLoadStatus status, - load_or_create_data *locd) -{ -#if 0 - g_return_if_fail (locd); - g_return_if_fail (GNOME_IS_CALENDAR (locd->gcal)); - - switch (status) { - case CAL_CLIENT_LOAD_SUCCESS: - gnome_calendar_update_all (locd->gcal); - break; - - case CAL_CLIENT_LOAD_ERROR: - if (locd->gcom == CALENDAR_OPEN_OR_CREATE) { - /* FIXME: connect to the cal_loaded signal of the - * CalClient and get theasynchronous notification - * properly! */ - /*gtk_signal_connect (GTK_OBJECT (gcal->client), - "cal_loaded", - gnome_calendar_create_cb, gcal);*/ - - gtk_signal_disconnect (GTK_OBJECT (locd->gcal->client), - locd->signal_handle); - - cal_client_create_calendar (locd->gcal->client, - locd->uri); - gnome_calendar_update_all (locd->gcal); - } - break; - - case CAL_CLIENT_LOAD_IN_USE: - /* FIXME: what to do? */ - g_message ("gnome_calendar_load_cb: in use"); - break; - - case CAL_CLIENT_LOAD_METHOD_NOT_SUPPORTED: - /* FIXME: what to do? */ - g_message ("gnome_calendar_load_cb(): method not supported"); - break; - - default: - g_message ("gnome_calendar_load_cb(): unhandled result code %d!", (int) status); - g_assert_not_reached (); - } - - g_free (locd->uri); - g_free (locd); -#endif -} - - -int -gnome_calendar_open (GnomeCalendar *gcal, - char *file, - GnomeCalendarOpenMode gcom) +gboolean +gnome_calendar_open (GnomeCalendar *gcal, char *file, GnomeCalendarOpenMode gcom) { GnomeCalendarPrivate *priv; - load_or_create_data *locd; + struct load_create_closure *c; - g_return_val_if_fail (gcal != NULL, 0); - g_return_val_if_fail (GNOME_IS_CALENDAR (gcal), 0); - g_return_val_if_fail (file != NULL, 0); + g_return_val_if_fail (gcal != NULL, FALSE); + g_return_val_if_fail (GNOME_IS_CALENDAR (gcal), FALSE); + g_return_val_if_fail (file != NULL, FALSE); priv = gcal->priv; + g_return_val_if_fail (priv->load_state == LOAD_STATE_NOT_LOADED, FALSE); - locd = g_new0 (load_or_create_data, 1); - locd->gcal = gcal; - locd->uri = g_strdup (file); - locd->gcom = gcom; + c = connect_load (gcal, file); - locd->signal_handle = gtk_signal_connect (GTK_OBJECT (priv->client), - "cal_loaded", - gnome_calendar_load_cb, - locd); + if (gcom == CALENDAR_OPEN) + priv->load_state = LOAD_STATE_WAIT_LOAD; + else if (gcom == CALENDAR_OPEN_OR_CREATE) + priv->load_state = LOAD_STATE_WAIT_LOAD_BEFORE_CREATE; + else { + g_assert_not_reached (); + return FALSE; + } - if (cal_client_load_calendar (priv->client, file) == FALSE) { - g_message ("Error loading calendar: %s", file); - return 0; + if (!cal_client_load_calendar (priv->client, file)) { + priv->load_state = LOAD_STATE_NOT_LOADED; + disconnect_load (gcal, c); + g_message ("gnome_calendar_open(): Could not issue the request"); + return FALSE; } - return 1; + return TRUE; } #if 0 diff --git a/calendar/gui/gnome-cal.h b/calendar/gui/gnome-cal.h index 6201c0d524..53b547581e 100644 --- a/calendar/gui/gnome-cal.h +++ b/calendar/gui/gnome-cal.h @@ -44,8 +44,8 @@ struct _GnomeCalendarClass { typedef enum { - CALENDAR_OPEN, - CALENDAR_OPEN_OR_CREATE + CALENDAR_OPEN, + CALENDAR_OPEN_OR_CREATE } GnomeCalendarOpenMode; GtkType gnome_calendar_get_type (void); @@ -55,7 +55,7 @@ GtkWidget *gnome_calendar_new (void); CalClient *gnome_calendar_get_cal_client (GnomeCalendar *gcal); -int gnome_calendar_open (GnomeCalendar *gcal, +gboolean gnome_calendar_open (GnomeCalendar *gcal, char *file, GnomeCalendarOpenMode gcom); /* -- cgit v1.2.3