aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/e-itip-control.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/e-itip-control.c')
-rw-r--r--calendar/gui/e-itip-control.c300
1 files changed, 266 insertions, 34 deletions
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>&nbsp"
+ char *html;
+
+ html = g_strdup_printf ("<form><b>%s</b>&nbsp"
"<select NAME=\"action\" SIZE=\"1\"> "
"<option VALUE=\"U\">%s</option>"
"</select>&nbsp &nbsp "
@@ -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>&nbsp"
+ char *html;
+
+ html = g_strdup_printf ("<form><b>%s</b>&nbsp"
"<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)
{