aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/itip-formatter
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/itip-formatter')
-rw-r--r--plugins/itip-formatter/ChangeLog28
-rw-r--r--plugins/itip-formatter/itip-formatter.c548
-rw-r--r--plugins/itip-formatter/itip-view.c378
-rw-r--r--plugins/itip-formatter/itip-view.h33
-rw-r--r--plugins/itip-formatter/org-gnome-itip-formatter.eplug.in6
5 files changed, 953 insertions, 40 deletions
diff --git a/plugins/itip-formatter/ChangeLog b/plugins/itip-formatter/ChangeLog
index c2fbae2bad..82154dfc23 100644
--- a/plugins/itip-formatter/ChangeLog
+++ b/plugins/itip-formatter/ChangeLog
@@ -1,3 +1,31 @@
+2004-12-29 JP Rosevear <jpr@novell.com>
+
+ * itip-view.h: new protos
+
+ * itip-view.c (format_date_and_time_x): don't draw the leading
+ zero in 12hr clock mode for the hour
+ (set_sender_text): make intro statements closer to the UI design
+ (set_description_text): display description
+ (set_info_items): show info items, messages with icons
+ (set_progress_text): show progress text item (for
+ loading/searching calendars)
+ (set_one_button): add a response button
+ (set_buttons): set response buttons based on mode
+ (itip_view_destroy): clear info items
+ (itip_view_class_init): add response signal
+ (itip_view_init): new areas for description, info items, buttons
+ (itip_view_set_description): accessor
+ (itip_view_get_description): ditto
+ (itip_view_add_info_item): add an info item to the display
+ (itip_view_clear_info_items): clear all items
+ (itip_view_set_progress): set the progress message
+
+ * itip-formatter.c: move over calendar loading, searching code,
+ set more itip view properties
+
+ * org-gnome-itip-formatter.eplug.in: add a config page item,
+ doesn't do much right now
+
2004-12-22 JP Rosevear <jpr@novell.com>
* Initial checkin of new itip formatter
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index c16cc24826..7c8a7ed9ab 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -35,17 +35,28 @@
#include <camel/camel-mime-message.h>
#include <libecal/e-cal.h>
#include <libecal/e-cal-time-util.h>
+#include <libedataserverui/e-source-option-menu.h>
+#include <libedataserverui/e-source-selector.h>
#include <gtkhtml/gtkhtml-embedded.h>
#include <mail/em-format-hook.h>
+#include <mail/em-config.h>
#include <mail/em-format-html.h>
#include <e-util/e-account-list.h>
#include <e-util/e-icon-factory.h>
#include <calendar/gui/itip-utils.h>
+#include <calendar/common/authentication.h>
#include "itip-view.h"
#define CLASSID "itip://"
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;
@@ -58,12 +69,7 @@ typedef struct {
ECal *current_ecal;
ECalSourceType type;
- char action;
gboolean rsvp;
-
- GtkWidget *ok;
- GtkWidget *hbox;
- GtkWidget *vbox;
char *vcalendar;
ECalComponent *comp;
@@ -87,6 +93,350 @@ typedef struct {
gint view_only;
} FormatItipPObject;
+typedef struct {
+ FormatItipPObject *pitip;
+ char *uid;
+ int count;
+ gboolean show_selector;
+} EItipControlFindData;
+
+
+typedef void (* FormatItipOpenFunc) (ECal *ecal, ECalendarStatus status, gpointer data);
+
+static void
+cal_opened_cb (ECal *ecal, ECalendarStatus status, gpointer data)
+{
+ FormatItipPObject *pitip = data;
+ ESource *source;
+ ECalSourceType source_type;
+ icaltimezone *zone;
+
+ source_type = e_cal_get_source_type (ecal);
+ source = e_cal_get_source (ecal);
+
+ 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");
+
+ g_hash_table_remove (pitip->ecals[source_type], e_source_peek_uid (source));
+
+ return;
+ }
+
+ zone = calendar_config_get_icaltimezone ();
+ e_cal_set_default_timezone (ecal, zone, NULL);
+
+ pitip->current_ecal = ecal;
+
+// set_ok_sens (itip);
+}
+
+static ECal *
+start_calendar_server (FormatItipPObject *pitip, ESource *source, ECalSourceType type, FormatItipOpenFunc func, gpointer data)
+{
+ ECal *ecal;
+
+ ecal = g_hash_table_lookup (pitip->ecals[type], e_source_peek_uid (source));
+ if (ecal) {
+ pitip->current_ecal = ecal;
+
+ itip_view_set_progress (ITIP_VIEW (pitip->view), NULL);
+// set_ok_sens (itip);
+ return ecal;
+ }
+
+ ecal = auth_new_cal_from_source (source, type);
+ g_signal_connect (G_OBJECT (ecal), "cal_opened", G_CALLBACK (func), data);
+
+ g_hash_table_insert (pitip->ecals[type], g_strdup (e_source_peek_uid (source)), ecal);
+
+ e_cal_open_async (ecal, TRUE);
+
+ return ecal;
+}
+
+static ECal *
+start_calendar_server_by_uid (FormatItipPObject *pitip, const char *uid, ECalSourceType type)
+{
+ int i;
+
+ for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++) {
+ ESource *source;
+
+ source = e_source_list_peek_source_by_uid (pitip->source_lists[i], uid);
+ if (source)
+ return start_calendar_server (pitip, source, type, cal_opened_cb, pitip);
+ }
+
+ return NULL;
+}
+
+static void
+source_selected_cb (ESourceOptionMenu *esom, ESource *source, gpointer data)
+{
+ FormatItipPObject *pitip = data;
+
+ g_message ("Source selected");
+
+ /* FIXME turn off buttons while we check the calendar for being open? */
+
+ start_calendar_server (pitip, source, pitip->type, cal_opened_cb, pitip);
+}
+
+static void
+find_cal_opened_cb (ECal *ecal, ECalendarStatus status, gpointer data)
+{
+ EItipControlFindData *fd = data;
+ FormatItipPObject *pitip = fd->pitip;
+ ESource *source;
+ ECalSourceType source_type;
+ icalcomponent *icalcomp;
+ icaltimezone *zone;
+
+ source_type = e_cal_get_source_type (ecal);
+ source = e_cal_get_source (ecal);
+
+ fd->count--;
+
+ g_signal_handlers_disconnect_matched (ecal, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, find_cal_opened_cb, NULL);
+
+ if (status != E_CALENDAR_STATUS_OK) {
+ g_hash_table_remove (pitip->ecals[source_type], e_source_peek_uid (source));
+
+ goto cleanup;
+ }
+
+ if (e_cal_get_object (ecal, fd->uid, NULL, &icalcomp, NULL)) {
+ icalcomponent_free (icalcomp);
+
+ pitip->current_ecal = ecal;
+
+ itip_view_set_progress (ITIP_VIEW (pitip->view), NULL);
+// set_ok_sens (fd->itip);
+ }
+
+ zone = calendar_config_get_icaltimezone ();
+ e_cal_set_default_timezone (ecal, zone, NULL);
+
+ 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;
+ ESource *source = NULL;
+ char *uid;
+
+ switch (pitip->type) {
+ case E_CAL_SOURCE_TYPE_EVENT:
+ uid = calendar_config_get_primary_calendar ();
+ break;
+ case E_CAL_SOURCE_TYPE_TODO:
+ uid = calendar_config_get_primary_tasks ();
+ break;
+ default:
+ uid = NULL;
+ g_assert_not_reached ();
+ }
+
+ if (uid) {
+ source = e_source_list_peek_source_by_uid (pitip->source_lists[pitip->type], uid);
+ g_free (uid);
+ }
+
+ /* Try to create a default if there isn't one */
+ 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);
+
+ //gtk_box_pack_start (GTK_BOX (pitip->vbox), esom, FALSE, TRUE, 0);
+ gtk_widget_show (esom);
+
+ /* 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);
+ }
+ } else {
+ /* FIXME Display error message to user */
+ }
+
+ g_free (fd->uid);
+ g_free (fd);
+ }
+}
+
+static void
+find_server (FormatItipPObject *pitip, ECalComponent *comp, gboolean show_selector)
+{
+ EItipControlFindData *fd = NULL;
+ GSList *groups, *l;
+ const char *uid;
+
+ e_cal_component_get_uid (comp, &uid);
+
+ itip_view_set_progress (ITIP_VIEW (pitip->view), "Searching for an existing version of this appointment");
+
+ groups = e_source_list_peek_groups (pitip->source_lists[pitip->type]);
+ for (l = groups; l; l = l->next) {
+ ESourceGroup *group;
+ GSList *sources, *m;
+
+ group = l->data;
+
+ sources = e_source_group_peek_sources (group);
+ for (m = sources; m; m = m->next) {
+ ESource *source;
+ ECal *ecal;
+
+ source = m->data;
+
+ if (!fd) {
+ fd = g_new0 (EItipControlFindData, 1);
+ fd->pitip = pitip;
+ fd->uid = g_strdup (uid);
+ fd->show_selector = show_selector;
+ }
+ fd->count++;
+
+ ecal = start_calendar_server (pitip, source, pitip->type, find_cal_opened_cb, fd);
+ }
+ }
+}
+
+static void
+cleanup_ecal (ECal *ecal)
+{
+ /* 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);
+
+ g_object_unref (ecal);
+}
+
+static icalproperty *
+find_attendee (icalcomponent *ical_comp, const char *address)
+{
+ icalproperty *prop;
+
+ if (address == NULL)
+ return 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;
+ const char *attendee;
+ 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 (address, text)) {
+ g_free (text);
+ break;
+ }
+ g_free (text);
+ }
+
+ return prop;
+}
+
+static gboolean
+change_status (icalcomponent *ical_comp, const char *address, icalparameter_partstat status)
+{
+ icalproperty *prop;
+
+ prop = find_attendee (ical_comp, address);
+ if (prop) {
+ icalparameter *param;
+
+ icalproperty_remove_parameter (prop, ICAL_PARTSTAT_PARAMETER);
+ param = icalparameter_new_partstat (status);
+ icalproperty_add_parameter (prop, param);
+ } else {
+ icalparameter *param;
+
+ if (address != NULL) {
+ prop = icalproperty_new_attendee (address);
+ icalcomponent_add_property (ical_comp, prop);
+
+ param = icalparameter_new_role (ICAL_ROLE_OPTPARTICIPANT);
+ icalproperty_add_parameter (prop, param);
+
+ param = icalparameter_new_partstat (status);
+ icalproperty_add_parameter (prop, param);
+ } else {
+ EAccount *a;
+
+ a = itip_addresses_get_default ();
+
+ prop = icalproperty_new_attendee (a->id->address);
+ icalcomponent_add_property (ical_comp, prop);
+
+ param = icalparameter_new_cn (a->id->name);
+ icalproperty_add_parameter (prop, param);
+
+ param = icalparameter_new_role (ICAL_ROLE_REQPARTICIPANT);
+ icalproperty_add_parameter (prop, param);
+
+ param = icalparameter_new_partstat (status);
+ icalproperty_add_parameter (prop, param);
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+update_item (FormatItipPObject *pitip)
+{
+ struct icaltimetype stamp;
+ icalproperty *prop;
+ icalcomponent *clone;
+// GtkWidget *dialog;
+ GError *error = NULL;
+
+ /* Set X-MICROSOFT-CDO-REPLYTIME to record the time at which
+ * the user accepted/declined the request. (Outlook ignores
+ * SEQUENCE in REPLY reponses and instead requires that each
+ * updated response have a later REPLYTIME than the previous
+ * one.) This also ends up getting saved in our own copy of
+ * the meeting, though there's currently no way to see that
+ * information (unless it's being saved to an Exchange folder
+ * and you then look at it in Outlook).
+ */
+ stamp = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
+ prop = icalproperty_new_x (icaltime_as_ical_string (stamp));
+ icalproperty_set_x_name (prop, "X-MICROSOFT-CDO-REPLYTIME");
+ icalcomponent_add_property (pitip->ical_comp, prop);
+
+ clone = icalcomponent_new_clone (pitip->ical_comp);
+ icalcomponent_add_component (pitip->top_level, clone);
+ 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);
+ g_error_free (error);
+ } else {
+ /* FIXME I think we should do nothing */
+// dialog = gnome_ok_dialog (_("Update complete\n"));
+ }
+// gnome_dialog_run_and_close (GNOME_DIALOG (dialog));
+
+ icalcomponent_remove_component (pitip->top_level, clone);
+}
+
static icalcomponent *
get_next (icalcompiter *iter)
{
@@ -191,6 +541,42 @@ extract_itip_data (FormatItipPObject *pitip)
// show_current (itip);
}
+static void
+view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
+{
+ FormatItipPObject *pitip = data;
+ gboolean status = FALSE;
+
+ switch (response) {
+ case ITIP_VIEW_RESPONSE_ACCEPT:
+ status = change_status (pitip->ical_comp, pitip->my_address,
+ ICAL_PARTSTAT_ACCEPTED);
+ if (status) {
+ e_cal_component_rescan (pitip->comp);
+ update_item (pitip);
+ }
+ break;
+ case ITIP_VIEW_RESPONSE_TENTATIVE:
+ status = change_status (pitip->ical_comp, pitip->my_address,
+ ICAL_PARTSTAT_TENTATIVE);
+ if (status) {
+ e_cal_component_rescan (pitip->comp);
+ update_item (pitip);
+ }
+ break;
+ case ITIP_VIEW_RESPONSE_DECLINE:
+ status = change_status (pitip->ical_comp, pitip->my_address,
+ ICAL_PARTSTAT_DECLINED);
+ if (status) {
+ e_cal_component_rescan (pitip->comp);
+ update_item (pitip);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
static gboolean
format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
{
@@ -199,16 +585,58 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
ECalComponentOrganizer organizer;
ECalComponentDateTime datetime;
icaltimezone *from_zone, *to_zone;
+ GString *gstring = NULL;
+ GSList *list, *l;
const char *string;
-
+ int i;
+
+ /* 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))
+ /* FIXME More error handling? */
+ pitip->source_lists[i] = NULL;
+
+ /* Initialize the ecal hashes */
+ pitip->ecals[i] = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, cleanup_ecal);
+ }
+
/* FIXME Error handling? */
+ /* FIXME Handle multiple VEVENTS with the same UID, ie detached instances */
extract_itip_data (pitip);
pitip->view = itip_view_new ();
gtk_widget_show (pitip->view);
- itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_REQUEST);
-
+ switch (pitip->method) {
+ case ICAL_METHOD_PUBLISH:
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_PUBLISH);
+ break;
+ case ICAL_METHOD_REQUEST:
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_REQUEST);
+ break;
+ case ICAL_METHOD_REPLY:
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_REPLY);
+ break;
+ case ICAL_METHOD_ADD:
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_ADD);
+ break;
+ case ICAL_METHOD_CANCEL:
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_CANCEL);
+ break;
+ case ICAL_METHOD_REFRESH:
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_REFRESH);
+ break;
+ case ICAL_METHOD_COUNTER:
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_COUNTER);
+ break;
+ case ICAL_METHOD_DECLINECOUNTER:
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_DECLINECOUNTER);
+ break;
+ default:
+ /* FIXME What to do here? */
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_ERROR);
+ }
+
e_cal_component_get_organizer (pitip->comp, &organizer);
itip_view_set_organizer (ITIP_VIEW (pitip->view), organizer.cn ? organizer.cn : itip_strip_mailto (organizer.value));
/* FIXME, do i need to strip the sentby somehow? Maybe with camel? */
@@ -220,6 +648,23 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
e_cal_component_get_location (pitip->comp, &string);
itip_view_set_location (ITIP_VIEW (pitip->view), string);
+ e_cal_component_get_location (pitip->comp, &string);
+ itip_view_set_location (ITIP_VIEW (pitip->view), string);
+
+ e_cal_component_get_description_list (pitip->comp, &list);
+ for (l = list; l; l = l->next) {
+ ECalComponentText *text = l->data;
+
+ if (!gstring)
+ gstring = g_string_new (text->value);
+ else
+ g_string_append_printf (gstring, "\n\n%s", text->value);
+ }
+ e_cal_component_free_text_list (list);
+
+ itip_view_set_description (ITIP_VIEW (pitip->view), gstring->str);
+ g_string_free (gstring, TRUE);
+
to_zone = calendar_config_get_icaltimezone ();
e_cal_component_get_dtstart (pitip->comp, &datetime);
@@ -254,8 +699,18 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
}
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");
+
gtk_container_add (GTK_CONTAINER (eb), pitip->view);
+ gtk_widget_set_usize (pitip->view, 640, -1);
+
+ g_signal_connect (pitip->view, "response", G_CALLBACK (view_response_cb), pitip);
+ /* FIXME Show selector should be handled in the itip view */
+ find_server (pitip, pitip->comp, TRUE);
+
return TRUE;
}
@@ -273,3 +728,80 @@ format_itip (EPlugin *ep, EMFormatHookTarget *target)
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>");
}
+
+GtkWidget *
+itip_formatter_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data)
+{
+// EMConfigTargetPrefs *target = (EMConfigTargetPrefs *) hook_data->config->target;
+ GtkWidget *page;
+ GtkWidget *tab_label;
+ GtkWidget *frame;
+ GtkWidget *frame_label;
+ GtkWidget *padding_label;
+ GtkWidget *hbox;
+ GtkWidget *inner_vbox;
+ GtkWidget *check;
+ GtkWidget *check_gaim;
+
+ /* A structure to pass some stuff around */
+// stuff = g_new0 (struct bbdb_stuff, 1);
+// stuff->target = target;
+
+ /* Create a new notebook page */
+ page = gtk_vbox_new (FALSE, 0);
+ GTK_CONTAINER (page)->border_width = 12;
+ tab_label = gtk_label_new (_("Meetings"));
+ gtk_notebook_append_page (GTK_NOTEBOOK (hook_data->parent), page, tab_label);
+
+ /* Frame */
+ frame = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
+
+ /* "Automatic Contacts" */
+ frame_label = gtk_label_new ("");
+ gtk_label_set_markup (GTK_LABEL (frame_label), _("<span weight=\"bold\">General</span>"));
+ GTK_MISC (frame_label)->xalign = 0.0;
+ gtk_box_pack_start (GTK_BOX (frame), frame_label, FALSE, FALSE, 0);
+
+ /* Indent/padding */
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (frame), hbox, FALSE, TRUE, 0);
+ padding_label = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (hbox), padding_label, FALSE, FALSE, 0);
+ inner_vbox = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), inner_vbox, FALSE, FALSE, 0);
+
+ /* Enable BBDB checkbox */
+ check = gtk_check_button_new_with_mnemonic (_("_Delete message after acting"));
+// gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), gconf_client_get_bool (target->gconf, GCONF_KEY_ENABLE, NULL));
+// g_signal_connect (GTK_TOGGLE_BUTTON (check), "toggled", G_CALLBACK (enable_toggled_cb), stuff);
+ gtk_box_pack_start (GTK_BOX (inner_vbox), check, FALSE, FALSE, 0);
+// stuff->check = check;
+
+ /* "Instant Messaging Contacts" */
+ frame = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (page), frame, TRUE, TRUE, 24);
+
+ frame_label = gtk_label_new ("");
+ gtk_label_set_markup (GTK_LABEL (frame_label), _("<span weight=\"bold\">Conflict Search</span>"));
+ GTK_MISC (frame_label)->xalign = 0.0;
+ gtk_box_pack_start (GTK_BOX (frame), frame_label, FALSE, FALSE, 0);
+
+ /* Indent/padding */
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (frame), hbox, FALSE, TRUE, 0);
+ padding_label = gtk_label_new ("");
+ gtk_box_pack_start (GTK_BOX (hbox), padding_label, FALSE, FALSE, 0);
+ inner_vbox = gtk_vbox_new (FALSE, 6);
+ gtk_box_pack_start (GTK_BOX (hbox), inner_vbox, FALSE, FALSE, 0);
+
+ /* Enable Gaim Checkbox */
+ check_gaim = gtk_label_new (_("Select the calendars to search for meeting conflicts"));
+ gtk_box_pack_start (GTK_BOX (inner_vbox), check_gaim, FALSE, FALSE, 0);
+// stuff->check_gaim = check_gaim;
+
+ gtk_widget_show_all (page);
+
+ return page;
+}
+
diff --git a/plugins/itip-formatter/itip-view.c b/plugins/itip-formatter/itip-view.c
index e58506605b..a1a1e8c12a 100644
--- a/plugins/itip-formatter/itip-view.c
+++ b/plugins/itip-formatter/itip-view.c
@@ -20,6 +20,10 @@
*
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
@@ -36,6 +40,7 @@
#include <e-util/e-account-list.h>
#include <e-util/e-icon-factory.h>
#include <e-util/e-time-utils.h>
+#include <e-util/e-gtk-utils.h>
#include <calendar/gui/itip-utils.h>
#include "itip-view.h"
@@ -43,6 +48,12 @@
G_DEFINE_TYPE (ItipView, itip_view, GTK_TYPE_HBOX);
+typedef struct {
+ ItipViewInfoItemType type;
+
+ char *message;
+} ItipViewInfoItem;
+
struct _ItipViewPrivate {
ItipViewMode mode;
@@ -66,8 +77,28 @@ struct _ItipViewPrivate {
GtkWidget *end_header;
GtkWidget *end_label;
struct tm *end_tm;
+
+ GtkWidget *info_box;
+ GSList *info_items;
+
+ GtkWidget *description_label;
+ char *description;
+
+ GtkWidget *progress_box;
+ GtkWidget *progress_label;
+ char *progress;
+
+ GtkWidget *button_box;
+};
+
+/* Signal IDs */
+enum {
+ RESPONSE,
+ LAST_SIGNAL
};
+static guint signals[LAST_SIGNAL] = { 0 };
+
static void
format_date_and_time_x (struct tm *date_tm,
struct tm *current_tm,
@@ -100,11 +131,11 @@ format_date_and_time_x (struct tm *date_tm,
if (!show_zero_seconds && date_tm->tm_sec == 0)
/* strftime format of a weekday, a date and a
time, in 12-hour format, without seconds. */
- format = _("Today %I:%M %p");
+ format = _("Today %l:%M %p");
else
/* strftime format of a weekday, a date and a
time, in 12-hour format. */
- format = _("Today %I:%M:%S %p");
+ format = _("Today %l:%M:%S %p");
}
/* Tomorrow */
@@ -126,11 +157,11 @@ format_date_and_time_x (struct tm *date_tm,
if (!show_zero_seconds && date_tm->tm_sec == 0)
/* strftime format of a weekday, a date and a
time, in 12-hour format, without seconds. */
- format = _("%A, %B %e %I:%M %p");
+ format = _("%A, %B %e %l:%M %p");
else
/* strftime format of a weekday, a date and a
time, in 12-hour format. */
- format = _("%A, %B %e %I:%M:%S %p");
+ format = _("%A, %B %e %l:%M:%S %p");
}
/* Within 7 days */
@@ -152,11 +183,11 @@ format_date_and_time_x (struct tm *date_tm,
if (!show_zero_seconds && date_tm->tm_sec == 0)
/* strftime format of a weekday, a date and a
time, in 12-hour format, without seconds. */
- format = _("%A %I:%M %p");
+ format = _("%A %l:%M %p");
else
/* strftime format of a weekday, a date and a
time, in 12-hour format. */
- format = _("%A %I:%M:%S %p");
+ format = _("%A %l:%M:%S %p");
}
/* This Year */
@@ -178,11 +209,11 @@ format_date_and_time_x (struct tm *date_tm,
if (!show_zero_seconds && date_tm->tm_sec == 0)
/* strftime format of a weekday, a date and a
time, in 12-hour format, without seconds. */
- format = _("%A, %B %e %I:%M %p");
+ format = _("%A, %B %e %l:%M %p");
else
/* strftime format of a weekday, a date and a
time, in 12-hour format. */
- format = _("%A, %B %e %I:%M:%S %p");
+ format = _("%A, %B %e %l:%M:%S %p");
}
} else {
if (!show_midnight && date_tm->tm_hour == 0
@@ -202,11 +233,11 @@ format_date_and_time_x (struct tm *date_tm,
if (!show_zero_seconds && date_tm->tm_sec == 0)
/* strftime format of a weekday, a date and a
time, in 12-hour format, without seconds. */
- format = _("%A, %B %e, %Y %I:%M %p");
+ format = _("%A, %B %e, %Y %l:%M %p");
else
/* strftime format of a weekday, a date and a
time, in 12-hour format. */
- format = _("%A, %B %e, %Y %I:%M:%S %p");
+ format = _("%A, %B %e, %Y %l:%M:%S %p");
}
}
@@ -231,38 +262,45 @@ set_sender_text (ItipView *view)
switch (priv->mode) {
case ITIP_VIEW_MODE_PUBLISH:
if (priv->sentby)
- sender = g_strdup_printf (_("<b>%s</b> through %s has published meeting information."), organizer, priv->sentby);
+ sender = g_strdup_printf (_("<b>%s</b> through %s has published the following meeting information:"), organizer, priv->sentby);
else
- sender = g_strdup_printf (_("<b>%s</b> has published meeting information."), organizer);
+ sender = g_strdup_printf (_("<b>%s</b> has published the following meeting information:"), organizer);
break;
case ITIP_VIEW_MODE_REQUEST:
/* FIXME is the delegator stuff handled correctly here? */
if (priv->delegator) {
- sender = g_strdup_printf (_("<b>%s</b> requests the presence of %s at a meeting."), organizer, priv->delegator);
+ sender = g_strdup_printf (_("<b>%s</b> requests the presence of %s at the following meeting:"), organizer, priv->delegator);
} else {
if (priv->sentby)
- sender = g_strdup_printf (_("<b>%s</b> through %s requests your presence at a meeting."), organizer, priv->sentby);
+ sender = g_strdup_printf (_("<b>%s</b> through %s requests your presence at the following meeting:"), organizer, priv->sentby);
else
- sender = g_strdup_printf (_("<b>%s</b> requests your presence at a meeting."), organizer);
+ sender = g_strdup_printf (_("<b>%s</b> requests your presence at the following meeting:"), organizer);
}
break;
case ITIP_VIEW_MODE_ADD:
+ /* FIXME What text for this? */
if (priv->sentby)
- sender = g_strdup_printf (_("<b>%s</b> through %s wishes to add to an existing meeting."), organizer, priv->sentby);
+ sender = g_strdup_printf (_("<b>%s</b> through %s wishes to add to an existing meeting:"), organizer, priv->sentby);
else
- sender = g_strdup_printf (_("<b>%s</b> wishes to add to an existing meeting."), organizer);
+ sender = g_strdup_printf (_("<b>%s</b> wishes to add to an existing meeting:"), organizer);
break;
case ITIP_VIEW_MODE_REFRESH:
- sender = g_strdup_printf (_("<b>%s</b> wishes to receive the latest meeting information."), attendee);
+ sender = g_strdup_printf (_("<b>%s</b> wishes to receive the latest information for the following meeting:"), attendee);
break;
case ITIP_VIEW_MODE_REPLY:
- sender = g_strdup_printf (_("<b>%s</b> has replied to a meeting invitation."), attendee);
+ sender = g_strdup_printf (_("<b>%s</b> has accepted the following meeting:"), attendee);
break;
case ITIP_VIEW_MODE_CANCEL:
if (priv->sentby)
- sender = g_strdup_printf (_("<b>%s</b> through %s has cancelled a meeting."), organizer, priv->sentby);
+ sender = g_strdup_printf (_("<b>%s</b> through %s has cancelled the follow meeting:"), organizer, priv->sentby);
else
- sender = g_strdup_printf (_("<b>%s</b> has cancelled a meeting."), organizer);
+ sender = g_strdup_printf (_("<b>%s</b> has cancelled the following meeting."), organizer);
+ break;
+ case ITIP_VIEW_MODE_COUNTER:
+ if (priv->sentby)
+ sender = g_strdup_printf (_("<b>%s</b> through %s has cancelled the follow meeting:"), organizer, priv->sentby);
+ else
+ sender = g_strdup_printf (_("<b>%s</b> has cancelled the following meeting."), organizer);
break;
default:
break;
@@ -304,6 +342,18 @@ set_location_text (ItipView *view)
}
static void
+set_description_text (ItipView *view)
+{
+ ItipViewPrivate *priv;
+
+ priv = view->priv;
+
+ gtk_label_set_text (GTK_LABEL (priv->description_label), priv->description);
+
+ priv->description ? gtk_widget_show (priv->description_label) : gtk_widget_hide (priv->description_label);
+}
+
+static void
set_start_text (ItipView *view)
{
ItipViewPrivate *priv;
@@ -352,6 +402,139 @@ set_end_text (ItipView *view)
}
static void
+set_info_items (ItipView *view)
+{
+ ItipViewPrivate *priv;
+ GSList *l;
+
+ priv = view->priv;
+
+ gtk_container_foreach (GTK_CONTAINER (priv->info_box), (GtkCallback) gtk_widget_destroy, NULL);
+
+ for (l = priv->info_items; l; l = l->next) {
+ ItipViewInfoItem *item = l->data;
+ GtkWidget *hbox, *image, *label;
+
+ hbox = gtk_hbox_new (FALSE, 0);
+
+ switch (item->type) {
+ case ITIP_VIEW_INFO_ITEM_TYPE_INFO:
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ break;
+ case ITIP_VIEW_INFO_ITEM_TYPE_WARNING:
+ image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
+ break;
+ 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_NONE:
+ default:
+ image = NULL;
+ }
+
+ if (image) {
+ gtk_widget_show (image);
+ gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 6);
+ }
+
+ label = gtk_label_new (item->message);
+ gtk_widget_show (label);
+ 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);
+ }
+}
+
+static void
+set_progress_text (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);
+
+ priv->progress ? gtk_widget_show (priv->progress_box) : gtk_widget_hide (priv->progress_box);
+}
+
+#define DATA_RESPONSE_KEY "ItipView::button_response"
+
+static void
+button_clicked_cb (GtkWidget *widget, gpointer data)
+{
+ ItipViewResponse response;
+
+ response = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), DATA_RESPONSE_KEY));
+
+ g_message ("Response %d", response);
+ g_signal_emit (G_OBJECT (data), signals[RESPONSE], 0, response);
+}
+
+static void
+set_one_button (ItipView *view, char *label, char *stock_id, ItipViewResponse response)
+{
+ ItipViewPrivate *priv;
+ GtkWidget *button;
+
+ priv = view->priv;
+
+ 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);
+
+ g_signal_connect (button, "clicked", G_CALLBACK (button_clicked_cb), view);
+}
+
+static void
+set_buttons (ItipView *view)
+{
+ ItipViewPrivate *priv;
+
+ priv = view->priv;
+
+ gtk_container_foreach (GTK_CONTAINER (priv->button_box), (GtkCallback) gtk_widget_destroy, NULL);
+
+ /* Everything gets the open button */
+ set_one_button (view, "_Open Calendar", GTK_STOCK_JUMP_TO, ITIP_VIEW_RESPONSE_OPEN);
+
+ switch (priv->mode) {
+ case ITIP_VIEW_MODE_PUBLISH:
+ /* FIXME Is this really the right button? */
+ set_one_button (view, "_Accept", GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
+ break;
+ case ITIP_VIEW_MODE_REQUEST:
+ set_one_button (view, "_Decline", GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
+ set_one_button (view, "_Tentative", GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
+ set_one_button (view, "_Accept", GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
+ break;
+ case ITIP_VIEW_MODE_ADD:
+ /* FIXME Right response? */
+ set_one_button (view, "_Add", GTK_STOCK_ADD, ITIP_VIEW_RESPONSE_ACCEPT);
+ break;
+ case ITIP_VIEW_MODE_REFRESH:
+ /* FIXME Is this really the right button? */
+ set_one_button (view, "_Refresh", GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_REFRESH);
+ break;
+ case ITIP_VIEW_MODE_REPLY:
+ /* FIXME Is this really the right button? */
+ set_one_button (view, "_Update", GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_UPDATE);
+ break;
+ case ITIP_VIEW_MODE_CANCEL:
+ set_one_button (view, "_Update", GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_UPDATE);
+ break;
+ case ITIP_VIEW_MODE_COUNTER:
+ break;
+ case ITIP_VIEW_MODE_DECLINECOUNTER:
+ break;
+ default:
+ break;
+ }
+}
+
+static void
itip_view_destroy (GtkObject *object)
{
ItipView *view = ITIP_VIEW (object);
@@ -365,6 +548,8 @@ itip_view_destroy (GtkObject *object)
g_free (priv->location);
g_free (priv->start_tm);
g_free (priv->end_tm);
+
+ itip_view_clear_info_items (view);
g_free (priv);
view->priv = NULL;
@@ -383,13 +568,22 @@ itip_view_class_init (ItipViewClass *klass)
gtkobject_class = GTK_OBJECT_CLASS (klass);
gtkobject_class->destroy = itip_view_destroy;
+
+ signals[RESPONSE] =
+ g_signal_new ("response",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ItipViewClass, response),
+ NULL, NULL,
+ gtk_marshal_NONE__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT);
}
static void
itip_view_init (ItipView *view)
{
ItipViewPrivate *priv;
- GtkWidget *icon, *vbox, *separator, *table;
+ GtkWidget *icon, *vbox, *separator, *table, *image;
priv = g_new0 (ItipViewPrivate, 1);
view->priv = priv;
@@ -411,6 +605,7 @@ itip_view_init (ItipView *view)
/* The first section listing the sender */
/* FIXME What to do if the send and organizer do not match */
priv->sender_label = gtk_label_new (NULL);
+ gtk_misc_set_alignment (GTK_MISC (priv->sender_label), 0, 0.5);
gtk_widget_show (priv->sender_label);
gtk_box_pack_start (GTK_BOX (vbox), priv->sender_label, FALSE, FALSE, 6);
@@ -434,11 +629,13 @@ itip_view_init (ItipView *view)
/* Location */
priv->location_header = gtk_label_new (_("Location:"));
priv->location_label = gtk_label_new (NULL);
+ gtk_misc_set_alignment (GTK_MISC (priv->location_header), 0, 0.5);
gtk_misc_set_alignment (GTK_MISC (priv->location_label), 0, 0.5);
gtk_table_attach (GTK_TABLE (table), priv->location_header, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
gtk_table_attach (GTK_TABLE (table), priv->location_label, 1, 2, 1, 2, GTK_FILL, 0, 0, 0);
- priv->start_header = gtk_label_new (_("Starts:"));
+ /* Start time */
+ priv->start_header = gtk_label_new (_("Start time:"));
priv->start_label = gtk_label_new (NULL);
gtk_misc_set_alignment (GTK_MISC (priv->start_header), 0, 0.5);
gtk_misc_set_alignment (GTK_MISC (priv->start_label), 0, 0.5);
@@ -446,14 +643,48 @@ itip_view_init (ItipView *view)
gtk_table_attach (GTK_TABLE (table), priv->start_header, 0, 1, 2, 3, GTK_FILL, 0, 0, 0);
gtk_table_attach (GTK_TABLE (table), priv->start_label, 1, 2, 2, 3, GTK_FILL, 0, 0, 0);
- priv->end_header = gtk_label_new (_("Ends:"));
+ /* End time */
+ priv->end_header = gtk_label_new (_("End time:"));
priv->end_label = gtk_label_new (NULL);
gtk_misc_set_alignment (GTK_MISC (priv->end_header), 0, 0.5);
gtk_misc_set_alignment (GTK_MISC (priv->end_label), 0, 0.5);
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);
+
+ /* Description */
+ priv->description_label = gtk_label_new (NULL);
+ gtk_label_set_line_wrap (GTK_LABEL (priv->description_label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (priv->description_label), 0, 0.5);
+// gtk_box_pack_start (GTK_BOX (vbox), priv->description_label, FALSE, FALSE, 6);
+
+ separator = gtk_hseparator_new ();
+ 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);
+
+ 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);
/* 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);
}
GtkWidget *
@@ -477,6 +708,7 @@ itip_view_set_mode (ItipView *view, ItipViewMode mode)
priv->mode = mode;
set_sender_text (view);
+ set_buttons (view);
}
ItipViewMode
@@ -598,7 +830,7 @@ itip_view_set_summary (ItipView *view, const char *summary)
if (priv->summary)
g_free (priv->summary);
- priv->summary = g_strdup (summary);
+ priv->summary = summary ? g_strstrip (g_strdup (summary)) : NULL;
set_summary_text (view);
}
@@ -629,7 +861,7 @@ itip_view_set_location (ItipView *view, const char *location)
if (priv->location)
g_free (priv->location);
- priv->location = g_strdup (location);
+ priv->location = location ? g_strstrip (g_strdup (location)) : NULL;
set_location_text (view);
}
@@ -647,6 +879,39 @@ itip_view_get_location (ItipView *view)
return priv->location;
}
+/* FIXME Status and description */
+void
+itip_view_set_description (ItipView *view, const char *description)
+{
+ ItipViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (ITIP_IS_VIEW (view));
+
+ priv = view->priv;
+
+ if (priv->description)
+ g_free (priv->description);
+
+ priv->description = description ? g_strstrip (g_strdup (description)) : NULL;
+
+ set_description_text (view);
+}
+
+const char *
+itip_view_get_description (ItipView *view)
+{
+ ItipViewPrivate *priv;
+
+ g_return_val_if_fail (view != NULL, NULL);
+ g_return_val_if_fail (ITIP_IS_VIEW (view), NULL);
+
+ priv = view->priv;
+
+ return priv->description;
+}
+
+
void
itip_view_set_start (ItipView *view, struct tm *start)
{
@@ -718,3 +983,64 @@ itip_view_get_end (ItipView *view)
return priv->end_tm;
}
+
+void
+itip_view_add_info_item (ItipView *view, ItipViewInfoItemType type, const char *message)
+{
+ ItipViewPrivate *priv;
+ ItipViewInfoItem *item;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (ITIP_IS_VIEW (view));
+
+ priv = view->priv;
+
+ item = g_new0 (ItipViewInfoItem, 1);
+
+ item->type = type;
+ item->message = g_strdup (message);
+
+ priv->info_items = g_slist_append (priv->info_items, item);
+
+ set_info_items (view);
+}
+
+void
+itip_view_clear_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->info_box), (GtkCallback) gtk_widget_destroy, NULL);
+
+ for (l = priv->info_items; l; l = l->next) {
+ ItipViewInfoItem *item = l->data;
+
+ g_free (item->message);
+ g_free (item);
+ }
+}
+
+void
+itip_view_set_progress (ItipView *view, const char *message)
+{
+ ItipViewPrivate *priv;
+
+ g_return_if_fail (view != NULL);
+ g_return_if_fail (ITIP_IS_VIEW (view));
+
+ priv = view->priv;
+
+ if (priv->progress)
+ g_free (priv->progress);
+
+ priv->progress = message ? g_strstrip (g_strdup (message)) : NULL;
+
+ set_progress_text (view);
+}
+
diff --git a/plugins/itip-formatter/itip-view.h b/plugins/itip-formatter/itip-view.h
index ac9305bf2e..915b3286cb 100644
--- a/plugins/itip-formatter/itip-view.h
+++ b/plugins/itip-formatter/itip-view.h
@@ -43,10 +43,13 @@ typedef enum {
ITIP_VIEW_MODE_NONE,
ITIP_VIEW_MODE_PUBLISH,
ITIP_VIEW_MODE_REQUEST,
+ ITIP_VIEW_MODE_COUNTER,
+ ITIP_VIEW_MODE_DECLINECOUNTER,
ITIP_VIEW_MODE_ADD,
ITIP_VIEW_MODE_REPLY,
ITIP_VIEW_MODE_REFRESH,
- ITIP_VIEW_MODE_CANCEL
+ ITIP_VIEW_MODE_CANCEL,
+ ITIP_VIEW_MODE_ERROR
} ItipViewMode;
typedef enum {
@@ -55,19 +58,29 @@ typedef enum {
ITIP_VIEW_RESPONSE_TENTATIVE,
ITIP_VIEW_RESPONSE_DECLINE,
ITIP_VIEW_RESPONSE_UPDATE,
- ITIP_VIEW_RESPONSE_SEND
+ ITIP_VIEW_RESPONSE_REFRESH,
+ ITIP_VIEW_RESPONSE_OPEN
} ItipViewResponse;
-struct _ItipView
-{
+typedef enum {
+ ITIP_VIEW_INFO_ITEM_TYPE_NONE,
+ ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+ ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
+ ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
+ ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS
+} ItipViewInfoItemType;
+
+
+struct _ItipView {
GtkHBox parent_instance;
ItipViewPrivate *priv;
};
-struct _ItipViewClass
-{
+struct _ItipViewClass {
GtkHBoxClass parent_class;
+
+ void (* response) (ItipView *view, int response);
};
GType itip_view_get_type (void);
@@ -91,12 +104,20 @@ const char *itip_view_get_summary (ItipView *view);
void itip_view_set_location (ItipView *view, const char *location);
const char *itip_view_get_location (ItipView *view);
+void itip_view_set_description (ItipView *view, const char *description);
+const char *itip_view_get_description (ItipView *view);
+
void itip_view_set_start (ItipView *view, struct tm *start);
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);
+
+void itip_view_set_progress (ItipView *view, const char *message);
+
G_END_DECLS
#endif
diff --git a/plugins/itip-formatter/org-gnome-itip-formatter.eplug.in b/plugins/itip-formatter/org-gnome-itip-formatter.eplug.in
index 901e695bd0..2f47b3f4a4 100644
--- a/plugins/itip-formatter/org-gnome-itip-formatter.eplug.in
+++ b/plugins/itip-formatter/org-gnome-itip-formatter.eplug.in
@@ -10,5 +10,11 @@
<item mime_type="text/calendar" flags="inline_disposition" format="format_itip"/>
</group>
</hook>
+
+ <hook class="org.gnome.evolution.mail.config:1.0">
+ <group target="prefs">
+ <item type="page" path="90.bbdb" label="BBDB" factory="itip_formatter_page_factory"/>
+ </group>
+ </hook>
</e-plugin>
</e-plugin-list> \ No newline at end of file