aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/itip-formatter/itip-view.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/itip-formatter/itip-view.c')
-rw-r--r--plugins/itip-formatter/itip-view.c378
1 files changed, 352 insertions, 26 deletions
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);
+}
+