aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/itip-formatter/ChangeLog50
-rw-r--r--plugins/itip-formatter/itip-formatter.c382
-rw-r--r--plugins/itip-formatter/itip-view.c401
-rw-r--r--plugins/itip-formatter/itip-view.h30
4 files changed, 749 insertions, 114 deletions
diff --git a/plugins/itip-formatter/ChangeLog b/plugins/itip-formatter/ChangeLog
index 82154dfc23..d4b47dc96a 100644
--- a/plugins/itip-formatter/ChangeLog
+++ b/plugins/itip-formatter/ChangeLog
@@ -1,3 +1,53 @@
+2005-01-03 JP Rosevear <jpr@novell.com>
+
+ * itip-view.h: new protos, signal
+
+ * itip-view.c (set_info_items): be more generic so both upper and
+ lower setting can use it
+ (set_upper_info_items): set the upper info items
+ (set_lower_info_items): ditto for lower items
+ (itip_view_destroy): clear both sets of info items
+ (itip_view_class_init): add source selected signalo
+ (itip_view_init): add separate upper and lower info item areas and
+ a detail area
+ (itip_view_add_upper_info_item): add upper info item
+ (itip_view_remove_upper_info_item): remove a singal upper area
+ info item
+ (itip_view_clear_upper_info_items): clear them all
+ (itip_view_add_lower_info_item): as above
+ (itip_view_remove_lower_info_item): ditto
+ (itip_view_clear_lower_info_items): ditto
+ (source_selected_cb): emit the source selected signal when the
+ source in the option menu changes
+ (itip_view_set_source_list): take a source list and create an
+ e-source-option-menu if its non-null
+ (itip_view_get_source_list): get source list
+ (itip_view_set_source): set a specific source in the source option
+ menu
+ (itip_view_get_source): obtain that source
+ (itip_view_set_rsvp): get the rsvp status
+ (itip_view_get_rsvp): set it
+ (itip_view_set_show_rsvp): set visibility of rsvp check box
+ (itip_view_get_show_rsvp): get the visibility of rsvp check box
+ (itip_view_set_buttons_sensitive): set button sensitivity
+ (itip_view_get_buttons_sensitive): get button sensitivity
+
+ * itip-formatter.c (find_my_address): find the user's address in
+ the list of attendees
+ (set_buttons_sensitive): set the action buttons sensitivity
+ appropriately
+ (cal_opened_cb): use above
+ (start_calendar_server): ditto
+ (start_calendar_server_by_uid): de-sensitize buttons to start
+ (source_selected_cb): ditto
+ (find_cal_opened_cb): check for conflicting appointments; set
+ informative info area items
+ (find_server): create the sexp for determining conflicts
+ (update_item): oset informative info area items
+ (view_response_cb): implement some of the responses, start on
+ implementing rsvp
+ (format_itip_object): load the source lists properly
+
2004-12-29 JP Rosevear <jpr@novell.com>
* itip-view.h: new protos
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index 7c8a7ed9ab..871c8cb3bf 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -43,6 +43,7 @@
#include <mail/em-format-html.h>
#include <e-util/e-account-list.h>
#include <e-util/e-icon-factory.h>
+#include <calendar/gui/calendar-config.h>
#include <calendar/gui/itip-utils.h>
#include <calendar/common/authentication.h>
#include "itip-view.h"
@@ -52,12 +53,6 @@
void format_itip (EPlugin *ep, EMFormatHookTarget *target);
GtkWidget *itip_formatter_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data);
-/* FIXME We should include these properly */
-icaltimezone *calendar_config_get_icaltimezone (void);
-void calendar_config_init (void);
-char *calendar_config_get_primary_calendar (void);
-char *calendar_config_get_primary_tasks (void);
-
typedef struct {
EMFormatHTMLPObject pobject;
@@ -69,8 +64,6 @@ typedef struct {
ECal *current_ecal;
ECalSourceType type;
- gboolean rsvp;
-
char *vcalendar;
ECalComponent *comp;
icalcomponent *main_comp;
@@ -78,7 +71,9 @@ typedef struct {
icalcomponent *top_level;
icalcompiter iter;
icalproperty_method method;
-
+ time_t start_time;
+ time_t end_time;
+
int current;
int total;
@@ -91,19 +86,130 @@ typedef struct {
gchar *delegator_name;
gchar *my_address;
gint view_only;
+
+ guint progress_info_id;
} FormatItipPObject;
typedef struct {
FormatItipPObject *pitip;
char *uid;
- int count;
+
+ char *sexp;
+
gboolean show_selector;
+
+ int count;
} EItipControlFindData;
typedef void (* FormatItipOpenFunc) (ECal *ecal, ECalendarStatus status, gpointer data);
static void
+find_my_address (FormatItipPObject *pitip, icalcomponent *ical_comp, icalparameter_partstat *status)
+{
+ icalproperty *prop;
+ char *my_alt_address = NULL;
+
+ for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY);
+ prop != NULL;
+ prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY)) {
+ icalvalue *value;
+ icalparameter *param;
+ const char *attendee, *name;
+ char *attendee_clean, *name_clean;
+ EIterator *it;
+
+ value = icalproperty_get_value (prop);
+ if (value != NULL) {
+ attendee = icalvalue_get_string (value);
+ attendee_clean = g_strdup (itip_strip_mailto (attendee));
+ attendee_clean = g_strstrip (attendee_clean);
+ } else {
+ attendee = NULL;
+ attendee_clean = NULL;
+ }
+
+ param = icalproperty_get_first_parameter (prop, ICAL_CN_PARAMETER);
+ if (param != NULL) {
+ name = icalparameter_get_cn (param);
+ name_clean = g_strdup (name);
+ name_clean = g_strstrip (name_clean);
+ } else {
+ name = NULL;
+ name_clean = NULL;
+ }
+
+ if (pitip->delegator_address) {
+ char *delegator_clean;
+
+ delegator_clean = g_strdup (itip_strip_mailto (attendee));
+ delegator_clean = g_strstrip (delegator_clean);
+
+ /* If the mailer told us the address to use, use that */
+ if (delegator_clean != NULL
+ && !g_ascii_strcasecmp (attendee_clean, delegator_clean)) {
+ pitip->my_address = g_strdup (itip_strip_mailto (pitip->delegator_address));
+ pitip->my_address = g_strstrip (pitip->my_address);
+
+ if (status) {
+ param = icalproperty_get_first_parameter (prop, ICAL_PARTSTAT_PARAMETER);
+ *status = param ? icalparameter_get_partstat (param) : ICAL_PARTSTAT_NEEDSACTION;
+ }
+ }
+
+ g_free (delegator_clean);
+ } else {
+ it = e_list_get_iterator((EList *)pitip->accounts);
+ while (e_iterator_is_valid(it)) {
+ const EAccount *account = e_iterator_get(it);
+
+ /* Check for a matching address */
+ if (attendee_clean != NULL
+ && !g_ascii_strcasecmp (account->id->address, attendee_clean)) {
+ pitip->my_address = g_strdup (account->id->address);
+ if (status) {
+ param = icalproperty_get_first_parameter (prop, ICAL_PARTSTAT_PARAMETER);
+ *status = param ? icalparameter_get_partstat (param) : ICAL_PARTSTAT_NEEDSACTION;
+ }
+ g_free (attendee_clean);
+ g_free (name_clean);
+ g_free (my_alt_address);
+ g_object_unref(it);
+ return;
+ }
+
+ /* Check for a matching cname to fall back on */
+ if (name_clean != NULL
+ && !g_ascii_strcasecmp (account->id->name, name_clean))
+ my_alt_address = g_strdup (attendee_clean);
+
+ e_iterator_next(it);
+ }
+ g_object_unref(it);
+ }
+
+ g_free (attendee_clean);
+ g_free (name_clean);
+ }
+
+ pitip->my_address = my_alt_address;
+ if (status)
+ *status = ICAL_PARTSTAT_NEEDSACTION;
+}
+
+static void
+set_buttons_sensitive (FormatItipPObject *pitip)
+{
+ gboolean read_only = TRUE;
+
+ if (pitip->current_ecal)
+ e_cal_is_read_only (pitip->current_ecal, &read_only, NULL);
+
+ itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), pitip->current_ecal != NULL && !read_only);
+}
+
+
+static void
cal_opened_cb (ECal *ecal, ECalendarStatus status, gpointer data)
{
FormatItipPObject *pitip = data;
@@ -117,7 +223,11 @@ cal_opened_cb (ECal *ecal, ECalendarStatus status, gpointer data)
g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, cal_opened_cb, NULL);
if (status != E_CALENDAR_STATUS_OK) {
- itip_view_set_progress (ITIP_VIEW (pitip->view), "Failed to load at least one calendar");
+ char *warn;
+
+ warn = g_strdup_printf ("Failed to load the calendar '%s'", e_source_peek_name (source));
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_WARNING, warn);
+ g_free (warn);
g_hash_table_remove (pitip->ecals[source_type], e_source_peek_uid (source));
@@ -129,7 +239,7 @@ cal_opened_cb (ECal *ecal, ECalendarStatus status, gpointer data)
pitip->current_ecal = ecal;
-// set_ok_sens (itip);
+ set_buttons_sensitive (pitip);
}
static ECal *
@@ -141,8 +251,11 @@ start_calendar_server (FormatItipPObject *pitip, ESource *source, ECalSourceType
if (ecal) {
pitip->current_ecal = ecal;
- itip_view_set_progress (ITIP_VIEW (pitip->view), NULL);
-// set_ok_sens (itip);
+ itip_view_remove_lower_info_item (ITIP_VIEW (pitip->view), pitip->progress_info_id);
+ pitip->progress_info_id = 0;
+
+ set_buttons_sensitive (pitip);
+
return ecal;
}
@@ -161,6 +274,8 @@ start_calendar_server_by_uid (FormatItipPObject *pitip, const char *uid, ECalSou
{
int i;
+ itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
+
for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++) {
ESource *source;
@@ -173,13 +288,11 @@ start_calendar_server_by_uid (FormatItipPObject *pitip, const char *uid, ECalSou
}
static void
-source_selected_cb (ESourceOptionMenu *esom, ESource *source, gpointer data)
+source_selected_cb (ItipView *view, ESource *source, gpointer data)
{
FormatItipPObject *pitip = data;
- g_message ("Source selected");
-
- /* FIXME turn off buttons while we check the calendar for being open? */
+ itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
start_calendar_server (pitip, source, pitip->type, cal_opened_cb, pitip);
}
@@ -193,7 +306,8 @@ find_cal_opened_cb (ECal *ecal, ECalendarStatus status, gpointer data)
ECalSourceType source_type;
icalcomponent *icalcomp;
icaltimezone *zone;
-
+ GList *objects = NULL;
+
source_type = e_cal_get_source_type (ecal);
source = e_cal_get_source (ecal);
@@ -202,18 +316,54 @@ find_cal_opened_cb (ECal *ecal, ECalendarStatus status, gpointer data)
g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, find_cal_opened_cb, NULL);
if (status != E_CALENDAR_STATUS_OK) {
+ char *warn;
+
+ /* FIXME Do we really want to warn here? If we fail
+ * to find the item, this won't be cleared but the
+ * selector might be shown */
+ warn = g_strdup_printf ("Failed to load the calendar '%s'", e_source_peek_name (source));
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_WARNING, warn);
+ g_free (warn);
+
g_hash_table_remove (pitip->ecals[source_type], e_source_peek_uid (source));
goto cleanup;
}
+ /* Check for conflicts */
+ /* FIXME Limit the calendars checked for conflicts? */
+ /* FIXME What happens for recurring conflicts? */
+ if (e_cal_get_object_list (ecal, fd->sexp, &objects, NULL) && g_list_length (objects) > 0) {
+ char *info;
+
+ g_message ("Conflicting item found");
+ info = g_strdup_printf ("An appointment in the calendar '%s' conflicts with this meeting", e_source_peek_name (source));
+ itip_view_add_upper_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_WARNING, info);
+ g_free (info);
+
+ e_cal_free_object_list (objects);
+ } else {
+ g_message ("Query failed");
+ }
+
if (e_cal_get_object (ecal, fd->uid, NULL, &icalcomp, NULL)) {
+ char *info;
+
icalcomponent_free (icalcomp);
pitip->current_ecal = ecal;
- itip_view_set_progress (ITIP_VIEW (pitip->view), NULL);
-// set_ok_sens (fd->itip);
+ /* We clear everything because we don't really care
+ * about any other info/warnings now we found an
+ * existing versions */
+ itip_view_clear_lower_info_items (ITIP_VIEW (pitip->view));
+ pitip->progress_info_id = 0;
+
+ info = g_strdup_printf ("Found the appointment in the calendar '%s'", e_source_peek_name (source));
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, info);
+ g_free (info);
+
+ set_buttons_sensitive (pitip);
}
zone = calendar_config_get_icaltimezone ();
@@ -221,12 +371,11 @@ find_cal_opened_cb (ECal *ecal, ECalendarStatus status, gpointer data)
cleanup:
if (fd->count == 0) {
- /* FIXME the box check is to see if the buttons are displayed i think */
- if (fd->show_selector && !pitip->current_ecal /*&& pitip->vbox*/) {
- GtkWidget *esom;
+ if (fd->show_selector && !pitip->current_ecal) {
ESource *source = NULL;
char *uid;
+ /* FIXME Should we take into account any sources we failed to open? */
switch (pitip->type) {
case E_CAL_SOURCE_TYPE_EVENT:
uid = calendar_config_get_primary_calendar ();
@@ -248,18 +397,23 @@ find_cal_opened_cb (ECal *ecal, ECalendarStatus status, gpointer data)
if (!source)
source = e_source_list_peek_source_any (pitip->source_lists[pitip->type]);
- g_message ("Picking any source");
- esom = e_source_option_menu_new (pitip->source_lists[pitip->type]);
- /* FIXME used to force the data to be kept alive, still do this? */
- g_signal_connect (esom, "source_selected", G_CALLBACK (source_selected_cb), fd->pitip);
+ itip_view_set_source_list (ITIP_VIEW (pitip->view), pitip->source_lists[pitip->type]);
+ g_signal_connect (pitip->view, "source_selected", G_CALLBACK (source_selected_cb), pitip);
- //gtk_box_pack_start (GTK_BOX (pitip->vbox), esom, FALSE, TRUE, 0);
- gtk_widget_show (esom);
+ /* The only method that RSVP makes sense for is REQUEST */
+ /* FIXME Default to the suggestion for RSVP for my attendee */
+ itip_view_set_show_rsvp (ITIP_VIEW (pitip->view), pitip->method == ICAL_METHOD_REQUEST ? TRUE : FALSE );
+
+ itip_view_remove_lower_info_item (ITIP_VIEW (pitip->view), pitip->progress_info_id);
+ pitip->progress_info_id = 0;
- /* FIXME What if there is no source? */
if (source) {
- e_source_option_menu_select (E_SOURCE_OPTION_MENU (esom), source);
- itip_view_set_progress (ITIP_VIEW (pitip->view), NULL);
+ itip_view_set_source (ITIP_VIEW (pitip->view), source);
+
+ /* FIXME Shouldn't the buttons be sensitized here? */
+ } else {
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, "Unable to find any calendars");
+ itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
}
} else {
/* FIXME Display error message to user */
@@ -279,7 +433,10 @@ find_server (FormatItipPObject *pitip, ECalComponent *comp, gboolean show_select
e_cal_component_get_uid (comp, &uid);
- itip_view_set_progress (ITIP_VIEW (pitip->view), "Searching for an existing version of this appointment");
+ pitip->progress_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS,
+ "Searching for an existing version of this appointment");
+
+ itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
groups = e_source_list_peek_groups (pitip->source_lists[pitip->type]);
for (l = groups; l; l = l->next) {
@@ -296,10 +453,23 @@ find_server (FormatItipPObject *pitip, ECalComponent *comp, gboolean show_select
source = m->data;
if (!fd) {
+ char *start, *end;
+
fd = g_new0 (EItipControlFindData, 1);
fd->pitip = pitip;
fd->uid = g_strdup (uid);
fd->show_selector = show_selector;
+
+ if (pitip->start_time && pitip->end_time) {
+ start = isodate_from_time_t (pitip->start_time);
+ end = isodate_from_time_t (pitip->end_time);
+
+ fd->sexp = g_strdup_printf ("(occur-in-time-range? (make-time \"%s\") (make-time \"%s\"))", start, end);
+ g_message ("Sexp is %s", fd->sexp);
+ }
+
+ g_free (start);
+ g_free (end);
}
fd->count++;
@@ -309,8 +479,10 @@ find_server (FormatItipPObject *pitip, ECalComponent *comp, gboolean show_select
}
static void
-cleanup_ecal (ECal *ecal)
+cleanup_ecal (gpointer data)
{
+ ECal *ecal = data;
+
/* Clean up any signals */
g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, cal_opened_cb, NULL);
g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, find_cal_opened_cb, NULL);
@@ -398,12 +570,11 @@ change_status (icalcomponent *ical_comp, const char *address, icalparameter_part
}
static void
-update_item (FormatItipPObject *pitip)
+update_item (FormatItipPObject *pitip, ItipViewResponse response)
{
struct icaltimetype stamp;
icalproperty *prop;
icalcomponent *clone;
-// GtkWidget *dialog;
GError *error = NULL;
/* Set X-MICROSOFT-CDO-REPLYTIME to record the time at which
@@ -425,14 +596,40 @@ update_item (FormatItipPObject *pitip)
icalcomponent_set_method (pitip->top_level, pitip->method);
if (!e_cal_receive_objects (pitip->current_ecal, pitip->top_level, &error)) {
- /* FIXME e-error */
-// dialog = gnome_warning_dialog (error->message);
+ /* FIXME Really use e_error? or should it just be an info item */
+// e_error_run (NULL, "org.gnome.itip-formatter:meeting-update-failed", error->message, NULL);
g_error_free (error);
} else {
- /* FIXME I think we should do nothing */
-// dialog = gnome_ok_dialog (_("Update complete\n"));
+ ESource *source;
+ char *info;
+
+ /* FIXME This makes the UI look ugly */
+ itip_view_set_source_list (ITIP_VIEW (pitip->view), NULL);
+
+ itip_view_clear_lower_info_items (ITIP_VIEW (pitip->view));
+ source = e_cal_get_source (pitip->current_ecal);
+
+ switch (response) {
+ case ITIP_VIEW_RESPONSE_ACCEPT:
+ info = g_strdup_printf ("Sent to calendar '%s' as accepted", e_source_peek_name (source));
+ break;
+ case ITIP_VIEW_RESPONSE_TENTATIVE:
+ info = g_strdup_printf ("Sent to calendar '%s' as tentative", e_source_peek_name (source));
+ break;
+ case ITIP_VIEW_RESPONSE_DECLINE:
+ /* FIXME some calendars just might not save it at all, is this accurate? */
+ info = g_strdup_printf ("Sent to calendar '%s' as declined", e_source_peek_name (source));
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, info);
+ g_free (info);
+
+ /* FIXME Should we hide or desensitize the buttons now? */
}
-// gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
icalcomponent_remove_component (pitip->top_level, clone);
}
@@ -467,18 +664,12 @@ extract_itip_data (FormatItipPObject *pitip)
icalcomponent *tz_comp;
icalcompiter tz_iter;
-/* FIXME try and match sender with organizer/attendee/sentby?
- pd->from_address = camel_address_encode ((CamelAddress *)from);
- g_message ("Detected from address %s", pd->from_address);
-*/
-
content = camel_medium_get_content_object ((CamelMedium *) pitip->pobject.part);
mem = camel_stream_mem_new ();
camel_data_wrapper_write_to_stream (content, mem);
pitip->vcalendar = g_strndup (((CamelStreamMem *) mem)->buffer->data, ((CamelStreamMem *) mem)->buffer->len);
- /* FIXME unref the content object as well? */
camel_object_unref (mem);
pitip->top_level = e_cal_util_new_top_level ();
@@ -553,7 +744,7 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
ICAL_PARTSTAT_ACCEPTED);
if (status) {
e_cal_component_rescan (pitip->comp);
- update_item (pitip);
+ update_item (pitip, response);
}
break;
case ITIP_VIEW_RESPONSE_TENTATIVE:
@@ -561,7 +752,7 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
ICAL_PARTSTAT_TENTATIVE);
if (status) {
e_cal_component_rescan (pitip->comp);
- update_item (pitip);
+ update_item (pitip, response);
}
break;
case ITIP_VIEW_RESPONSE_DECLINE:
@@ -569,12 +760,69 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
ICAL_PARTSTAT_DECLINED);
if (status) {
e_cal_component_rescan (pitip->comp);
- update_item (pitip);
+ update_item (pitip, response);
}
break;
default:
break;
}
+
+ if (e_cal_get_save_schedules (pitip->current_ecal))
+ return;
+
+ if (itip_view_get_rsvp (ITIP_VIEW (pitip->view)) && status) {
+ ECalComponent *comp = NULL;
+ ECalComponentVType vtype;
+ icalcomponent *ical_comp;
+ icalproperty *prop;
+ icalvalue *value;
+ const char *attendee;
+ GSList *l, *list = NULL;
+
+ comp = e_cal_component_clone (pitip->comp);
+ if (comp == NULL)
+ return;
+
+ vtype = e_cal_component_get_vtype (comp);
+
+ if (pitip->my_address == NULL)
+ find_my_address (pitip, pitip->ical_comp, NULL);
+ g_assert (pitip->my_address != NULL);
+
+ ical_comp = e_cal_component_get_icalcomponent (comp);
+
+ for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY);
+ prop != NULL;
+ prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY))
+ {
+ char *text;
+
+ value = icalproperty_get_value (prop);
+ if (!value)
+ continue;
+
+ attendee = icalvalue_get_string (value);
+
+ text = g_strdup (itip_strip_mailto (attendee));
+ text = g_strstrip (text);
+ if (g_strcasecmp (pitip->my_address, text))
+ list = g_slist_prepend (list, prop);
+ g_free (text);
+ }
+
+ for (l = list; l; l = l->next) {
+ prop = l->data;
+ icalcomponent_remove_property (ical_comp, prop);
+ icalproperty_free (prop);
+ }
+ g_slist_free (list);
+
+ e_cal_component_rescan (comp);
+ itip_send_comp (E_CAL_COMPONENT_METHOD_REPLY, comp, pitip->current_ecal, pitip->top_level);
+
+ g_object_unref (comp);
+
+ }
}
static gboolean
@@ -592,7 +840,7 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
/* Source Lists and open ecal clients */
for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++) {
- if (!e_cal_get_sources (&pitip->source_lists[E_CAL_SOURCE_TYPE_EVENT], E_CAL_SOURCE_TYPE_EVENT, NULL))
+ if (!e_cal_get_sources (&pitip->source_lists[i], i, NULL))
/* FIXME More error handling? */
pitip->source_lists[i] = NULL;
@@ -642,6 +890,11 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
/* FIXME, do i need to strip the sentby somehow? Maybe with camel? */
itip_view_set_sentby (ITIP_VIEW (pitip->view), organizer.sentby);
+/* FIXME try and match sender with organizer/attendee/sentby?
+ pd->from_address = camel_address_encode ((CamelAddress *)from);
+ g_message ("Detected from address %s", pd->from_address);
+*/
+
e_cal_component_get_summary (pitip->comp, &text);
itip_view_set_summary (ITIP_VIEW (pitip->view), text.value ? text.value : _("None"));
@@ -668,10 +921,12 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
to_zone = calendar_config_get_icaltimezone ();
e_cal_component_get_dtstart (pitip->comp, &datetime);
+ pitip->start_time = 0;
if (datetime.value) {
struct tm start_tm;
- /* FIXME Handle tzid that is not in the component - treat as "local" time */
+ /* If the timezone is not in the component, guess the local time */
+ /* Should we guess if the timezone is an olsen name somehow? */
if (!datetime.value->is_utc && datetime.tzid)
from_zone = icalcomponent_get_timezone (pitip->top_level, datetime.tzid);
else
@@ -680,28 +935,34 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
start_tm = icaltimetype_to_tm_with_zone (datetime.value, from_zone, to_zone);
itip_view_set_start (ITIP_VIEW (pitip->view), &start_tm);
+ pitip->start_time = icaltime_as_timet_with_zone (*datetime.value, from_zone);
}
e_cal_component_free_datetime (&datetime);
e_cal_component_get_dtend (pitip->comp, &datetime);
+ pitip->end_time = 0;
if (datetime.value) {
struct tm end_tm;
-
- /* FIXME Handle tzid that is not in the component - treat as "local" time */
+
+ /* If the timezone is not in the component, guess the local time */
+ /* Should we guess if the timezone is an olsen name somehow? */
if (!datetime.value->is_utc && datetime.tzid)
from_zone = icalcomponent_get_timezone (pitip->top_level, datetime.tzid);
else
from_zone = NULL;
end_tm = icaltimetype_to_tm_with_zone (datetime.value, from_zone, to_zone);
-
+
itip_view_set_end (ITIP_VIEW (pitip->view), &end_tm);
+ pitip->end_time = icaltime_as_timet_with_zone (*datetime.value, from_zone);
}
e_cal_component_free_datetime (&datetime);
- /* Info area items */
- itip_view_add_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, "This meeting occurs weekly indefinitely");
- itip_view_add_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_WARNING, "An appointment in the calendar conflicts with this meeting");
+ /* Recurrence info */
+ /* FIXME Better recurring description */
+ if (e_cal_component_has_recurrences (pitip->comp)) {
+ itip_view_add_upper_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, "This meeting recurs");
+ }
gtk_container_add (GTK_CONTAINER (eb), pitip->view);
gtk_widget_set_usize (pitip->view, 640, -1);
@@ -719,11 +980,10 @@ format_itip (EPlugin *ep, EMFormatHookTarget *target)
{
FormatItipPObject *pitip;
- calendar_config_init ();
-
pitip = (FormatItipPObject *) em_format_html_add_pobject ((EMFormatHTML *) target->format, sizeof (FormatItipPObject), CLASSID, target->part, format_itip_object);
// FIXME set the free function
// pitip->object.free = pitip_free;
+
camel_stream_printf (target->stream, "<table border=0 width=\"100%%\" cellpadding=3><tr>");
camel_stream_printf (target->stream, "<td valign=top><object classid=\"%s\"></object></td><td width=100%% valign=top>", CLASSID);
camel_stream_printf (target->stream, "</td></tr></table>");
diff --git a/plugins/itip-formatter/itip-view.c b/plugins/itip-formatter/itip-view.c
index a1a1e8c12a..4b9f161e30 100644
--- a/plugins/itip-formatter/itip-view.c
+++ b/plugins/itip-formatter/itip-view.c
@@ -33,6 +33,8 @@
#include <camel/camel-stream-mem.h>
#include <camel/camel-medium.h>
#include <camel/camel-mime-message.h>
+#include <libedataserver/e-time-utils.h>
+#include <libedataserverui/e-source-option-menu.h>
#include <libecal/e-cal.h>
#include <gtkhtml/gtkhtml-embedded.h>
#include <mail/em-format-hook.h>
@@ -50,8 +52,9 @@ G_DEFINE_TYPE (ItipView, itip_view, GTK_TYPE_HBOX);
typedef struct {
ItipViewInfoItemType type;
-
char *message;
+
+ guint id;
} ItipViewInfoItem;
struct _ItipViewPrivate {
@@ -78,21 +81,33 @@ struct _ItipViewPrivate {
GtkWidget *end_label;
struct tm *end_tm;
- GtkWidget *info_box;
- GSList *info_items;
-
+ GtkWidget *upper_info_box;
+ GSList *upper_info_items;
+
+ GtkWidget *lower_info_box;
+ GSList *lower_info_items;
+
+ guint next_info_item_id;
+
GtkWidget *description_label;
char *description;
- GtkWidget *progress_box;
- GtkWidget *progress_label;
- char *progress;
+ GtkWidget *details_box;
+
+ GtkWidget *esom;
+ GtkWidget *esom_header;
+ ESourceList *source_list;
+ GtkWidget *rsvp_check;
+ gboolean rsvp_show;
+
GtkWidget *button_box;
+ gboolean buttons_sensitive;
};
/* Signal IDs */
enum {
+ SOURCE_SELECTED,
RESPONSE,
LAST_SIGNAL
};
@@ -402,16 +417,13 @@ set_end_text (ItipView *view)
}
static void
-set_info_items (ItipView *view)
+set_info_items (GtkWidget *info_box, GSList *info_items)
{
- ItipViewPrivate *priv;
GSList *l;
- priv = view->priv;
-
- gtk_container_foreach (GTK_CONTAINER (priv->info_box), (GtkCallback) gtk_widget_destroy, NULL);
+ gtk_container_foreach (GTK_CONTAINER (info_box), (GtkCallback) gtk_widget_destroy, NULL);
- for (l = priv->info_items; l; l = l->next) {
+ for (l = info_items; l; l = l->next) {
ItipViewInfoItem *item = l->data;
GtkWidget *hbox, *image, *label;
@@ -427,6 +439,9 @@ set_info_items (ItipView *view)
case ITIP_VIEW_INFO_ITEM_TYPE_ERROR:
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_SMALL_TOOLBAR);
break;
+ case ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS:
+ image = e_icon_factory_get_image ("stock_animation", E_ICON_SIZE_BUTTON);
+ break;
case ITIP_VIEW_INFO_ITEM_TYPE_NONE:
default:
image = NULL;
@@ -442,21 +457,28 @@ set_info_items (ItipView *view)
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 6);
gtk_widget_show (hbox);
- gtk_box_pack_start (GTK_BOX (priv->info_box), hbox, FALSE, FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (info_box), hbox, FALSE, FALSE, 6);
}
}
static void
-set_progress_text (ItipView *view)
+set_upper_info_items (ItipView *view)
{
ItipViewPrivate *priv;
-
+
priv = view->priv;
- g_message ("Setting progress to: %s", priv->progress);
- gtk_label_set_text (GTK_LABEL (priv->progress_label), priv->progress);
+ set_info_items (priv->upper_info_box, priv->upper_info_items);
+}
- priv->progress ? gtk_widget_show (priv->progress_box) : gtk_widget_hide (priv->progress_box);
+static void
+set_lower_info_items (ItipView *view)
+{
+ ItipViewPrivate *priv;
+
+ priv = view->priv;
+
+ set_info_items (priv->lower_info_box, priv->lower_info_items);
}
#define DATA_RESPONSE_KEY "ItipView::button_response"
@@ -483,7 +505,7 @@ set_one_button (ItipView *view, char *label, char *stock_id, ItipViewResponse re
button = e_gtk_button_new_with_icon (label, stock_id);
g_object_set_data (G_OBJECT (button), DATA_RESPONSE_KEY, GINT_TO_POINTER (response));
gtk_widget_show (button);
- gtk_container_add (GTK_CONTAINER (priv->button_box), button);
+ gtk_container_add (GTK_CONTAINER (priv->button_box), button);
g_signal_connect (button, "clicked", G_CALLBACK (button_clicked_cb), view);
}
@@ -549,7 +571,8 @@ itip_view_destroy (GtkObject *object)
g_free (priv->start_tm);
g_free (priv->end_tm);
- itip_view_clear_info_items (view);
+ itip_view_clear_upper_info_items (view);
+ itip_view_clear_lower_info_items (view);
g_free (priv);
view->priv = NULL;
@@ -569,6 +592,15 @@ itip_view_class_init (ItipViewClass *klass)
gtkobject_class->destroy = itip_view_destroy;
+ signals[SOURCE_SELECTED] =
+ g_signal_new ("source_selected",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ItipViewClass, source_selected),
+ NULL, NULL,
+ gtk_marshal_NONE__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
signals[RESPONSE] =
g_signal_new ("response",
G_TYPE_FROM_CLASS (klass),
@@ -583,7 +615,7 @@ static void
itip_view_init (ItipView *view)
{
ItipViewPrivate *priv;
- GtkWidget *icon, *vbox, *separator, *table, *image;
+ GtkWidget *icon, *vbox, *separator, *table;
priv = g_new0 (ItipViewPrivate, 1);
view->priv = priv;
@@ -651,10 +683,10 @@ itip_view_init (ItipView *view)
gtk_table_attach (GTK_TABLE (table), priv->end_header, 0, 1, 3, 4, GTK_FILL, 0, 0, 0);
gtk_table_attach (GTK_TABLE (table), priv->end_label, 1, 2, 3, 4, GTK_FILL, 0, 0, 0);
- /* Info items */
- priv->info_box = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (priv->info_box);
- gtk_box_pack_start (GTK_BOX (vbox), priv->info_box, FALSE, FALSE, 6);
+ /* Upper Info items */
+ priv->upper_info_box = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (priv->upper_info_box);
+ gtk_box_pack_start (GTK_BOX (vbox), priv->upper_info_box, FALSE, FALSE, 6);
/* Description */
priv->description_label = gtk_label_new (NULL);
@@ -666,25 +698,27 @@ itip_view_init (ItipView *view)
gtk_widget_show (separator);
gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 6);
- /* Progress */
- priv->progress_box = gtk_hbox_new (FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), priv->progress_box, FALSE, FALSE, 6);
-
- image = e_icon_factory_get_image ("stock_animation", E_ICON_SIZE_BUTTON);
- gtk_widget_show (image);
- gtk_box_pack_start (GTK_BOX (priv->progress_box), image, FALSE, FALSE, 6);
+ /* Lower Info items */
+ priv->lower_info_box = gtk_vbox_new (FALSE, 0);
+ gtk_widget_show (priv->lower_info_box);
+ gtk_box_pack_start (GTK_BOX (vbox), priv->lower_info_box, FALSE, FALSE, 6);
- priv->progress_label = gtk_label_new (NULL);
- gtk_widget_show (priv->progress_label);
- gtk_misc_set_alignment (GTK_MISC (priv->progress_label), 0, 0.5);
- gtk_box_pack_start (GTK_BOX (priv->progress_box), priv->progress_label, FALSE, FALSE, 6);
+ /* Detail area */
+ priv->details_box = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (priv->details_box);
+ gtk_box_pack_start (GTK_BOX (vbox), priv->details_box, FALSE, FALSE, 6);
+ priv->rsvp_check = gtk_check_button_new_with_mnemonic ("Send _reply to sender");
+ gtk_box_pack_end (GTK_BOX (priv->details_box), priv->rsvp_check, FALSE, FALSE, 6);
+
/* The buttons for actions */
priv->button_box = gtk_hbutton_box_new ();
gtk_button_box_set_layout (GTK_BUTTON_BOX (priv->button_box), GTK_BUTTONBOX_END);
gtk_box_set_spacing (GTK_BOX (priv->button_box), 12);
gtk_widget_show (priv->button_box);
gtk_box_pack_start (GTK_BOX (vbox), priv->button_box, FALSE, FALSE, 6);
+
+ priv->buttons_sensitive = TRUE;
}
GtkWidget *
@@ -984,29 +1018,107 @@ itip_view_get_end (ItipView *view)
return priv->end_tm;
}
-void
-itip_view_add_info_item (ItipView *view, ItipViewInfoItemType type, const char *message)
+guint
+itip_view_add_upper_info_item (ItipView *view, ItipViewInfoItemType type, const char *message)
{
ItipViewPrivate *priv;
ItipViewInfoItem *item;
+ g_return_val_if_fail (view != NULL, 0);
+ g_return_val_if_fail (ITIP_IS_VIEW (view), 0);
+
+ priv = view->priv;
+
+ item = g_new0 (ItipViewInfoItem, 1);
+
+ item->type = type;
+ item->message = g_strdup (message);
+ item->id = priv->next_info_item_id++;
+
+ priv->upper_info_items = g_slist_append (priv->upper_info_items, item);
+
+ set_upper_info_items (view);
+
+ return item->id;
+}
+
+void
+itip_view_remove_upper_info_item (ItipView *view, guint id)
+{
+ ItipViewPrivate *priv;
+ GSList *l;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (ITIP_IS_VIEW (view));
+
+ priv = view->priv;
+
+ for (l = priv->upper_info_items; l; l = l->next) {
+ ItipViewInfoItem *item = l->data;
+
+ if (item->id == id) {
+ priv->upper_info_items = g_slist_remove (priv->upper_info_items, item);
+
+ g_free (item->message);
+ g_free (item);
+
+ set_upper_info_items (view);
+
+ return;
+ }
+ }
+}
+
+void
+itip_view_clear_upper_info_items (ItipView *view)
+{
+ ItipViewPrivate *priv;
+ GSList *l;
+
g_return_if_fail (view != NULL);
g_return_if_fail (ITIP_IS_VIEW (view));
priv = view->priv;
+ gtk_container_foreach (GTK_CONTAINER (priv->upper_info_box), (GtkCallback) gtk_widget_destroy, NULL);
+
+ for (l = priv->upper_info_items; l; l = l->next) {
+ ItipViewInfoItem *item = l->data;
+
+ g_free (item->message);
+ g_free (item);
+ }
+
+ g_slist_free (priv->upper_info_items);
+ priv->upper_info_items = NULL;
+}
+
+guint
+itip_view_add_lower_info_item (ItipView *view, ItipViewInfoItemType type, const char *message)
+{
+ ItipViewPrivate *priv;
+ ItipViewInfoItem *item;
+
+ g_return_val_if_fail (view != NULL, 0);
+ g_return_val_if_fail (ITIP_IS_VIEW (view), 0);
+
+ priv = view->priv;
+
item = g_new0 (ItipViewInfoItem, 1);
item->type = type;
item->message = g_strdup (message);
+ item->id = priv->next_info_item_id++;
- priv->info_items = g_slist_append (priv->info_items, item);
+ priv->lower_info_items = g_slist_append (priv->lower_info_items, item);
- set_info_items (view);
+ set_lower_info_items (view);
+
+ return item->id;
}
void
-itip_view_clear_info_items (ItipView *view)
+itip_view_remove_lower_info_item (ItipView *view, guint id)
{
ItipViewPrivate *priv;
GSList *l;
@@ -1016,18 +1128,144 @@ itip_view_clear_info_items (ItipView *view)
priv = view->priv;
- gtk_container_foreach (GTK_CONTAINER (priv->info_box), (GtkCallback) gtk_widget_destroy, NULL);
+ for (l = priv->lower_info_items; l; l = l->next) {
+ ItipViewInfoItem *item = l->data;
+
+ if (item->id == id) {
+ priv->lower_info_items = g_slist_remove (priv->lower_info_items, item);
+
+ g_free (item->message);
+ g_free (item);
+
+ set_lower_info_items (view);
+
+ return;
+ }
+ }
+}
- for (l = priv->info_items; l; l = l->next) {
+void
+itip_view_clear_lower_info_items (ItipView *view)
+{
+ ItipViewPrivate *priv;
+ GSList *l;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (ITIP_IS_VIEW (view));
+
+ priv = view->priv;
+
+ gtk_container_foreach (GTK_CONTAINER (priv->lower_info_box), (GtkCallback) gtk_widget_destroy, NULL);
+
+ for (l = priv->lower_info_items; l; l = l->next) {
ItipViewInfoItem *item = l->data;
g_free (item->message);
g_free (item);
}
+
+ g_slist_free (priv->lower_info_items);
+ priv->lower_info_items = NULL;
+}
+
+static void
+source_selected_cb (ESourceOptionMenu *esom, ESource *source, gpointer data)
+{
+ ItipView *view = data;
+
+ g_signal_emit (view, signals[SOURCE_SELECTED], 0, source);
+}
+
+void
+itip_view_set_source_list (ItipView *view, ESourceList *source_list)
+{
+ ItipViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (ITIP_IS_VIEW (view));
+
+ priv = view->priv;
+
+ if (priv->source_list)
+ g_object_unref (priv->source_list);
+
+ if (priv->esom)
+ gtk_widget_destroy (priv->esom);
+
+ if (!source_list) {
+ if (priv->esom_header)
+ gtk_widget_destroy (priv->esom_header);
+
+ priv->source_list = NULL;
+ priv->esom = NULL;
+ priv->esom_header = NULL;
+
+ return;
+ }
+
+ priv->source_list = g_object_ref (source_list);
+
+ priv->esom = e_source_option_menu_new (source_list);
+ gtk_widget_show (priv->esom);
+ g_signal_connect (priv->esom, "source_selected", G_CALLBACK (source_selected_cb), view);
+
+ if (!priv->esom_header) {
+ priv->esom_header = gtk_label_new_with_mnemonic (_("_Calendar:"));
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->esom_header), priv->esom);
+ gtk_widget_show (priv->esom_header);
+ }
+
+ gtk_box_pack_start (GTK_BOX (priv->details_box), priv->esom_header, FALSE, TRUE, 6);
+ gtk_box_pack_start (GTK_BOX (priv->details_box), priv->esom, FALSE, TRUE, 0);
+}
+
+ESourceList *
+itip_view_get_source_list (ItipView *view)
+{
+ ItipViewPrivate *priv;
+
+ g_return_val_if_fail (view != NULL, FALSE);
+ g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
+
+ priv = view->priv;
+
+ return priv->source_list;
+}
+
+void
+itip_view_set_source (ItipView *view, ESource *source)
+{
+ ItipViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (ITIP_IS_VIEW (view));
+
+ priv = view->priv;
+
+ if (!priv->esom)
+ return;
+
+ e_source_option_menu_select (E_SOURCE_OPTION_MENU (priv->esom), source);
+}
+
+ESource *
+itip_view_get_source (ItipView *view)
+{
+ ItipViewPrivate *priv;
+
+ g_return_val_if_fail (view != NULL, FALSE);
+ g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
+
+ priv = view->priv;
+
+ if (!priv->esom)
+ return NULL;
+
+ return e_source_option_menu_peek_selected (E_SOURCE_OPTION_MENU (priv->esom));
}
void
-itip_view_set_progress (ItipView *view, const char *message)
+itip_view_set_rsvp (ItipView *view, gboolean rsvp)
{
ItipViewPrivate *priv;
@@ -1035,12 +1273,77 @@ itip_view_set_progress (ItipView *view, const char *message)
g_return_if_fail (ITIP_IS_VIEW (view));
priv = view->priv;
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->rsvp_check), rsvp);
+}
- if (priv->progress)
- g_free (priv->progress);
+gboolean
+itip_view_get_rsvp (ItipView *view)
+{
+ ItipViewPrivate *priv;
+
+ g_return_val_if_fail (view != NULL, FALSE);
+ g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
+
+ priv = view->priv;
+
+ return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->rsvp_check));
+}
- priv->progress = message ? g_strstrip (g_strdup (message)) : NULL;
+void
+itip_view_set_show_rsvp (ItipView *view, gboolean rsvp)
+{
+ ItipViewPrivate *priv;
- set_progress_text (view);
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (ITIP_IS_VIEW (view));
+
+ priv = view->priv;
+
+ priv->rsvp_show = rsvp;
+
+ priv->rsvp_show ? gtk_widget_show (priv->rsvp_check) : gtk_widget_hide (priv->rsvp_check);
}
+gboolean
+itip_view_get_show_rsvp (ItipView *view)
+{
+ ItipViewPrivate *priv;
+
+ g_return_val_if_fail (view != NULL, FALSE);
+ g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
+
+ priv = view->priv;
+
+ return priv->rsvp_show;
+}
+
+void
+itip_view_set_buttons_sensitive (ItipView *view, gboolean sensitive)
+{
+ ItipViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (ITIP_IS_VIEW (view));
+
+ priv = view->priv;
+
+ priv->buttons_sensitive = sensitive;
+
+ gtk_widget_set_sensitive (priv->button_box, priv->buttons_sensitive);
+}
+
+gboolean
+itip_view_get_buttons_sensitive (ItipView *view)
+{
+ ItipViewPrivate *priv;
+
+ g_return_val_if_fail (view != NULL, FALSE);
+ g_return_val_if_fail (ITIP_IS_VIEW (view), FALSE);
+
+ priv = view->priv;
+
+ return priv->buttons_sensitive;
+}
+
+
diff --git a/plugins/itip-formatter/itip-view.h b/plugins/itip-formatter/itip-view.h
index 915b3286cb..c42a931b31 100644
--- a/plugins/itip-formatter/itip-view.h
+++ b/plugins/itip-formatter/itip-view.h
@@ -25,6 +25,7 @@
#include <glib-object.h>
#include <gtk/gtkhbox.h>
+#include <libedataserver/e-source-list.h>
G_BEGIN_DECLS
@@ -73,13 +74,16 @@ typedef enum {
struct _ItipView {
GtkHBox parent_instance;
-
+
ItipViewPrivate *priv;
+
+ GtkWidget *action_vbox;
};
struct _ItipViewClass {
GtkHBoxClass parent_class;
+ void (* source_selected) (ItipView *view, ESource *selected_source);
void (* response) (ItipView *view, int response);
};
@@ -113,10 +117,28 @@ const struct tm *itip_view_get_start (ItipView *view);
void itip_view_set_end (ItipView *view, struct tm *end);
const struct tm *itip_view_get_end (ItipView *view);
-void itip_view_add_info_item (ItipView *view, ItipViewInfoItemType, const char *message);
-void itip_view_clear_info_items (ItipView *view);
+guint itip_view_add_upper_info_item (ItipView *view, ItipViewInfoItemType, const char *message);
+void itip_view_remove_upper_info_item (ItipView *view, guint id);
+void itip_view_clear_upper_info_items (ItipView *view);
+
+guint itip_view_add_lower_info_item (ItipView *view, ItipViewInfoItemType, const char *message);
+void itip_view_remove_lower_info_item (ItipView *view, guint id);
+void itip_view_clear_lower_info_items (ItipView *view);
+
+void itip_view_set_source_list (ItipView *view, ESourceList *source_list);
+ESourceList *itip_view_get_source_list (ItipView *view);
+
+void itip_view_set_source (ItipView *view, ESource *source);
+ESource *itip_view_get_source (ItipView *view);
+
+void itip_view_set_rsvp (ItipView *view, gboolean rsvp);
+gboolean itip_view_get_rsvp (ItipView *view);
+
+void itip_view_set_show_rsvp (ItipView *view, gboolean rsvp);
+gboolean itip_view_get_show_rsvp (ItipView *view);
-void itip_view_set_progress (ItipView *view, const char *message);
+void itip_view_set_buttons_sensitive (ItipView *view, gboolean sensitive);
+gboolean itip_view_get_buttons_sensitive (ItipView *view);
G_END_DECLS