diff options
-rw-r--r-- | calendar/ChangeLog | 39 | ||||
-rw-r--r-- | calendar/cal-client/cal-client.c | 11 | ||||
-rw-r--r-- | calendar/cal-util/cal-util.c | 30 | ||||
-rw-r--r-- | calendar/cal-util/cal-util.h | 2 | ||||
-rw-r--r-- | calendar/gui/calendar-config.c | 55 | ||||
-rw-r--r-- | calendar/gui/calendar-config.h | 4 | ||||
-rw-r--r-- | calendar/gui/e-itip-control.c | 300 |
7 files changed, 399 insertions, 42 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 8c2263765c..d7ac3e60fa 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,42 @@ +2002-05-07 JP Rosevear <jpr@ximian.com> + + * gui/e-itip-control.c (start_calendar_server): start a server a + uri + (start_default_server): start a default server + (get_servers): get all clients for all folders of the given + type(s) + (find_server): locate a server for a particular uid + (init): get_servers, listen for object_requested signal + (destroy): destroy all clients + (write_html): put options is there own cell + (get_publish_options): place selector in if param is true + (get_request_options): ditto + (get_real_item): only try and look up the item if we know its in + the server + (show_current_event): find the server (if any) for the current + comp + (show_current_todo): ditto + (update_attendee_status): if there is no server for the comp, it + doesn't exist + (remove_item): ditto + (button_selected_cb): get a client for the selected folder + (object_requested_cb): draw the folder button in + + * gui/calendar-config.h: new protos + + * gui/calendar-config.c (calendar_config_default_tasks_folder): + get default tasks uri + (calendar_config_default_calendar_folder): get default calendar + uri + + * cal-client/cal-client.c (get_default_uri): use + cal_util_expand_uri + + * cal-util/cal-util.h: new proto + + * cal-util/cal-util.c (cal_util_expand_uri): tack on the file name + if its a file uri + 2002-05-03 Rodrigo Moya <rodrigo@ximian.com> * gui/e-tasks.c (e_tasks_delete_selected): diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c index 60063a72b2..30402bf126 100644 --- a/calendar/cal-client/cal-client.c +++ b/calendar/cal-client/cal-client.c @@ -796,7 +796,7 @@ static char * get_default_uri (gboolean tasks) { Bonobo_ConfigDatabase db; - char *uri, *file_uri; + char *uri; CORBA_Environment ev; CORBA_exception_init (&ev); @@ -817,13 +817,8 @@ get_default_uri (gboolean tasks) if (BONOBO_EX (&ev)) { CORBA_exception_free (&ev); uri = get_fall_back_uri (tasks); - } else if (!strncmp (uri, "file:", 5)) { - for (file_uri = uri + 5; *file_uri == '/'; file_uri++) - ; - file_uri = g_strdup_printf ("/%s/%s.ics", file_uri, - tasks ? "tasks" : "calendar"); - g_free (uri); - uri = file_uri; + } else { + uri = cal_util_expand_uri (uri, tasks); } return uri; diff --git a/calendar/cal-util/cal-util.c b/calendar/cal-util/cal-util.c index a30329c638..8ba1ff7d63 100644 --- a/calendar/cal-util/cal-util.c +++ b/calendar/cal-util/cal-util.c @@ -21,9 +21,11 @@ #include <config.h> #include <stdlib.h> +#include <string.h> #include <glib.h> #include <libgnome/gnome-defs.h> #include <libgnome/gnome-i18n.h> +#include <libgnome/gnome-util.h> #include "cal-util.h" @@ -528,3 +530,31 @@ cal_util_priority_from_string (const char *string) return priority; } + +char * +cal_util_expand_uri (char *uri, gboolean tasks) +{ + char *file_uri, *file_name; + + if (!strncmp (uri, "file://", 7)) { + file_uri = uri + 7; + if (strlen (file_uri) > 4 + && !strcmp (file_uri + strlen (file_uri) - 4, ".ics")) { + + /* it's a .ics file */ + return g_strdup (uri); + } + + /* we assume it's a dir and glom <type>.ics onto the end. */ + if (tasks) + file_name = g_concat_dir_and_file (file_uri, "tasks.ics"); + else + file_name = g_concat_dir_and_file (file_uri, "calendar.ics"); + file_uri = g_strdup_printf("file://%s", file_name); + g_free(file_name); + } else { + file_uri = g_strdup (uri); + } + + return file_uri; +} diff --git a/calendar/cal-util/cal-util.h b/calendar/cal-util/cal-util.h index 8a5dce9b03..d4ccfb5388 100644 --- a/calendar/cal-util/cal-util.h +++ b/calendar/cal-util/cal-util.h @@ -83,6 +83,8 @@ icaltimezone *cal_util_resolve_tzid (const char *tzid, gpointer data); char *cal_util_priority_to_string (int priority); int cal_util_priority_from_string (const char *string); +char *cal_util_expand_uri (char *uri, gboolean tasks); + END_GNOME_DECLS diff --git a/calendar/gui/calendar-config.c b/calendar/gui/calendar-config.c index 0237766ea8..572db1fe2c 100644 --- a/calendar/gui/calendar-config.c +++ b/calendar/gui/calendar-config.c @@ -1146,3 +1146,58 @@ calendar_config_get_hide_completed_tasks_sexp (void) return sexp; } + +char * +calendar_config_default_calendar_folder (void) +{ + Bonobo_ConfigDatabase db; + char *uri; + CORBA_Environment ev; + + CORBA_exception_init (&ev); + + db = bonobo_get_object ("wombat:", "Bonobo/ConfigDatabase", &ev); + + if (BONOBO_EX (&ev) || db == CORBA_OBJECT_NIL) { + CORBA_exception_free (&ev); + return NULL; + } + + uri = bonobo_config_get_string (db, "/DefaultFolders/calendar_uri", &ev); + bonobo_object_release_unref (db, NULL); + + if (BONOBO_EX (&ev)) { + CORBA_exception_free (&ev); + return NULL; + } + + return uri; +} + +char * +calendar_config_default_tasks_folder (void) +{ + Bonobo_ConfigDatabase db; + char *uri; + CORBA_Environment ev; + + CORBA_exception_init (&ev); + + db = bonobo_get_object ("wombat:", "Bonobo/ConfigDatabase", &ev); + + if (BONOBO_EX (&ev) || db == CORBA_OBJECT_NIL) { + CORBA_exception_free (&ev); + return NULL; + } + + uri = bonobo_config_get_string (db, "/DefaultFolders/tasks_uri", &ev); + bonobo_object_release_unref (db, NULL); + + if (BONOBO_EX (&ev)) { + CORBA_exception_free (&ev); + return NULL; + } + + return uri; +} + diff --git a/calendar/gui/calendar-config.h b/calendar/gui/calendar-config.h index 8c5f867a38..6f0a9ee0fd 100644 --- a/calendar/gui/calendar-config.h +++ b/calendar/gui/calendar-config.h @@ -182,4 +182,8 @@ void calendar_config_check_timezone_set (void); supports 12-hour time format. */ gboolean calendar_config_locale_supports_12_hour_format(void); +/* Default folders, read-only */ +char *calendar_config_default_calendar_folder (void); +char *calendar_config_default_tasks_folder (void); + #endif /* _CALENDAR_CONFIG_H_ */ diff --git a/calendar/gui/e-itip-control.c b/calendar/gui/e-itip-control.c index 85052a09a1..90be0c509c 100644 --- a/calendar/gui/e-itip-control.c +++ b/calendar/gui/e-itip-control.c @@ -37,6 +37,7 @@ #include <libgnomeui/gnome-uidefs.h> #include <libgnomeui/gnome-dialog.h> #include <libgnomeui/gnome-dialog-util.h> +#include <bonobo/bonobo-exception.h> #include <gal/util/e-unicode-i18n.h> #include <gal/widgets/e-unicode.h> #include <gtkhtml/gtkhtml.h> @@ -47,6 +48,8 @@ #include <cal-client/cal-client.h> #include <e-util/e-time-utils.h> #include <e-util/e-dialog-widgets.h> +#include <evolution-shell-client.h> +#include <evolution-folder-selector-button.h> #include "calendar-config.h" #include "itip-utils.h" #include "e-itip-control.h" @@ -60,9 +63,11 @@ struct _EItipControlPrivate { GtkWidget *prev; #endif + GPtrArray *event_clients; CalClient *event_client; + GPtrArray *task_clients; CalClient *task_client; - + char *vcalendar; CalComponent *comp; icalcomponent *main_comp; @@ -117,6 +122,11 @@ struct _EItipControlPrivate { <input TYPE=Submit name=\"ok\" value=\"OK\"></form>" #endif +extern EvolutionShellClient *global_shell_client; + +static const char *calendar_types[] = { "calendar", NULL }; +static const char *tasks_types[] = { "tasks", NULL }; + static void class_init (EItipControlClass *klass); static void init (EItipControl *itip); static void destroy (GtkObject *obj); @@ -126,6 +136,7 @@ static void prev_clicked_cb (GtkWidget *widget, gpointer data); static void next_clicked_cb (GtkWidget *widget, gpointer data); #endif static void url_requested_cb (GtkHTML *html, const gchar *url, GtkHTMLStream *handle, gpointer data); +static gboolean object_requested_cb (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data); static void ok_clicked_cb (GtkHTML *html, const gchar *method, const gchar *url, const gchar *encoding, gpointer data); static GtkVBoxClass *parent_class = NULL; @@ -185,10 +196,35 @@ start_calendar_server_cb (CalClient *cal_client, } static CalClient * -start_calendar_server (gboolean tasks) +start_calendar_server (char *uri) { CalClient *client; - gboolean success; + gboolean success = FALSE; + + client = cal_client_new (); + + gtk_signal_connect (GTK_OBJECT (client), "cal_opened", + start_calendar_server_cb, &success); + + cal_client_open_calendar (client, uri, TRUE); + + /* run a sub event loop to turn cal-client's async load + notification into a synchronous call */ + gtk_main (); + + if (success) + return client; + + gtk_object_unref (GTK_OBJECT (client)); + + return NULL; +} + +static CalClient * +start_default_server (gboolean tasks) +{ + CalClient *client; + gboolean success = FALSE; client = cal_client_new (); @@ -202,7 +238,7 @@ start_calendar_server (gboolean tasks) if (!cal_client_open_default_calendar (client, FALSE)) goto error; } - + /* run a sub event loop to turn cal-client's async load notification into a synchronous call */ gtk_main (); @@ -216,6 +252,88 @@ start_calendar_server (gboolean tasks) return NULL; } +static GPtrArray * +get_servers (EvolutionShellClient *shell_client, const char *possible_types[], gboolean tasks) +{ + GNOME_Evolution_StorageRegistry registry; + GNOME_Evolution_StorageRegistry_StorageList *storage_list; + GPtrArray *servers; + int i, j, k; + CORBA_Environment ev; + + servers = g_ptr_array_new (); + + bonobo_object_ref (BONOBO_OBJECT (shell_client)); + registry = evolution_shell_client_get_storage_registry_interface (shell_client); + + CORBA_exception_init (&ev); + storage_list = GNOME_Evolution_StorageRegistry_getStorageList (registry, &ev); + if (BONOBO_EX (&ev)) { + CORBA_exception_free (&ev); + return servers; + } + + for (i = 0; i < storage_list->_length; i++) { + GNOME_Evolution_Storage storage; + GNOME_Evolution_FolderList *folder_list; + + storage = storage_list->_buffer[i]; + folder_list = GNOME_Evolution_Storage_getFolderList (storage, &ev); + + for (j = 0; j < folder_list->_length; j++) { + GNOME_Evolution_Folder folder; + + folder = folder_list->_buffer[j]; + for (k = 0; possible_types[k] != NULL; k++) { + CalClient *client; + char *uri; + + if (strcmp (possible_types[k], folder.type)) + continue; + + uri = cal_util_expand_uri (folder.physicalUri, tasks); + client = start_calendar_server (uri); + if (client != NULL) + g_ptr_array_add (servers, client); + g_free (uri); + + break; + } + } + + CORBA_free (folder_list); + } + + bonobo_object_unref (BONOBO_OBJECT (shell_client)); + + return servers; +} + +static CalClient * +find_server (GPtrArray *servers, CalComponent *comp) +{ + const char *uid; + int i; + + cal_component_get_uid (comp, &uid); + for (i = 0; i < servers->len; i++) { + CalClient *client; + CalComponent *found_comp; + CalClientGetStatus status; + + client = g_ptr_array_index (servers, i); + status = cal_client_get_object (client, uid, &found_comp); + if (status == CAL_CLIENT_GET_SUCCESS) { + gtk_object_unref (GTK_OBJECT (found_comp)); + gtk_object_ref (GTK_OBJECT (client)); + + return client; + } + } + + return NULL; +} + static void init (EItipControl *itip) { @@ -249,19 +367,15 @@ init (EItipControl *itip) #endif /* Get the cal clients */ - priv->event_client = start_calendar_server (FALSE); - if (priv->event_client == NULL) - g_warning ("Unable to start calendar client"); - - priv->task_client = start_calendar_server (TRUE); - if (priv->task_client == NULL) - g_warning ("Unable to start calendar client"); - + priv->event_clients = get_servers (global_shell_client, calendar_types, FALSE); + priv->event_client = NULL; + priv->task_clients = get_servers (global_shell_client, tasks_types, TRUE); + priv->task_client = NULL; + /* Html Widget */ priv->html = gtk_html_new (); gtk_html_set_default_content_type (GTK_HTML (priv->html), "text/html; charset=utf-8"); - gtk_widget_show (priv->html); scrolled_window = gtk_scrolled_window_new (NULL, NULL); @@ -276,6 +390,9 @@ init (EItipControl *itip) gtk_signal_connect (GTK_OBJECT (priv->html), "url_requested", url_requested_cb, itip); + gtk_signal_connect (GTK_OBJECT (priv->html), "object_requested", + GTK_SIGNAL_FUNC (object_requested_cb), + itip); gtk_signal_connect (GTK_OBJECT (priv->html), "submit", ok_clicked_cb, itip); @@ -315,7 +432,8 @@ destroy (GtkObject *obj) { EItipControl *itip = E_ITIP_CONTROL (obj); EItipControlPrivate *priv; - + int i; + priv = itip->priv; clean_up (itip); @@ -323,8 +441,12 @@ destroy (GtkObject *obj) itip_addresses_free (priv->addresses); priv->addresses = NULL; - gtk_object_unref (GTK_OBJECT (priv->event_client)); - gtk_object_unref (GTK_OBJECT (priv->task_client)); + for (i = 0; i < priv->event_clients->len; i++) + gtk_object_unref (GTK_OBJECT (g_ptr_array_index (priv->event_clients, i))); + g_ptr_array_free (priv->event_clients, TRUE); + for (i = 0; i < priv->task_clients->len; i++) + gtk_object_unref (GTK_OBJECT (g_ptr_array_index (priv->task_clients, i))); + g_ptr_array_free (priv->task_clients, TRUE); g_free (priv); @@ -817,9 +939,12 @@ write_html (EItipControl *itip, const gchar *itip_desc, const gchar *itip_title, gtk_html_write (GTK_HTML (priv->html), html_stream, HTML_SEP, strlen (HTML_SEP)); /* Options */ - if (options != NULL) + if (options != NULL) { + const_html = "</td></tr><tr><td valign=\"center\">"; + gtk_html_write (GTK_HTML (priv->html), html_stream, const_html, strlen (const_html)); gtk_html_write (GTK_HTML (priv->html), html_stream, options, strlen (options)); - + } + const_html = "</td></tr></table>"; gtk_html_write (GTK_HTML (priv->html), html_stream, const_html, strlen(const_html)); @@ -833,9 +958,11 @@ write_html (EItipControl *itip, const gchar *itip_desc, const gchar *itip_title, static char* -get_publish_options () +get_publish_options (gboolean selector) { - return g_strdup_printf ("<form><b>%s</b> " + char *html; + + html = g_strdup_printf ("<form><b>%s</b> " "<select NAME=\"action\" SIZE=\"1\"> " "<option VALUE=\"U\">%s</option>" "</select>    " @@ -844,12 +971,24 @@ get_publish_options () U_("Choose an action:"), U_("Update"), U_("OK")); + + if (selector) { + char *sel; + + sel = g_strconcat (html, "<object classid=\"gtk:label\">", NULL); + g_free (html); + html = sel; + } + + return html; } static char* -get_request_options () +get_request_options (gboolean selector) { - return g_strdup_printf ("<form><b>%s</b> " + char *html; + + html = g_strdup_printf ("<form><b>%s</b> " "<select NAME=\"action\" SIZE=\"1\"> " "<option VALUE=\"A\">%s</option> " "<option VALUE=\"T\">%s</option> " @@ -863,6 +1002,16 @@ get_request_options () U_("Decline"), U_("RSVP"), U_("OK")); + + if (selector) { + char *sel; + + sel = g_strconcat (html, "<object classid=\"gtk:label\">", NULL); + g_free (html); + html = sel; + } + + return html; } static char* @@ -924,7 +1073,7 @@ get_real_item (EItipControl *itip) EItipControlPrivate *priv; CalComponent *comp; CalComponentVType type; - CalClientGetStatus status; + CalClientGetStatus status = CAL_CLIENT_GET_NOT_FOUND; const char *uid; priv = itip->priv; @@ -934,10 +1083,12 @@ get_real_item (EItipControl *itip) switch (type) { case CAL_COMPONENT_EVENT: - status = cal_client_get_object (priv->event_client, uid, &comp); + if (priv->event_client != NULL) + status = cal_client_get_object (priv->event_client, uid, &comp); break; case CAL_COMPONENT_TODO: - status = cal_client_get_object (priv->task_client, uid, &comp); + if (priv->task_client != NULL) + status = cal_client_get_object (priv->task_client, uid, &comp); break; default: status = CAL_CLIENT_GET_NOT_FOUND; @@ -959,21 +1110,23 @@ show_current_event (EItipControl *itip) priv = itip->priv; + priv->event_client = find_server (priv->event_clients, priv->comp); + switch (priv->method) { case ICAL_METHOD_PUBLISH: itip_desc = U_("<b>%s</b> has published meeting information."); itip_title = U_("Meeting Information"); - options = get_publish_options (); + options = get_publish_options (priv->event_client ? FALSE : TRUE); break; case ICAL_METHOD_REQUEST: itip_desc = U_("<b>%s</b> requests your presence at a meeting."); itip_title = U_("Meeting Proposal"); - options = get_request_options (); + options = get_request_options (priv->event_client ? FALSE : TRUE); break; case ICAL_METHOD_ADD: itip_desc = U_("<b>%s</b> wishes to add to an existing meeting."); itip_title = U_("Meeting Update"); - options = get_publish_options (); + options = get_publish_options (priv->event_client ? FALSE : TRUE); break; case ICAL_METHOD_REFRESH: itip_desc = U_("<b>%s</b> wishes to receive the latest meeting information."); @@ -1029,21 +1182,23 @@ show_current_todo (EItipControl *itip) priv = itip->priv; + priv->task_client = find_server (priv->task_clients, priv->comp); + switch (priv->method) { case ICAL_METHOD_PUBLISH: itip_desc = U_("<b>%s</b> has published task information."); itip_title = U_("Task Information"); - options = get_publish_options (); + options = get_publish_options (priv->task_client ? FALSE : TRUE); break; case ICAL_METHOD_REQUEST: itip_desc = U_("<b>%s</b> requests you perform a task."); itip_title = U_("Task Proposal"); - options = get_request_options (); + options = get_request_options (priv->task_client ? FALSE : TRUE); break; case ICAL_METHOD_ADD: itip_desc = U_("<b>%s</b> wishes to add to an existing task."); itip_title = U_("Task Update"); - options = get_publish_options (); + options = get_publish_options (priv->task_client ? FALSE : TRUE); break; case ICAL_METHOD_REFRESH: itip_desc = U_("<b>%s</b> wishes to receive the latest task information."); @@ -1179,6 +1334,12 @@ show_current (EItipControl *itip) if (priv->comp) gtk_object_unref (GTK_OBJECT (priv->comp)); + if (priv->event_client != NULL) + gtk_object_unref (GTK_OBJECT (priv->event_client)); + priv->event_client = NULL; + if (priv->task_client != NULL) + gtk_object_unref (GTK_OBJECT (priv->task_client)); + priv->task_client = NULL; /* Strip out alarms for security purposes */ alarm_iter = icalcomponent_begin_component (priv->ical_comp, ICAL_VALARM_COMPONENT); @@ -1414,7 +1575,7 @@ update_attendee_status (EItipControl *itip) EItipControlPrivate *priv; CalClient *client; CalClientGetStatus status; - CalComponent *comp; + CalComponent *comp = NULL; CalComponentVType type; const char *uid; GtkWidget *dialog; @@ -1427,6 +1588,12 @@ update_attendee_status (EItipControl *itip) else client = priv->event_client; + if (client == NULL) { + dialog = gnome_warning_dialog (_("Attendee status can not be updated " + "because the item no longer exists")); + goto cleanup; + } + /* Obtain our version */ cal_component_get_uid (priv->comp, &uid); status = cal_client_get_object (client, uid, &comp); @@ -1447,7 +1614,6 @@ update_attendee_status (EItipControl *itip) "attendee. Add as an attendee?"), NULL, NULL); if (gnome_dialog_run_and_close (GNOME_DIALOG (dialog)) == GNOME_YES) { - icalparameter *param; change_status (cal_component_get_icalcomponent (comp), itip_strip_mailto (a->value), a->status); @@ -1478,7 +1644,8 @@ update_attendee_status (EItipControl *itip) } cleanup: - gtk_object_unref (GTK_OBJECT (comp)); + if (comp != NULL) + gtk_object_unref (GTK_OBJECT (comp)); gnome_dialog_run_and_close (GNOME_DIALOG (dialog)); } @@ -1499,6 +1666,9 @@ remove_item (EItipControl *itip) else client = priv->event_client; + if (client == NULL) + return; + cal_component_get_uid (priv->comp, &uid); if (cal_client_remove_object (client, uid)) { dialog = gnome_ok_dialog (_("Removal Complete")); @@ -1621,6 +1791,28 @@ next_clicked_cb (GtkWidget *widget, gpointer data) #endif static void +button_selected_cb (EvolutionFolderSelectorButton *button, GNOME_Evolution_Folder *folder, gpointer data) +{ + EItipControl *itip = E_ITIP_CONTROL (data); + EItipControlPrivate *priv; + CalComponentVType type; + char *uri; + + priv = itip->priv; + + type = cal_component_get_vtype (priv->comp); + if (type == CAL_COMPONENT_TODO) + uri = cal_util_expand_uri (folder->physicalUri, TRUE); + else + uri = cal_util_expand_uri (folder->physicalUri, FALSE); + + gtk_object_unref (GTK_OBJECT (priv->event_client)); + priv->event_client = start_calendar_server (uri); + + g_free (uri); +} + +static void url_requested_cb (GtkHTML *html, const gchar *url, GtkHTMLStream *handle, gpointer data) { unsigned char buffer[4096]; int len, fd; @@ -1651,6 +1843,46 @@ url_requested_cb (GtkHTML *html, const gchar *url, GtkHTMLStream *handle, gpoint g_free (path); } +static gboolean +object_requested_cb (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) +{ + EItipControl *itip = E_ITIP_CONTROL (data); + EItipControlPrivate *priv; + GtkWidget *button; + CalComponentVType vtype; + + priv = itip->priv; + + vtype = cal_component_get_vtype (priv->comp); + + switch (vtype) { + case CAL_COMPONENT_EVENT: + button = evolution_folder_selector_button_new ( + global_shell_client, _("Select Calendar Folder"), + calendar_config_default_calendar_folder (), + calendar_types); + priv->event_client = start_default_server (FALSE); + break; + case CAL_COMPONENT_TODO: + button = evolution_folder_selector_button_new ( + global_shell_client, _("Select Tasks Folder"), + calendar_config_default_tasks_folder (), + tasks_types); + priv->task_client = start_default_server (TRUE); + break; + default: + button = NULL; + } + + gtk_signal_connect (GTK_OBJECT (button), "selected", + button_selected_cb, itip); + + gtk_container_add (GTK_CONTAINER (eb), button); + gtk_widget_show (button); + + return TRUE; +} + static void ok_clicked_cb (GtkHTML *html, const gchar *method, const gchar *url, const gchar *encoding, gpointer data) { |