diff options
Diffstat (limited to 'calendar')
-rw-r--r-- | calendar/ChangeLog | 12 | ||||
-rw-r--r-- | calendar/gui/dialogs/comp-editor.c | 30 | ||||
-rw-r--r-- | calendar/gui/e-itip-control.c | 1496 | ||||
-rw-r--r-- | calendar/gui/e-itip-control.h | 87 | ||||
-rw-r--r-- | calendar/gui/itip-bonobo-control.c | 267 | ||||
-rw-r--r-- | calendar/gui/itip-bonobo-control.h | 30 | ||||
-rw-r--r-- | calendar/gui/itip-control-factory.c | 267 | ||||
-rw-r--r-- | calendar/gui/itip-control-factory.h | 30 | ||||
-rw-r--r-- | calendar/gui/main.c | 4 |
9 files changed, 1454 insertions, 769 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 4cdcb6fcad..989a227541 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,5 +1,17 @@ 2001-06-21 JP Rosevear <jpr@ximian.com> + * gui/main.c (main): update to new call + + * gui/e-itip-control.[hc]: break the widget bits out on their own + into a proper object, basic stuff seems to be working again + + * gui/itip-control-factory.c: put the control specific bits here + from e-itip-control.c + + * gui/itip-control-factory.h: new header + +2001-06-21 JP Rosevear <jpr@ximian.com> + * gui/dialogs/Makefile.am (gladedir): add include path * gui/dialogs/comp-editor.c (setup_widgets): remove buttons and diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c index 252d858e7f..d67ebc7919 100644 --- a/calendar/gui/dialogs/comp-editor.c +++ b/calendar/gui/dialogs/comp-editor.c @@ -97,9 +97,6 @@ static void print_preview_cmd (GtkWidget *widget, gpointer data); static void print_setup_cmd (GtkWidget *widget, gpointer data); static void close_cmd (GtkWidget *widget, gpointer data); -static void save_clicked_cb (GtkWidget *widget, gpointer data); -static void close_clicked_cb (GtkWidget *widget, gpointer data); -static void help_clicked_cb (GtkWidget *widget, gpointer data); static gint delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data); static EPixmap pixmaps [] = @@ -177,9 +174,6 @@ setup_widgets (CompEditor *editor) CompEditorPrivate *priv; BonoboUIContainer *container; GtkWidget *vbox; - GtkWidget *bbox; - GtkWidget *pixmap; - GtkWidget *button; priv = editor->priv; @@ -902,30 +896,6 @@ close_cmd (GtkWidget *widget, gpointer data) } static void -save_clicked_cb (GtkWidget *widget, gpointer data) -{ - CompEditor *editor = COMP_EDITOR (data); - - save_comp (editor); - close_dialog (editor); -} - -static void -close_clicked_cb (GtkWidget *widget, gpointer data) -{ - CompEditor *editor = COMP_EDITOR (data); - - if (prompt_to_save_changes (editor)) - close_dialog (editor); -} - -/* Button callbacks */ -static void -help_clicked_cb (GtkWidget *widget, gpointer data) -{ -} - -static void page_changed_cb (GtkWidget *widget, gpointer data) { CompEditor *editor = COMP_EDITOR (data); diff --git a/calendar/gui/e-itip-control.c b/calendar/gui/e-itip-control.c index cbd84c52e9..8363f11d2e 100644 --- a/calendar/gui/e-itip-control.c +++ b/calendar/gui/e-itip-control.c @@ -1,934 +1,994 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Evolution calendar - Control for displaying iTIP mail messages +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-itip-control.c * - * Copyright (C) 2000 Helix Code, Inc. - * Copyright (C) 2000 Ximian, Inc. + * Copyright (C) 2001 Ximian, Inc. * - * Author: Jesse Pavel <jpavel@ximian.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * Author: JP Rosevear */ +#ifdef HAVE_CONFIG_H #include <config.h> -#include <time.h> +#endif + #include <glib.h> -#include <gtk/gtkobject.h> -#include <gtk/gtkwidget.h> +#include <gtk/gtkmisc.h> #include <libgnome/gnome-defs.h> #include <libgnome/gnome-i18n.h> +#include <libgnome/gnome-util.h> +#include <libgnomeui/gnome-stock.h> #include <libgnomeui/gnome-dialog.h> #include <libgnomeui/gnome-dialog-util.h> -#include <bonobo/bonobo-generic-factory.h> -#include <bonobo/bonobo-persist-stream.h> -#include <bonobo/bonobo-stream-client.h> -#include <bonobo/bonobo-context.h> - -#include <glade/glade.h> #include <ical.h> -#include <Evolution-Composer.h> - -#include "e-itip-control.h" #include <cal-util/cal-component.h> #include <cal-client/cal-client.h> #include <e-util/e-time-utils.h> +#include <e-util/e-dialog-widgets.h> #include "calendar-config.h" #include "itip-utils.h" +#include "e-itip-control.h" -#define MAIL_COMPOSER_OAF_IID "OAFIID:GNOME_Evolution_Mail_Composer" +struct _EItipControlPrivate { + GtkWidget *summary; + GtkWidget *datetime; + GtkWidget *message; + GtkWidget *count; + GtkWidget *options; + GtkWidget *ok; + GtkWidget *next; + GtkWidget *prev; + + CalClient *event_client; + CalClient *task_client; -#define DEFAULT_WIDTH 400 -#define DEFAULT_HEIGHT 300 + char *vcalendar; + CalComponent *comp; + icalcomponent *main_comp; + icalcomponent *ical_comp; + icalcompiter iter; + icalproperty_method method; -extern gchar *evolution_dir; + const int *map; + int current; + int total; -typedef struct _EItipControlPrivate EItipControlPrivate; + gchar *from_address; + gchar *my_address; +}; -struct _EItipControlPrivate { - GladeXML *xml, *xml2; - GtkWidget *main_frame; - GtkWidget *organizer_entry, *dtstart_label, *dtend_label; - GtkWidget *summary_entry, *description_box, *message_text; - GtkWidget *button_box; - GtkWidget *address_entry; - GtkWidget *add_button; - GtkWidget *loading_window; - GtkWidget *loading_progress; - - icalcomponent *main_comp, *comp; - CalComponent *cal_comp; - char *vcalendar; - gchar *from_address, *my_address, *organizer; - icalparameter_partstat new_partstat; +/* Option menu maps */ +enum { + UPDATE_CALENDAR }; -enum E_ITIP_BONOBO_ARGS { - FROM_ADDRESS_ARG_ID, - MY_ADDRESS_ARG_ID +enum { + ACCEPT_TO_CALENDAR_RSVP, + ACCEPT_TO_CALENDAR, + TENTATIVE_TO_CALENDAR_RSVP, + TENTATIVE_TO_CALENDAR, + DECLINE_TO_CALENDAR_RSVP, + DECLINE_TO_CALENDAR }; +enum { + SEND_FREEBUSY +}; -/******** - * find_attendee() searches through the attendee properties of `comp' - * and returns the one the value of which is the same as `address' if such - * a property exists. Otherwise, it will return NULL. - ********/ -static icalproperty * -find_attendee (icalcomponent *comp, char *address) -{ - icalproperty *prop; - const char *attendee, *text; - icalvalue *value; - - for (prop = icalcomponent_get_first_property (comp, ICAL_ATTENDEE_PROPERTY); - prop != NULL; - prop = icalcomponent_get_next_property (comp, ICAL_ATTENDEE_PROPERTY)) - { - value = icalproperty_get_value (prop); - if (!value) - continue; +enum { + CANCEL_CALENDAR +}; - attendee = icalvalue_get_string (value); +static const int publish_map[] = { + UPDATE_CALENDAR, + -1 +}; - /* Here I strip off the "MAILTO:" if it is present. */ - text = strchr (attendee, ':'); - if (text != NULL) - text++; - else - text = attendee; +static const char *publish_text_map[] = { + "Update Calendar", + NULL +}; - if (strcmp (text, address) == 0) { - /* We have found the correct property. */ - break; - } - } - - return prop; -} +static const int request_map[] = { + ACCEPT_TO_CALENDAR_RSVP, + ACCEPT_TO_CALENDAR, + TENTATIVE_TO_CALENDAR_RSVP, + TENTATIVE_TO_CALENDAR, + DECLINE_TO_CALENDAR_RSVP, + DECLINE_TO_CALENDAR, + -1 +}; -static void -itip_control_destroy_cb (GtkObject *object, - gpointer data) -{ - EItipControlPrivate *priv = data; +static const char *request_text_map[] = { + "Accept and RSVP", + "Accept and do not RSVP", + "Tentatively accept and RSVP", + "Tentatively accept and do not RSVP", + "Decline and RSVP", + "Decline and do not RSVP", + NULL +}; - gtk_object_unref (GTK_OBJECT (priv->xml)); - gtk_object_unref (GTK_OBJECT (priv->xml2)); +static const int request_fb_map[] = { + SEND_FREEBUSY, + -1 +}; - if (priv->main_comp != NULL) { - if (priv->comp != NULL) - icalcomponent_remove_component (priv->main_comp, priv->comp); - - icalcomponent_free (priv->main_comp); - } +static const char *request_fb_text_map[] = { + "Send Free/Busy Information", + NULL +}; +static const int reply_map[] = { + UPDATE_CALENDAR, + -1 +}; - if (priv->cal_comp != NULL) { - gtk_object_unref (GTK_OBJECT (priv->cal_comp)); - } +static const char *reply_text_map[] = { + "Update Calendar", + NULL +}; - if (priv->from_address != NULL) - g_free (priv->from_address); - - if (priv->organizer != NULL) - g_free (priv->organizer); +static const int cancel_map[] = { + CANCEL_CALENDAR, + -1 +}; - if (priv->vcalendar != NULL) - g_free (priv->vcalendar); +static const char *cancel_text_map[] = { + "Cancel", + NULL +}; - g_free (priv); -} - +static void class_init (EItipControlClass *klass); +static void init (EItipControl *itip); +static void destroy (GtkObject *obj); -static void -cal_opened_cb (CalClient *client, CalClientOpenStatus status, gpointer data) -{ - EItipControlPrivate *priv = data; +static void prev_clicked_cb (GtkWidget *widget, gpointer data); +static void next_clicked_cb (GtkWidget *widget, gpointer data); +static void ok_clicked_cb (GtkWidget *widget, gpointer data); - gtk_widget_hide (priv->loading_progress); +static GtkVBoxClass *parent_class = NULL; - if (status == CAL_CLIENT_OPEN_SUCCESS) { - if (cal_client_update_object (client, priv->cal_comp) == FALSE) { - GtkWidget *dialog; - - dialog = gnome_warning_dialog(_("I couldn't update your calendar file!\n")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - } else { - /* We have success. */ - GtkWidget *dialog; - - dialog = gnome_ok_dialog(_("Component successfully updated.")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - } - } else { - GtkWidget *dialog; - dialog = gnome_ok_dialog(_("There was an error loading the calendar file.")); - gnome_dialog_run (GNOME_DIALOG(dialog)); +GtkType +e_itip_control_get_type (void) +{ + static GtkType type = 0; + + if (type == 0) { + static const GtkTypeInfo info = + { + "EItipControl", + sizeof (EItipControl), + sizeof (EItipControlClass), + (GtkClassInitFunc) class_init, + (GtkObjectInitFunc) init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + type = gtk_type_unique (gtk_vbox_get_type (), &info); } - gtk_object_unref (GTK_OBJECT (client)); - return; + return type; } static void -update_calendar (EItipControlPrivate *priv) +class_init (EItipControlClass *klass) { - gchar cal_uri[255]; - CalClient *client; + GtkObjectClass *object_class; - snprintf (cal_uri, 250, "%s/local/Calendar/calendar.ics", evolution_dir); - - client = cal_client_new (); - - gtk_signal_connect (GTK_OBJECT (client), "cal_opened", - GTK_SIGNAL_FUNC (cal_opened_cb), priv); - - if (cal_client_open_calendar (client, cal_uri, FALSE) == FALSE) { - GtkWidget *dialog; - - dialog = gnome_warning_dialog(_("I couldn't open your calendar file!\n")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - gtk_object_unref (GTK_OBJECT (client)); - - return; - } + object_class = GTK_OBJECT_CLASS (klass); - gtk_progress_bar_update (GTK_PROGRESS_BAR (priv->loading_progress), 0.5); - gtk_widget_show (priv->loading_progress); + parent_class = gtk_type_class (gtk_vbox_get_type ()); - return; + object_class->destroy = destroy; } + +/* Calendar Server routines */ static void -add_button_clicked_cb (GtkWidget *widget, gpointer data) +start_calendar_server_cb (CalClient *cal_client, + CalClientOpenStatus status, + gpointer data) { - EItipControlPrivate *priv = data; + gboolean *success = data; - update_calendar (priv); + if (status == CAL_CLIENT_OPEN_SUCCESS) + *success = TRUE; + else + *success = FALSE; - return; + gtk_main_quit (); /* end the sub event loop */ } -static void -change_my_status (icalparameter_partstat status, EItipControlPrivate *priv) +static CalClient * +start_calendar_server (gchar *uri) { - icalproperty *prop; + CalClient *client; + gchar *filename; + gboolean success; + + client = cal_client_new (); - prop = find_attendee (priv->comp, priv->my_address); - if (prop) { - icalparameter *param; + /* FIX ME */ + filename = g_concat_dir_and_file (g_get_home_dir (), uri); - icalproperty_remove_parameter (prop, ICAL_PARTSTAT_PARAMETER); - param = icalparameter_new_partstat (status); - icalproperty_add_parameter (prop, param); - } -} + gtk_signal_connect (GTK_OBJECT (client), "cal_opened", + start_calendar_server_cb, &success); -static void -accept_button_clicked_cb (GtkWidget *widget, gpointer data) -{ - EItipControlPrivate *priv = data; + if (!cal_client_open_calendar (client, filename, FALSE)) + return NULL; - change_my_status (ICAL_PARTSTAT_ACCEPTED, priv); - itip_send_comp (CAL_COMPONENT_METHOD_REPLY, priv->cal_comp); - update_calendar (priv); - - return; + /* run a sub event loop to turn cal-client's async load + notification into a synchronous call */ + gtk_main (); + + if (success) + return client; + + return NULL; } static void -tentative_button_clicked_cb (GtkWidget *widget, gpointer data) +init (EItipControl *itip) { - EItipControlPrivate *priv = data; - - change_my_status (ICAL_PARTSTAT_TENTATIVE, priv); - itip_send_comp (CAL_COMPONENT_METHOD_REPLY, priv->cal_comp); - update_calendar (priv); + EItipControlPrivate *priv; + GtkWidget *hbox, *table, *lbl; - return; + priv = g_new0 (EItipControlPrivate, 1); + + itip->priv = priv; + + /* Header */ + priv->count = gtk_label_new ("0 of 0"); + gtk_widget_show (priv->count); + priv->prev = gnome_stock_button (GNOME_STOCK_BUTTON_PREV); + gtk_widget_show (priv->prev); + priv->next = gnome_stock_button (GNOME_STOCK_BUTTON_NEXT); + gtk_widget_show (priv->next); + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), priv->prev, FALSE, FALSE, 4); + gtk_box_pack_start (GTK_BOX (hbox), priv->count, TRUE, TRUE, 4); + gtk_box_pack_start (GTK_BOX (hbox), priv->next, FALSE, FALSE, 4); + gtk_widget_show (hbox); + + gtk_box_pack_start (GTK_BOX (itip), hbox, FALSE, FALSE, 4); + + gtk_signal_connect (GTK_OBJECT (priv->prev), "clicked", + GTK_SIGNAL_FUNC (prev_clicked_cb), itip); + gtk_signal_connect (GTK_OBJECT (priv->next), "clicked", + GTK_SIGNAL_FUNC (next_clicked_cb), itip); + + /* Information */ + table = gtk_table_new (1, 3, FALSE); + gtk_widget_show (table); + + lbl = gtk_label_new (_("Summary:")); + gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.0); + gtk_widget_show (lbl); + gtk_table_attach (GTK_TABLE (table), lbl, 0, 1, 0, 1, + GTK_EXPAND & GTK_FILL, GTK_SHRINK, 4, 0); + priv->summary = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (priv->summary), 0.0, 0.5); + gtk_widget_show (priv->summary); + gtk_table_attach (GTK_TABLE (table), priv->summary, 1, 2, 0, 1, + GTK_EXPAND & GTK_FILL, GTK_EXPAND, 4, 0); + + lbl = gtk_label_new (_("Date/Time:")); + gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5); + gtk_widget_show (lbl); + gtk_table_attach (GTK_TABLE (table), lbl, 0, 1, 1, 2, + GTK_EXPAND, GTK_SHRINK, 4, 0); + priv->datetime = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (priv->datetime), 0.0, 0.5); + gtk_widget_show (priv->datetime); + gtk_table_attach (GTK_TABLE (table), priv->datetime, 1, 2, 1, 2, + GTK_EXPAND & GTK_FILL, GTK_EXPAND, 4, 0); + + priv->message = gtk_label_new (""); + gtk_label_set_line_wrap (GTK_LABEL (priv->message), TRUE); + gtk_widget_show (priv->message); + gtk_table_attach (GTK_TABLE (table), priv->message, 0, 2, 2, 3, + GTK_EXPAND & GTK_FILL, GTK_EXPAND & GTK_FILL, 4, 0); + + gtk_box_pack_start (GTK_BOX (itip), table, FALSE, FALSE, 4); + + /* Actions */ + priv->options = gtk_option_menu_new (); + gtk_widget_show (priv->options); + priv->ok = gnome_stock_button (GNOME_STOCK_BUTTON_OK); + gtk_widget_show (priv->ok); + + hbox = hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), priv->options, TRUE, TRUE, 4); + gtk_box_pack_start (GTK_BOX (hbox), priv->ok, FALSE, FALSE, 4); + gtk_widget_show (hbox); + + gtk_signal_connect (GTK_OBJECT (priv->ok), "clicked", + GTK_SIGNAL_FUNC (ok_clicked_cb), itip); + + gtk_box_pack_start (GTK_BOX (itip), hbox, FALSE, FALSE, 4); + + /* Get the cal clients */ + priv->event_client = start_calendar_server ("evolution/local/Calendar/calendar.ics"); + if (priv->event_client == NULL) + g_warning ("Unable to start calendar client"); + priv->task_client = start_calendar_server ("evolution/local/Tasks/tasks.ics"); + g_warning ("Unable to start calendar client"); } static void -decline_button_clicked_cb (GtkWidget *widget, gpointer data) +destroy (GtkObject *obj) { - EItipControlPrivate *priv = data; + EItipControl *itip = E_ITIP_CONTROL (obj); + EItipControlPrivate *priv; - change_my_status (ICAL_PARTSTAT_DECLINED, priv); - itip_send_comp (CAL_COMPONENT_METHOD_REPLY, priv->cal_comp); - - return; + priv = itip->priv; + + g_free (priv); } +GtkWidget * +e_itip_control_new (void) +{ + return gtk_type_new (E_TYPE_ITIP_CONTROL); +} -/******** - * load_calendar_store() opens and loads the calendar referred to by cal_uri - * and sets cal_client as a client for that store. If cal_uri is NULL, - * we load the default calendar URI. If all goes well, it returns TRUE; - * otherwise, it returns FALSE. - ********/ -static gboolean -load_calendar_store (char *cal_uri, CalClient **cal_client) +static icalproperty * +find_attendee (icalcomponent *ical_comp, char *address) { - char uri_buf[255]; - char *uri; + icalproperty *prop; + const char *attendee, *text; + icalvalue *value; - if (cal_uri == NULL) { - snprintf (uri_buf, 250, "%s/local/Calendar/calendar.ics", evolution_dir); - uri = uri_buf; - } - else { - uri = cal_uri; - } + g_return_val_if_fail (address != NULL, NULL); - *cal_client = cal_client_new (); - if (cal_client_open_calendar (*cal_client, uri, FALSE) == FALSE) { - return FALSE; - } + for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY); + prop != NULL; + prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY)) + { + value = icalproperty_get_value (prop); + if (!value) + continue; - /* FIXME!!!!!! This is fucking ugly. */ + attendee = icalvalue_get_string (value); - while (!cal_client_get_load_state (*cal_client) != CAL_CLIENT_LOAD_LOADED) { - gtk_main_iteration_do (FALSE); /* Do a non-blocking iteration. */ - usleep (200000L); /* Pause for 1/5th of a second before checking again.*/ - } + /* Here I strip off the "MAILTO:" if it is present. */ + text = strchr (attendee, ':'); + if (text != NULL) + text++; + else + text = attendee; - return TRUE; + if (!strstr (text, address)) + break; + } + + return prop; } - static void -update_reply_cb (GtkWidget *widget, gpointer data) +set_label (EItipControl *itip) { - EItipControlPrivate *priv = data; - CalClient *cal_client; - CalComponent *cal_comp; - icalcomponent *comp; - icalproperty *prop; - icalparameter *param; - const char *uid; - - if (load_calendar_store (NULL, &cal_client) == FALSE) { - GtkWidget *dialog; - - dialog = gnome_warning_dialog(_("I couldn't load your calendar file!\n")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - gtk_object_unref (GTK_OBJECT (cal_client)); + EItipControlPrivate *priv; + gchar *text; - return; - } + priv = itip->priv; + text = g_strdup_printf ("%d of %d", priv->current, priv->total); + gtk_label_set_text (GTK_LABEL (priv->count), text); - cal_component_get_uid (priv->cal_comp, &uid); - if (cal_client_get_object (cal_client, uid, &cal_comp) != CAL_CLIENT_GET_SUCCESS) { - GtkWidget *dialog; - - dialog = gnome_warning_dialog(_("I couldn't read your calendar file!\n")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - gtk_object_unref (GTK_OBJECT (cal_client)); - - return; - } +} - comp = cal_component_get_icalcomponent (cal_comp); +static void +set_button_status (EItipControl *itip) +{ + EItipControlPrivate *priv; - prop = find_attendee (comp, priv->from_address); - if (!prop) { - GtkWidget *dialog; + priv = itip->priv; - dialog = gnome_warning_dialog(_("This is a reply from someone who was uninvited!")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - gtk_object_unref (GTK_OBJECT (cal_client)); - gtk_object_unref (GTK_OBJECT (cal_comp)); - - return; - } - - icalproperty_remove_parameter (prop, ICAL_PARTSTAT_PARAMETER); - param = icalparameter_new_partstat (priv->new_partstat); - icalproperty_add_parameter (prop, param); + if (priv->current == priv->total) + gtk_widget_set_sensitive (priv->next, FALSE); + else + gtk_widget_set_sensitive (priv->next, TRUE); - /* Now we need to update the object in the calendar store. */ - if (!cal_client_update_object (cal_client, cal_comp)) { - GtkWidget *dialog; + if (priv->current == 1) + gtk_widget_set_sensitive (priv->prev, FALSE); + else + gtk_widget_set_sensitive (priv->prev, TRUE); +} - dialog = gnome_warning_dialog(_("I couldn't update your calendar store.")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - gtk_object_unref (GTK_OBJECT (cal_client)); - gtk_object_unref (GTK_OBJECT (cal_comp)); +static GtkWidget * +create_menu (const char **map) +{ + GtkWidget *menu, *item; + int i; - return; - } - else { - /* We have success. */ - GtkWidget *dialog; + menu = gtk_menu_new (); - dialog = gnome_ok_dialog(_("Component successfully updated.")); - gnome_dialog_run (GNOME_DIALOG(dialog)); + for (i = 0; map[i] != NULL; i++) { + item = gtk_menu_item_new_with_label (map[i]); + gtk_widget_show (item); + gtk_menu_append (GTK_MENU (menu), item); } - + gtk_widget_show (menu); - gtk_object_unref (GTK_OBJECT (cal_client)); - gtk_object_unref (GTK_OBJECT (cal_comp)); + return menu; } static void -cancel_meeting_cb (GtkWidget *widget, gpointer data) +set_options (EItipControl *itip) { - EItipControlPrivate *priv = data; - CalClient *cal_client; - const char *uid; - - if (load_calendar_store (NULL, &cal_client) == FALSE) { - GtkWidget *dialog; - - dialog = gnome_warning_dialog(_("I couldn't load your calendar file!\n")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - gtk_object_unref (GTK_OBJECT (cal_client)); + EItipControlPrivate *priv; + gboolean sens = TRUE; - return; + priv = itip->priv; + + switch (priv->method) { + case ICAL_METHOD_PUBLISH: + priv->map = publish_map; + gtk_option_menu_set_menu (GTK_OPTION_MENU (priv->options), + create_menu (publish_text_map)); + break; + case ICAL_METHOD_REQUEST: + priv->map = request_map; + gtk_option_menu_set_menu (GTK_OPTION_MENU (priv->options), + create_menu (request_text_map)); + break; + case ICAL_METHOD_REPLY: + priv->map = reply_map; + gtk_option_menu_set_menu (GTK_OPTION_MENU (priv->options), + create_menu (reply_text_map)); + break; + case ICAL_METHOD_CANCEL: + priv->map = cancel_map; + gtk_option_menu_set_menu (GTK_OPTION_MENU (priv->options), + create_menu (cancel_text_map)); + break; + default: + priv->map = NULL; + gtk_option_menu_remove_menu (GTK_OPTION_MENU (priv->options)); + sens = FALSE; } - cal_component_get_uid (priv->cal_comp, &uid); - if (cal_client_remove_object (cal_client, uid) == FALSE) { - GtkWidget *dialog; + gtk_widget_set_sensitive (priv->options, sens); + gtk_widget_set_sensitive (priv->ok, sens); +} - dialog = gnome_warning_dialog(_("I couldn't delete the calendar component!\n")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - gtk_object_unref (GTK_OBJECT (cal_client)); + +static void +set_options_freebusy (EItipControl *itip) +{ + EItipControlPrivate *priv; + gboolean sens = TRUE; - return; + priv = itip->priv; + + switch (priv->method) { + case ICAL_METHOD_REQUEST: + priv->map = request_fb_map; + gtk_option_menu_set_menu (GTK_OPTION_MENU (priv->options), + create_menu (request_fb_text_map)); + break; + default: + priv->map = NULL; + gtk_option_menu_remove_menu (GTK_OPTION_MENU (priv->options)); + sens = FALSE; } - else { - /* We have success! */ - GtkWidget *dialog; - dialog = gnome_ok_dialog(_("Component successfully deleted.")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - } - + gtk_widget_set_sensitive (priv->options, sens); + gtk_widget_set_sensitive (priv->ok, sens); } +static void +write_label_piece (time_t t, char *buffer, int size, char *stext, char *etext) +{ + struct tm *tmp_tm; + int len; + + tmp_tm = localtime (&t); + if (stext != NULL) + strcat (buffer, stext); + len = strlen (buffer); + e_time_format_date_and_time (tmp_tm, + calendar_config_get_24_hour_format (), + FALSE, FALSE, + &buffer[len], size - len); + if (etext != NULL) + strcat (buffer, etext); +} -/* - * Bonobo::PersistStream - * - * These two functions implement the Bonobo::PersistStream load and - * save methods which allow data to be loaded into and out of the - * BonoboObject. - */ - -static char * -stream_read (Bonobo_Stream stream) +static void +set_date_label (GtkWidget *lbl, CalComponent *comp) { - Bonobo_Stream_iobuf *buffer; - CORBA_Environment ev; - gchar *data = NULL; - gint length = 0; - - CORBA_exception_init (&ev); - do { -#define READ_CHUNK_SIZE 65536 - Bonobo_Stream_read (stream, READ_CHUNK_SIZE, - &buffer, &ev); + CalComponentDateTime datetime; + time_t start = 0, end = 0, complete = 0, due = 0; + static char buffer[1024]; + + cal_component_get_dtstart (comp, &datetime); + if (datetime.value) + start = icaltime_as_timet (*datetime.value); + cal_component_get_dtend (comp, &datetime); + if (datetime.value) + end = icaltime_as_timet (*datetime.value); + cal_component_get_due (comp, &datetime); + if (datetime.value) + due = icaltime_as_timet (*datetime.value); + cal_component_get_completed (comp, &datetime.value); + if (datetime.value) + complete = icaltime_as_timet (*datetime.value); + + buffer[0] = '\0'; + + if (start > 0) + write_label_piece (start, buffer, 1024, NULL, NULL); + + if (end > 0 && start > 0) + write_label_piece (end, buffer, 1024, _(" to "), NULL); + + if (complete > 0) { + if (start > 0) + write_label_piece (complete, buffer, 1024, _(" (Completed "), ")"); + else + write_label_piece (complete, buffer, 1024, _("Completed "), NULL); + } + + if (due > 0 && complete == 0) { + if (start > 0) + write_label_piece (due, buffer, 1024, _(" (Due "), ")"); + else + write_label_piece (due, buffer, 1024, _("Due "), NULL); + } - if (ev._major != CORBA_NO_EXCEPTION) { - CORBA_exception_free (&ev); - return NULL; - } + gtk_label_set_text (GTK_LABEL (lbl), buffer); +} - if (buffer->_length <= 0) - break; +static void +set_message (EItipControl *itip, gchar *message, gboolean err) +{ + EItipControlPrivate *priv; + GtkStyle *style = NULL; + + priv = itip->priv; - data = g_realloc (data, - length + buffer->_length); + if (err) { + GdkColor color = {0, 65535, 0, 0}; + + style = gtk_style_copy (gtk_widget_get_style (priv->message)); + style->fg[0] = color; + gtk_widget_set_style (priv->message, style); + } else { + gtk_widget_restore_default_style (priv->message); + } - memcpy (data + length, - buffer->_buffer, buffer->_length); + if (message != NULL) + gtk_label_set_text (GTK_LABEL (priv->message), message); + else + gtk_label_set_text (GTK_LABEL (priv->message), ""); - length += buffer->_length; + if (err) { + gtk_style_unref (style); + } +} - CORBA_free (buffer); -#undef READ_CHUNK_SIZE - } while (1); +static void +show_current_event (EItipControl *itip) +{ + EItipControlPrivate *priv; + CalComponentText text; + + priv = itip->priv; - CORBA_free (buffer); - CORBA_exception_free (&ev); + set_options (itip); + + cal_component_get_summary (priv->comp, &text); + if (text.value) + gtk_label_set_text (GTK_LABEL (priv->summary), text.value); + else + gtk_label_set_text (GTK_LABEL (priv->summary), ""); - if (data == NULL) - data = g_strdup(""); + set_date_label (priv->datetime, priv->comp); - return data; -} /* stream_read */ + switch (priv->method) { + case ICAL_METHOD_PUBLISH: + set_message (itip, _("This is an event that can be added to your calendar."), FALSE); + break; + case ICAL_METHOD_REQUEST: + set_message (itip, _("This is a meeting request."), FALSE); + break; + case ICAL_METHOD_ADD: + set_message (itip, _("This is one or more additions to a current meeting."), FALSE); + break; + case ICAL_METHOD_REFRESH: + set_message (itip, _("This is a request for the latest event information."), FALSE); + break; + case ICAL_METHOD_REPLY: + set_message (itip, _("This is a reply to a meeting request."), FALSE); + break; + case ICAL_METHOD_CANCEL: + set_message (itip, _("This is an event cancellation."), FALSE); + break; + default: + set_message (itip, _("The message is not understandable."), TRUE); + } +} -/* - * This function implements the Bonobo::PersistStream:load method. - */ static void -pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream, - Bonobo_Persist_ContentType type, void *data, - CORBA_Environment *ev) +show_current_todo (EItipControl *itip) { - EItipControlPrivate *priv = data; + EItipControlPrivate *priv; CalComponentText text; - CalComponentDateTime datetime; - CalComponentOrganizer organizer; - icalproperty *prop; - GSList *list, *l; - time_t t; - gint pos = 0; - icalcompiter iter; - icalcomponent_kind comp_kind; - char message[256]; + priv = itip->priv; - if (type && g_strcasecmp (type, "text/calendar") != 0 && - g_strcasecmp (type, "text/x-calendar") != 0) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_Bonobo_Persist_WrongDataType, NULL); - return; - } - - if ((priv->vcalendar = stream_read (stream)) == NULL) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_Bonobo_Persist_FileNotFound, NULL); - return; - } + set_options (itip); + + cal_component_get_summary (priv->comp, &text); + if (text.value) + gtk_label_set_text (GTK_LABEL (priv->summary), text.value); + else + gtk_label_set_text (GTK_LABEL (priv->summary), ""); - /* Do something with the data, here. */ + set_date_label (priv->datetime, priv->comp); - priv->main_comp = icalparser_parse_string (priv->vcalendar); - if (priv->main_comp == NULL) { - g_printerr ("e-itip-control.c: the iCalendar data was invalid!\n"); - return; + switch (priv->method) { + case ICAL_METHOD_PUBLISH: + set_message (itip, _("This is an task that can be added to your calendar."), FALSE); + break; + case ICAL_METHOD_REQUEST: + set_message (itip, _("This is a task request."), FALSE); + break; + case ICAL_METHOD_REFRESH: + set_message (itip, _("This is a request for the latest task information."), FALSE); + break; + case ICAL_METHOD_REPLY: + set_message (itip, _("This is a reply to a task request."), FALSE); + break; + case ICAL_METHOD_CANCEL: + set_message (itip, _("This is an task cancellation."), FALSE); + break; + default: + set_message (itip, _("The message is not understandable."), TRUE); } +} - iter = icalcomponent_begin_component (priv->main_comp, ICAL_ANY_COMPONENT); - priv->comp = icalcompiter_deref (&iter); +static void +show_current_freebusy (EItipControl *itip) +{ + EItipControlPrivate *priv; + + priv = itip->priv; - { - FILE *fp; + set_options_freebusy (itip); + + gtk_label_set_text (GTK_LABEL (priv->summary), ""); - fp = fopen ("/tmp/evo.debug", "w"); + set_date_label (priv->datetime, priv->comp); - fputs ("The raw vCalendar data:\n\n", fp); - fputs (priv->vcalendar, fp); + switch (priv->method) { + case ICAL_METHOD_PUBLISH: + set_message (itip, _("This is freebusy information."), FALSE); + break; + case ICAL_METHOD_REQUEST: + set_message (itip, _("This is a request for freebusy information."), FALSE); + break; + case ICAL_METHOD_REPLY: + set_message (itip, _("This is a reply to a freebusy request."), FALSE); + break; + default: + set_message (itip, _("The message is not understandable."), TRUE); + } +} - fputs ("The main component:\n\n", fp); - fputs (icalcomponent_as_ical_string (priv->main_comp), fp); +static void +show_current (EItipControl *itip) +{ + EItipControlPrivate *priv; + CalComponentVType type; - fputs ("The child component:\n\n", fp); - fputs (icalcomponent_as_ical_string (priv->comp), fp); + priv = itip->priv; - fclose (fp); - } + set_label (itip); + set_button_status (itip); - if (priv->comp == NULL) { - g_printerr ("e-itip-control.c: I could not extract a proper component from\n" - " the vCalendar data.\n"); - icalcomponent_free (priv->main_comp); + if (priv->comp) + gtk_object_unref (GTK_OBJECT (priv->comp)); + + priv->comp = cal_component_new (); + if (!cal_component_set_icalcomponent (priv->comp, priv->ical_comp)) { + set_message (itip, _("The message does not appear to be properly formed"), TRUE); + gtk_object_unref (GTK_OBJECT (priv->comp)); + priv->comp = NULL; return; - } + }; - comp_kind = icalcomponent_isa (priv->comp); + type = cal_component_get_vtype (priv->comp); - switch (comp_kind) { - case ICAL_VEVENT_COMPONENT: - case ICAL_VTODO_COMPONENT: - case ICAL_VJOURNAL_COMPONENT: - priv->cal_comp = cal_component_new (); - if (cal_component_set_icalcomponent (priv->cal_comp, priv->comp) == FALSE) { - g_printerr ("e-itip-control.c: I couldn't create a CalComponent from the iTip data.\n"); - gtk_object_unref (GTK_OBJECT (priv->cal_comp)); - } + switch (type) { + case CAL_COMPONENT_EVENT: + show_current_event (itip); break; - case ICAL_VFREEBUSY_COMPONENT: - /* Take care of busy time information. */ - return; + case CAL_COMPONENT_TODO: + show_current_todo (itip); + break; + case CAL_COMPONENT_FREEBUSY: + show_current_freebusy (itip); break; default: - /* We don't know what this is, so bail. */ - { - GtkWidget *dialog; - - dialog = gnome_warning_dialog(_("I don't recognize this type of calendar component.")); - gnome_dialog_run (GNOME_DIALOG(dialog)); - - g_free (priv->vcalendar); - priv->vcalendar = NULL; - - return; + set_message (itip, _("The message contains only unsupported requests."), TRUE); } - break; - } /* End switch. */ +} +void +e_itip_control_set_data (EItipControl *itip, const gchar *text) +{ + EItipControlPrivate *priv; + icalproperty *prop; - /* Fill in the gui */ - cal_component_get_organizer (priv->cal_comp, &organizer); - priv->organizer = g_strdup (organizer.value); - gtk_entry_set_text (GTK_ENTRY (priv->organizer_entry), priv->organizer); + priv = itip->priv; - cal_component_get_summary (priv->cal_comp, &text); - gtk_entry_set_text (GTK_ENTRY (priv->summary_entry), text.value); - - cal_component_get_description_list (priv->cal_comp, &list); - for (l = list; l != NULL; l = l->next) { - text = *((CalComponentText *)l->data); + priv->vcalendar = g_strdup (text); + + priv->main_comp = icalparser_parse_string (priv->vcalendar); + if (priv->main_comp == NULL) { + set_message (itip, _("The information contained in this attachment was not valid"), TRUE); + priv->comp = NULL; + priv->total = 0; + priv->current = 0; + goto show; - gtk_editable_insert_text (GTK_EDITABLE (priv->description_box), - text.value, strlen (text.value), &pos); } - cal_component_free_text_list (list); + + prop = icalcomponent_get_first_property (priv->main_comp, ICAL_METHOD_PROPERTY); + priv->method = icalproperty_get_method (prop); + + priv->iter = icalcomponent_begin_component (priv->main_comp, ICAL_ANY_COMPONENT); + priv->ical_comp = icalcompiter_deref (&priv->iter); - cal_component_get_dtstart (priv->cal_comp, &datetime); - t = icaltime_as_timet (*datetime.value); - e_time_format_date_and_time (localtime (&t), - calendar_config_get_24_hour_format (), - FALSE, FALSE, message, sizeof (message)); - gtk_label_set_text (GTK_LABEL (priv->dtstart_label), message); + priv->total = icalcomponent_count_components (priv->main_comp, ICAL_VEVENT_COMPONENT); + priv->total += icalcomponent_count_components (priv->main_comp, ICAL_VTODO_COMPONENT); + priv->total += icalcomponent_count_components (priv->main_comp, ICAL_VFREEBUSY_COMPONENT); - cal_component_get_dtend (priv->cal_comp, &datetime); - t = icaltime_as_timet (*datetime.value); - e_time_format_date_and_time (localtime (&t), - calendar_config_get_24_hour_format (), - FALSE, FALSE, message, sizeof (message)); - gtk_label_set_text (GTK_LABEL (priv->dtend_label), message); + if (priv->total > 0) + priv->current = 1; + else + priv->current = 0; - /* Clear out any old-assed text that's been lying around in my message box. */ - gtk_editable_delete_text (GTK_EDITABLE (priv->message_text), 0, -1); + show: + show_current (itip); +} + +gchar * +e_itip_control_get_data (EItipControl *itip) +{ + EItipControlPrivate *priv; + + priv = itip->priv; -#if 0 - prop = icalcomponent_get_first_property (priv->comp, ICAL_ORGANIZER_PROPERTY); - if (prop) { - organizer = icalproperty_get_organizer (prop); - - /* Here I strip off the "MAILTO:" if it is present. */ - new_text = strchr (organizer, ':'); - if (new_text != NULL) - new_text++; - else - new_text = organizer; + return g_strdup (priv->vcalendar); +} - priv->organizer = g_strdup (new_text); - gtk_entry_set_text (GTK_ENTRY (priv->organizer_entry), new_text); - } -#endif +gint +e_itip_control_get_data_size (EItipControl *itip) +{ + EItipControlPrivate *priv; - prop = icalcomponent_get_first_property (priv->main_comp, ICAL_METHOD_PROPERTY); - switch (icalproperty_get_method (prop)) { - case ICAL_METHOD_PUBLISH: - { - GtkWidget *button; + priv = itip->priv; + + if (priv->vcalendar == NULL) + return 0; + + return strlen (priv->vcalendar); +} - snprintf (message, 250, "%s has published calendar information, " - "which you can add to your own calendar. " - "No reply is necessary.", - priv->from_address); - - button = gtk_button_new_with_label (_("Add to Calendar")); - gtk_box_pack_start (GTK_BOX (priv->button_box), button, FALSE, FALSE, 3); - gtk_widget_show (button); +void +e_itip_control_set_from_address (EItipControl *itip, const gchar *address) +{ + EItipControlPrivate *priv; - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (add_button_clicked_cb), priv); - - break; - } - case ICAL_METHOD_REQUEST: - { - /* I'll check if I have to rsvp. */ - icalproperty *prop; - icalparameter *param; - int rsvp = FALSE; + priv = itip->priv; - prop = find_attendee (priv->comp, priv->my_address); - if (prop) { - param = get_icalparam_by_type (prop, ICAL_RSVP_PARAMETER); + if (priv->from_address) + g_free (priv->from_address); - if (param) { - if (icalparameter_get_rsvp (param)) - rsvp = TRUE; - } - } + priv->from_address = g_strdup (address); +} - snprintf (message, 250, "This is a meeting organized by %s, " - "who indicated that you %s RSVP.", - (priv->organizer ? priv->organizer : "an unknown person"), - (rsvp ? "should" : "don't have to") ); +const gchar * +e_itip_control_get_from_address (EItipControl *itip) +{ + EItipControlPrivate *priv; - if (rsvp) { - GtkWidget *accept_button, *decline_button, *tentative_button; + priv = itip->priv; - accept_button = gtk_button_new_with_label (_(" Accept ")); - decline_button = gtk_button_new_with_label (_(" Decline ")); - tentative_button = gtk_button_new_with_label (_(" Tentative ")); + return priv->from_address; +} - gtk_box_pack_start (GTK_BOX (priv->button_box), decline_button, FALSE, FALSE, 3); - gtk_box_pack_end (GTK_BOX (priv->button_box), accept_button, FALSE, FALSE, 3); - gtk_box_pack_end (GTK_BOX (priv->button_box), tentative_button, FALSE, FALSE, 3); - gtk_signal_connect (GTK_OBJECT (accept_button), "clicked", - GTK_SIGNAL_FUNC (accept_button_clicked_cb), priv); - gtk_signal_connect (GTK_OBJECT (tentative_button), "clicked", - GTK_SIGNAL_FUNC (tentative_button_clicked_cb), priv); - gtk_signal_connect (GTK_OBJECT (decline_button), "clicked", - GTK_SIGNAL_FUNC (decline_button_clicked_cb), priv); +void +e_itip_control_set_my_address (EItipControl *itip, const gchar *address) +{ + EItipControlPrivate *priv; - gtk_widget_show (accept_button); - gtk_widget_show (tentative_button); - gtk_widget_show (decline_button); - } + priv = itip->priv; - } - break; - case ICAL_METHOD_REPLY: - { - icalproperty *prop; - icalparameter *param; - gboolean success = FALSE; - - prop = find_attendee (priv->comp, priv->from_address); - if (prop) { - param = get_icalparam_by_type (prop, ICAL_PARTSTAT_PARAMETER); - if (param) { - success = TRUE; + if (priv->my_address) + g_free (priv->my_address); + + priv->my_address = g_strdup (address); +} - priv->new_partstat = icalparameter_get_partstat (param); - } - } +const gchar * +e_itip_control_get_my_address (EItipControl *itip) +{ + EItipControlPrivate *priv; - if (!success) { - snprintf (message, 250, "%s sent a reply to a meeting request, but " - "the reply is not properly formed.", - priv->from_address); - } - else { - GtkWidget *button; - - button = gtk_button_new_with_label (_("Update Calendar")); - gtk_box_pack_start (GTK_BOX (priv->button_box), button, FALSE, FALSE, 3); - gtk_widget_show (button); - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (update_reply_cb), priv); - - snprintf (message, 250, "%s responded to your request, replying with: %s", - priv->from_address, partstat_values[priv->new_partstat]); - } + priv = itip->priv; - } - break; - case ICAL_METHOD_CANCEL: - if (strcmp (priv->organizer, priv->from_address) != 0) { - snprintf (message, 250, "%s sent a cancellation request, but is not " - "the organizer of the meeting.", - priv->from_address); - } else { - GtkWidget *button; - - button = gtk_button_new_with_label (_("Cancel Meeting")); - gtk_box_pack_start (GTK_BOX (priv->button_box), button, FALSE, FALSE, 3); - gtk_widget_show (button); - - gtk_signal_connect (GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC (cancel_meeting_cb), priv); - - snprintf (message, 250, "%s sent a cancellation request. You can" - " delete this event from your calendar, if you wish.", - priv->organizer); - } - break; - default: - snprintf (message, 250, "I haven't the slightest notion what this calendar " - "object represents. Sorry."); - } + return priv->my_address; +} - pos = 0; - gtk_editable_insert_text (GTK_EDITABLE (priv->message_text), - message, strlen (message), &pos); -} /* pstream_load */ -/* - * This function implements the Bonobo::PersistStream:save method. - */ static void -pstream_save (BonoboPersistStream *ps, const Bonobo_Stream stream, - Bonobo_Persist_ContentType type, void *data, - CORBA_Environment *ev) +update_item (EItipControl *itip) { - EItipControlPrivate *priv = data; - int length; + EItipControlPrivate *priv; + CalClient *client; + CalComponentVType type; + + priv = itip->priv; - if (type && g_strcasecmp (type, "text/calendar") != 0 && - g_strcasecmp (type, "text/x-calendar") != 0) { - CORBA_exception_set (ev, CORBA_USER_EXCEPTION, - ex_Bonobo_Persist_WrongDataType, NULL); - return; + type = cal_component_get_vtype (priv->comp); + if (type == CAL_COMPONENT_TODO) + client = priv->task_client; + else + client = priv->event_client; + + if (!cal_client_update_object (client, priv->comp)) { + GtkWidget *dialog; + + dialog = gnome_warning_dialog(_("I couldn't update your calendar file!\n")); + gnome_dialog_run (GNOME_DIALOG(dialog)); } +} - /* Put something into vcalendar here. */ - length = strlen (priv->vcalendar); +static void +remove_item (EItipControl *itip) +{ + EItipControlPrivate *priv; + CalClient *client; + CalComponentVType type; + const char *uid; + + priv = itip->priv; - bonobo_stream_client_write (stream, priv->vcalendar, length, ev); -} /* pstream_save */ + type = cal_component_get_vtype (priv->comp); + if (type == CAL_COMPONENT_TODO) + client = priv->task_client; + else + client = priv->event_client; -static CORBA_long -pstream_get_max_size (BonoboPersistStream *ps, void *data, - CORBA_Environment *ev) -{ - EItipControlPrivate *priv = data; - - if (priv->vcalendar) - return strlen (priv->vcalendar); - else - return 0L; + cal_component_get_uid (priv->comp, &uid); + if (!cal_client_remove_object (client, uid)) { + GtkWidget *dialog; + + dialog = gnome_warning_dialog(_("I couldn't remove the item from your calendar file!\n")); + gnome_dialog_run (GNOME_DIALOG(dialog)); + } } -static Bonobo_Persist_ContentTypeList * -pstream_get_content_types (BonoboPersistStream *ps, void *closure, - CORBA_Environment *ev) +static void +send_freebusy (void) { - return bonobo_persist_generate_content_types (2, "text/calendar", "text/x-calendar"); } static void -get_prop ( BonoboPropertyBag *bag, - BonoboArg *arg, - guint arg_id, - CORBA_Environment *ev, - gpointer user_data) +change_status (EItipControl *itip, gchar *address, icalparameter_partstat status) { - EItipControlPrivate *priv = user_data; + EItipControlPrivate *priv; + icalproperty *prop; - if (arg_id == FROM_ADDRESS_ARG_ID) { - BONOBO_ARG_SET_STRING (arg, priv->from_address); - } - else if (arg_id == MY_ADDRESS_ARG_ID) { - BONOBO_ARG_SET_STRING (arg, priv->my_address); + priv = itip->priv; + + prop = find_attendee (priv->ical_comp, address); + if (prop) { + icalparameter *param; + + icalproperty_remove_parameter (prop, ICAL_PARTSTAT_PARAMETER); + param = icalparameter_new_partstat (status); + icalproperty_add_parameter (prop, param); } } static void -set_prop ( BonoboPropertyBag *bag, - const BonoboArg *arg, - guint arg_id, - CORBA_Environment *ev, - gpointer user_data) +prev_clicked_cb (GtkWidget *widget, gpointer data) { - EItipControlPrivate *priv = user_data; + EItipControl *itip = E_ITIP_CONTROL (data); + EItipControlPrivate *priv; - if (arg_id == FROM_ADDRESS_ARG_ID) { - if (priv->from_address) - g_free (priv->from_address); + priv = itip->priv; - - priv->from_address = g_strdup (BONOBO_ARG_GET_STRING (arg)); + priv->current--; + priv->ical_comp = icalcompiter_prior (&priv->iter); - /* Let's set the widget here, though I'm not sure if - it will work. */ - gtk_entry_set_text (GTK_ENTRY (priv->address_entry), priv->from_address); - - } - else if (arg_id == MY_ADDRESS_ARG_ID) { - if (priv->my_address) - g_free (priv->my_address); - - priv->my_address = g_strdup (BONOBO_ARG_GET_STRING (arg)); - } + show_current (itip); } - -static BonoboObject * -e_itip_control_factory (BonoboGenericFactory *Factory, void *closure) +static void +next_clicked_cb (GtkWidget *widget, gpointer data) { - BonoboControl *control; - BonoboPropertyBag *prop_bag; - BonoboPersistStream *stream; + EItipControl *itip = E_ITIP_CONTROL (data); EItipControlPrivate *priv; - priv = g_new0 (EItipControlPrivate, 1); - - priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/" "e-itip-control.glade", "main_frame"); - - /* Create the control. */ - priv->main_frame = glade_xml_get_widget (priv->xml, "main_frame"); - priv->organizer_entry = glade_xml_get_widget (priv->xml, "organizer_entry"); - priv->dtstart_label = glade_xml_get_widget (priv->xml, "dtstart_label"); - priv->dtend_label = glade_xml_get_widget (priv->xml, "dtend_label"); - priv->summary_entry = glade_xml_get_widget (priv->xml, "summary_entry"); - priv->description_box = glade_xml_get_widget (priv->xml, "description_box"); - /* priv->add_button = glade_xml_get_widget (priv->xml, "add_button"); */ - priv->button_box = glade_xml_get_widget (priv->xml, "button_box"); - priv->address_entry = glade_xml_get_widget (priv->xml, "address_entry"); - priv->message_text = glade_xml_get_widget (priv->xml, "message_text"); - - gtk_text_set_word_wrap (GTK_TEXT (priv->message_text), TRUE); + priv = itip->priv; - priv->xml2 = glade_xml_new (EVOLUTION_GLADEDIR "/" "e-itip-control.glade", "loading_window"); - priv->loading_progress = glade_xml_get_widget (priv->xml2, "loading_progress"); - priv->loading_window = glade_xml_get_widget (priv->xml2, "loading_window"); - - gtk_signal_connect (GTK_OBJECT (priv->main_frame), "destroy", - GTK_SIGNAL_FUNC (itip_control_destroy_cb), priv); + priv->current++; + priv->ical_comp = icalcompiter_next (&priv->iter); - gtk_widget_show (priv->main_frame); + show_current (itip); +} - control = bonobo_control_new (priv->main_frame); +static void +ok_clicked_cb (GtkWidget *widget, gpointer data) +{ + EItipControl *itip = E_ITIP_CONTROL (data); + EItipControlPrivate *priv; + gint selection; + + priv = itip->priv; - /* create a property bag */ - prop_bag = bonobo_property_bag_new ( get_prop, set_prop, priv ); - bonobo_property_bag_add (prop_bag, "from_address", FROM_ADDRESS_ARG_ID, BONOBO_ARG_STRING, NULL, - "from_address", 0 ); - bonobo_property_bag_add (prop_bag, "my_address", MY_ADDRESS_ARG_ID, BONOBO_ARG_STRING, NULL, - "my_address", 0 ); + selection = e_dialog_option_menu_get (priv->options, priv->map); - bonobo_control_set_properties (control, prop_bag); - bonobo_object_unref (BONOBO_OBJECT (prop_bag)); + if (priv->map == publish_map) { + update_item (itip); + } else if (priv->map == request_map) { + gboolean rsvp = FALSE; + + switch (selection) { + case ACCEPT_TO_CALENDAR_RSVP: + rsvp = TRUE; + case ACCEPT_TO_CALENDAR: + change_status (itip, priv->my_address, ICAL_PARTSTAT_ACCEPTED); + break; + case TENTATIVE_TO_CALENDAR_RSVP: + rsvp = TRUE; + case TENTATIVE_TO_CALENDAR: + change_status (itip, priv->my_address, ICAL_PARTSTAT_TENTATIVE); + break; + case DECLINE_TO_CALENDAR_RSVP: + rsvp = TRUE; + case DECLINE_TO_CALENDAR: + change_status (itip, priv->my_address, ICAL_PARTSTAT_DECLINED); + break; + } + update_item (itip); + if (rsvp) + itip_send_comp (CAL_COMPONENT_METHOD_REPLY, priv->comp); - bonobo_control_set_automerge (control, TRUE); + } else if (priv->map == request_fb_map) { + send_freebusy (); - stream = bonobo_persist_stream_new (pstream_load, pstream_save, - pstream_get_max_size, - pstream_get_content_types, - priv); + } else if (priv->map == reply_map) { + update_item (itip); - if (stream == NULL) { - bonobo_object_unref (BONOBO_OBJECT (control)); - return NULL; + } else if (priv->map == cancel_map) { + remove_item (itip); } - - bonobo_object_add_interface (BONOBO_OBJECT (control), - BONOBO_OBJECT (stream)); - - return BONOBO_OBJECT (control); -} - -void -e_itip_control_factory_init (void) -{ - static BonoboGenericFactory *factory = NULL; - - if (factory != NULL) - return; - - factory = bonobo_generic_factory_new ( - "OAFIID:GNOME_Evolution_Calendar_iTip_ControlFactory", - e_itip_control_factory, NULL); - bonobo_running_context_auto_exit_unref (BONOBO_OBJECT (factory));; - - if (factory == NULL) - g_error ("I could not register an iTip control factory."); } - diff --git a/calendar/gui/e-itip-control.h b/calendar/gui/e-itip-control.h index 6c2df626ce..afad2b744d 100644 --- a/calendar/gui/e-itip-control.h +++ b/calendar/gui/e-itip-control.h @@ -1,30 +1,79 @@ -/* Evolution calendar - Control for displaying iTIP mail messages +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-itip-control.h * - * Copyright (C) 2000 Helix Code, Inc. - * Copyright (C) 2000 Ximian, Inc. + * Copyright (C) 2001 Ximian, Inc. * - * Author: Jesse Pavel <jpavel@ximian.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * Author: JP Rosevear */ -#ifndef __E_ITIP_CONTROL_H__ -#define __E_ITIP_CONTROL_H__ +#ifndef _E_ITIP_CONTROL_H_ +#define _E_ITIP_CONTROL_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gtk/gtk.h> + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus */ + +#define E_TYPE_ITIP_CONTROL (e_itip_control_get_type ()) +#define E_ITIP_CONTROL(obj) (GTK_CHECK_CAST ((obj), E_TYPE_ITIP_CONTROL, EItipControl)) +#define E_ITIP_CONTROL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_ITIP_CONTROL, EItipControlClass)) +#define E_IS_ITIP_CONTROL(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_ITIP_CONTROL)) +#define E_IS_ITIP_CONTROL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TYPE_ITIP_CONTROL)) + + +typedef struct _EItipControl EItipControl; +typedef struct _EItipControlPrivate EItipControlPrivate; +typedef struct _EItipControlClass EItipControlClass; + +struct _EItipControl { + GtkVBox parent; + + EItipControlPrivate *priv; +}; + +struct _EItipControlClass { + GtkVBoxClass parent_class; +}; + + + +GtkType e_itip_control_get_type (void); +GtkWidget * e_itip_control_new (void); +void e_itip_control_set_data (EItipControl *itip, + const gchar *text); +gchar * e_itip_control_get_data (EItipControl *itip); +gint e_itip_control_get_data_size (EItipControl *itip); +void e_itip_control_set_from_address (EItipControl *itip, + const gchar *address); +const gchar *e_itip_control_get_from_address (EItipControl *itip); +void e_itip_control_set_my_address (EItipControl *itip, + const gchar *address); +const gchar *e_itip_control_get_my_address (EItipControl *itip); -#include <bonobo/bonobo-control.h> -void e_itip_control_factory_init (void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ -#endif /* __E_ITIP_CONTROL_H__ */ +#endif /* _E_ITIP_CONTROL_H_ */ diff --git a/calendar/gui/itip-bonobo-control.c b/calendar/gui/itip-bonobo-control.c new file mode 100644 index 0000000000..a385803bc8 --- /dev/null +++ b/calendar/gui/itip-bonobo-control.c @@ -0,0 +1,267 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* Evolution calendar - Control for displaying iTIP mail messages + * + * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2000 Ximian, Inc. + * + * Author: Jesse Pavel <jpavel@ximian.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <config.h> +#include <glib.h> +#include <gtk/gtkobject.h> +#include <gtk/gtkwidget.h> +#include <bonobo/bonobo-generic-factory.h> +#include <bonobo/bonobo-control.h> +#include <bonobo/bonobo-property-bag.h> +#include <bonobo/bonobo-persist-stream.h> +#include <bonobo/bonobo-stream-client.h> +#include <bonobo/bonobo-context.h> +#include <ical.h> + +#include "e-itip-control.h" +#include "itip-control-factory.h" + +extern gchar *evolution_dir; + +enum E_ITIP_BONOBO_ARGS { + FROM_ADDRESS_ARG_ID, + MY_ADDRESS_ARG_ID +}; + +/* + * Bonobo::PersistStream + * + * These two functions implement the Bonobo::PersistStream load and + * save methods which allow data to be loaded into and out of the + * BonoboObject. + */ + +static char * +stream_read (Bonobo_Stream stream) +{ + Bonobo_Stream_iobuf *buffer; + CORBA_Environment ev; + gchar *data = NULL; + gint length = 0; + + CORBA_exception_init (&ev); + do { +#define READ_CHUNK_SIZE 65536 + Bonobo_Stream_read (stream, READ_CHUNK_SIZE, + &buffer, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + CORBA_exception_free (&ev); + return NULL; + } + + if (buffer->_length <= 0) + break; + + data = g_realloc (data, + length + buffer->_length); + + memcpy (data + length, + buffer->_buffer, buffer->_length); + + length += buffer->_length; + + CORBA_free (buffer); +#undef READ_CHUNK_SIZE + } while (1); + + CORBA_free (buffer); + CORBA_exception_free (&ev); + + if (data == NULL) + data = g_strdup(""); + + return data; +} /* stream_read */ + +/* + * This function implements the Bonobo::PersistStream:load method. + */ +static void +pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream, + Bonobo_Persist_ContentType type, void *data, + CORBA_Environment *ev) +{ + EItipControl *itip = data; + gchar *text; + + if (type && g_strcasecmp (type, "text/calendar") != 0 && + g_strcasecmp (type, "text/x-calendar") != 0) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_Bonobo_Persist_WrongDataType, NULL); + return; + } + + if ((text = stream_read (stream)) == NULL) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_Bonobo_Persist_FileNotFound, NULL); + return; + } + + e_itip_control_set_data (itip, text); + g_free (text); +} +/* + * This function implements the Bonobo::PersistStream:save method. + */ +static void +pstream_save (BonoboPersistStream *ps, const Bonobo_Stream stream, + Bonobo_Persist_ContentType type, void *data, + CORBA_Environment *ev) +{ + EItipControl *itip = data; + gchar *text; + gint len; + + if (type && g_strcasecmp (type, "text/calendar") != 0 && + g_strcasecmp (type, "text/x-calendar") != 0) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_Bonobo_Persist_WrongDataType, NULL); + return; + } + + text = e_itip_control_get_data (itip); + len = e_itip_control_get_data_size (itip); + + bonobo_stream_client_write (stream, text, len, ev); + g_free (text); +} /* pstream_save */ + +static CORBA_long +pstream_get_max_size (BonoboPersistStream *ps, void *data, + CORBA_Environment *ev) +{ + EItipControl *itip = data; + gint len; + + len = e_itip_control_get_data_size (itip); + + if (len > 0) + return len; + + return 0L; +} + +static Bonobo_Persist_ContentTypeList * +pstream_get_content_types (BonoboPersistStream *ps, void *closure, + CORBA_Environment *ev) +{ + return bonobo_persist_generate_content_types (2, "text/calendar", "text/x-calendar"); +} + +static void +get_prop (BonoboPropertyBag *bag, + BonoboArg *arg, + guint arg_id, + CORBA_Environment *ev, + gpointer user_data) +{ + EItipControl *itip = user_data; + + switch (arg_id) { + case FROM_ADDRESS_ARG_ID: + BONOBO_ARG_SET_STRING (arg, e_itip_control_get_from_address (itip)); + break; + case MY_ADDRESS_ARG_ID: + BONOBO_ARG_SET_STRING (arg, e_itip_control_get_my_address (itip)); + break; + } +} + +static void +set_prop ( BonoboPropertyBag *bag, + const BonoboArg *arg, + guint arg_id, + CORBA_Environment *ev, + gpointer user_data) +{ + EItipControl *itip = user_data; + + switch (arg_id) { + case FROM_ADDRESS_ARG_ID: + e_itip_control_set_from_address (itip, BONOBO_ARG_GET_STRING (arg)); + break; + case MY_ADDRESS_ARG_ID: + e_itip_control_set_my_address (itip, BONOBO_ARG_GET_STRING (arg)); + break; + } +} + + +static BonoboObject * +itip_control_factory (BonoboGenericFactory *Factory, void *closure) +{ + BonoboControl *control; + BonoboPropertyBag *prop_bag; + BonoboPersistStream *stream; + GtkWidget *itip; + + itip = e_itip_control_new (); + gtk_widget_show (itip); + control = bonobo_control_new (itip); + + /* create a property bag */ + prop_bag = bonobo_property_bag_new (get_prop, set_prop, itip); + bonobo_property_bag_add (prop_bag, "from_address", FROM_ADDRESS_ARG_ID, BONOBO_ARG_STRING, NULL, + "from_address", 0 ); + bonobo_property_bag_add (prop_bag, "my_address", MY_ADDRESS_ARG_ID, BONOBO_ARG_STRING, NULL, + "my_address", 0 ); + + bonobo_control_set_properties (control, prop_bag); + bonobo_object_unref (BONOBO_OBJECT (prop_bag)); + + bonobo_control_set_automerge (control, TRUE); + + stream = bonobo_persist_stream_new (pstream_load, pstream_save, + pstream_get_max_size, + pstream_get_content_types, + itip); + + if (stream == NULL) { + bonobo_object_unref (BONOBO_OBJECT (control)); + return NULL; + } + + bonobo_object_add_interface (BONOBO_OBJECT (control), + BONOBO_OBJECT (stream)); + + return BONOBO_OBJECT (control); +} + +void +itip_control_factory_init (void) +{ + static BonoboGenericFactory *factory = NULL; + + if (factory != NULL) + return; + + factory = bonobo_generic_factory_new ( + "OAFIID:GNOME_Evolution_Calendar_iTip_ControlFactory", + itip_control_factory, NULL); + bonobo_running_context_auto_exit_unref (BONOBO_OBJECT (factory));; + + if (factory == NULL) + g_error ("I could not register an iTip control factory."); +} + diff --git a/calendar/gui/itip-bonobo-control.h b/calendar/gui/itip-bonobo-control.h new file mode 100644 index 0000000000..045fd31bc3 --- /dev/null +++ b/calendar/gui/itip-bonobo-control.h @@ -0,0 +1,30 @@ +/* Evolution calendar - Control for displaying iTIP mail messages + * + * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2000 Ximian, Inc. + * + * Authors: + * Jesse Pavel <jpavel@ximian.com> + * JP Rosevear <jpr@ximian.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __ITIP_CONTROL_FACTORY_H__ +#define __ITIP_CONTROL_FACTORY_H__ + +void itip_control_factory_init (void); + +#endif /* __ITIP_CONTROL_H__ */ diff --git a/calendar/gui/itip-control-factory.c b/calendar/gui/itip-control-factory.c new file mode 100644 index 0000000000..a385803bc8 --- /dev/null +++ b/calendar/gui/itip-control-factory.c @@ -0,0 +1,267 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* Evolution calendar - Control for displaying iTIP mail messages + * + * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2000 Ximian, Inc. + * + * Author: Jesse Pavel <jpavel@ximian.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <config.h> +#include <glib.h> +#include <gtk/gtkobject.h> +#include <gtk/gtkwidget.h> +#include <bonobo/bonobo-generic-factory.h> +#include <bonobo/bonobo-control.h> +#include <bonobo/bonobo-property-bag.h> +#include <bonobo/bonobo-persist-stream.h> +#include <bonobo/bonobo-stream-client.h> +#include <bonobo/bonobo-context.h> +#include <ical.h> + +#include "e-itip-control.h" +#include "itip-control-factory.h" + +extern gchar *evolution_dir; + +enum E_ITIP_BONOBO_ARGS { + FROM_ADDRESS_ARG_ID, + MY_ADDRESS_ARG_ID +}; + +/* + * Bonobo::PersistStream + * + * These two functions implement the Bonobo::PersistStream load and + * save methods which allow data to be loaded into and out of the + * BonoboObject. + */ + +static char * +stream_read (Bonobo_Stream stream) +{ + Bonobo_Stream_iobuf *buffer; + CORBA_Environment ev; + gchar *data = NULL; + gint length = 0; + + CORBA_exception_init (&ev); + do { +#define READ_CHUNK_SIZE 65536 + Bonobo_Stream_read (stream, READ_CHUNK_SIZE, + &buffer, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) { + CORBA_exception_free (&ev); + return NULL; + } + + if (buffer->_length <= 0) + break; + + data = g_realloc (data, + length + buffer->_length); + + memcpy (data + length, + buffer->_buffer, buffer->_length); + + length += buffer->_length; + + CORBA_free (buffer); +#undef READ_CHUNK_SIZE + } while (1); + + CORBA_free (buffer); + CORBA_exception_free (&ev); + + if (data == NULL) + data = g_strdup(""); + + return data; +} /* stream_read */ + +/* + * This function implements the Bonobo::PersistStream:load method. + */ +static void +pstream_load (BonoboPersistStream *ps, const Bonobo_Stream stream, + Bonobo_Persist_ContentType type, void *data, + CORBA_Environment *ev) +{ + EItipControl *itip = data; + gchar *text; + + if (type && g_strcasecmp (type, "text/calendar") != 0 && + g_strcasecmp (type, "text/x-calendar") != 0) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_Bonobo_Persist_WrongDataType, NULL); + return; + } + + if ((text = stream_read (stream)) == NULL) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_Bonobo_Persist_FileNotFound, NULL); + return; + } + + e_itip_control_set_data (itip, text); + g_free (text); +} +/* + * This function implements the Bonobo::PersistStream:save method. + */ +static void +pstream_save (BonoboPersistStream *ps, const Bonobo_Stream stream, + Bonobo_Persist_ContentType type, void *data, + CORBA_Environment *ev) +{ + EItipControl *itip = data; + gchar *text; + gint len; + + if (type && g_strcasecmp (type, "text/calendar") != 0 && + g_strcasecmp (type, "text/x-calendar") != 0) { + CORBA_exception_set (ev, CORBA_USER_EXCEPTION, + ex_Bonobo_Persist_WrongDataType, NULL); + return; + } + + text = e_itip_control_get_data (itip); + len = e_itip_control_get_data_size (itip); + + bonobo_stream_client_write (stream, text, len, ev); + g_free (text); +} /* pstream_save */ + +static CORBA_long +pstream_get_max_size (BonoboPersistStream *ps, void *data, + CORBA_Environment *ev) +{ + EItipControl *itip = data; + gint len; + + len = e_itip_control_get_data_size (itip); + + if (len > 0) + return len; + + return 0L; +} + +static Bonobo_Persist_ContentTypeList * +pstream_get_content_types (BonoboPersistStream *ps, void *closure, + CORBA_Environment *ev) +{ + return bonobo_persist_generate_content_types (2, "text/calendar", "text/x-calendar"); +} + +static void +get_prop (BonoboPropertyBag *bag, + BonoboArg *arg, + guint arg_id, + CORBA_Environment *ev, + gpointer user_data) +{ + EItipControl *itip = user_data; + + switch (arg_id) { + case FROM_ADDRESS_ARG_ID: + BONOBO_ARG_SET_STRING (arg, e_itip_control_get_from_address (itip)); + break; + case MY_ADDRESS_ARG_ID: + BONOBO_ARG_SET_STRING (arg, e_itip_control_get_my_address (itip)); + break; + } +} + +static void +set_prop ( BonoboPropertyBag *bag, + const BonoboArg *arg, + guint arg_id, + CORBA_Environment *ev, + gpointer user_data) +{ + EItipControl *itip = user_data; + + switch (arg_id) { + case FROM_ADDRESS_ARG_ID: + e_itip_control_set_from_address (itip, BONOBO_ARG_GET_STRING (arg)); + break; + case MY_ADDRESS_ARG_ID: + e_itip_control_set_my_address (itip, BONOBO_ARG_GET_STRING (arg)); + break; + } +} + + +static BonoboObject * +itip_control_factory (BonoboGenericFactory *Factory, void *closure) +{ + BonoboControl *control; + BonoboPropertyBag *prop_bag; + BonoboPersistStream *stream; + GtkWidget *itip; + + itip = e_itip_control_new (); + gtk_widget_show (itip); + control = bonobo_control_new (itip); + + /* create a property bag */ + prop_bag = bonobo_property_bag_new (get_prop, set_prop, itip); + bonobo_property_bag_add (prop_bag, "from_address", FROM_ADDRESS_ARG_ID, BONOBO_ARG_STRING, NULL, + "from_address", 0 ); + bonobo_property_bag_add (prop_bag, "my_address", MY_ADDRESS_ARG_ID, BONOBO_ARG_STRING, NULL, + "my_address", 0 ); + + bonobo_control_set_properties (control, prop_bag); + bonobo_object_unref (BONOBO_OBJECT (prop_bag)); + + bonobo_control_set_automerge (control, TRUE); + + stream = bonobo_persist_stream_new (pstream_load, pstream_save, + pstream_get_max_size, + pstream_get_content_types, + itip); + + if (stream == NULL) { + bonobo_object_unref (BONOBO_OBJECT (control)); + return NULL; + } + + bonobo_object_add_interface (BONOBO_OBJECT (control), + BONOBO_OBJECT (stream)); + + return BONOBO_OBJECT (control); +} + +void +itip_control_factory_init (void) +{ + static BonoboGenericFactory *factory = NULL; + + if (factory != NULL) + return; + + factory = bonobo_generic_factory_new ( + "OAFIID:GNOME_Evolution_Calendar_iTip_ControlFactory", + itip_control_factory, NULL); + bonobo_running_context_auto_exit_unref (BONOBO_OBJECT (factory));; + + if (factory == NULL) + g_error ("I could not register an iTip control factory."); +} + diff --git a/calendar/gui/itip-control-factory.h b/calendar/gui/itip-control-factory.h new file mode 100644 index 0000000000..045fd31bc3 --- /dev/null +++ b/calendar/gui/itip-control-factory.h @@ -0,0 +1,30 @@ +/* Evolution calendar - Control for displaying iTIP mail messages + * + * Copyright (C) 2000 Helix Code, Inc. + * Copyright (C) 2000 Ximian, Inc. + * + * Authors: + * Jesse Pavel <jpavel@ximian.com> + * JP Rosevear <jpr@ximian.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __ITIP_CONTROL_FACTORY_H__ +#define __ITIP_CONTROL_FACTORY_H__ + +void itip_control_factory_init (void); + +#endif /* __ITIP_CONTROL_H__ */ diff --git a/calendar/gui/main.c b/calendar/gui/main.c index e75819f0f0..7a21193799 100644 --- a/calendar/gui/main.c +++ b/calendar/gui/main.c @@ -41,7 +41,7 @@ #include "calendar-config.h" #include "component-factory.h" #include "control-factory.h" -#include "e-itip-control.h" +#include "itip-control-factory.h" #include "tasks-control-factory.h" static void @@ -77,7 +77,7 @@ main (int argc, char **argv) control_factory_init (); component_factory_init (); - e_itip_control_factory_init (); + itip_control_factory_init (); tasks_control_factory_init (); bonobo_main (); |