aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog23
-rw-r--r--calendar/cal-client/cal-client.c102
-rw-r--r--calendar/cal-client/cal-client.h9
-rw-r--r--calendar/gui/dialogs/Makefile.am3
-rw-r--r--calendar/gui/dialogs/e-timezone-dialog.c526
-rw-r--r--calendar/gui/dialogs/e-timezone-dialog.glade264
-rw-r--r--calendar/gui/dialogs/e-timezone-dialog.h72
-rw-r--r--calendar/idl/evolution-calendar.idl16
-rw-r--r--calendar/pcs/cal.c42
9 files changed, 1057 insertions, 0 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 67cbb6f918..f25155b5d0 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,26 @@
+2001-06-14 Damon Chaplin <damon@ximian.com>
+
+ * gui/dialogs/e-timezone-dialog.[hc]:
+ * gui/dialogs/e-timezone-dialog.glade: new dialog for setting the
+ time zone.
+
+ * gui/dialogs/Makefile.am: added timezone dialog files.
+
+ * idl/evolution-calendar.idl: added CalTimezoneInfo struct and seq,
+ and getBuiltinTimezoneInfo method.
+
+ * pcs/cal.c (impl_Cal_get_builtin_timezone_info): implemented method.
+ (cal_class_init): added method to epv.
+
+ * cal-client/cal-client.c (struct CalClientPrivate): added
+ timezone_info array to contain cached info on builtin timezone city
+ names and coordinates.
+ (cal_client_get_builtin_timezone_info): new function to get the info
+ about builtin timezones.
+
+ * cal-client/cal-client.h: added CalTimezoneInfo struct, to contain
+ the city names and coords of the builtin timezones.
+
2001-06-13 JP Rosevear <jpr@ximian.com>
* gui/dialogs/comp-editor-util.c (comp_editor_date_label): remove
diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c
index cd8c8713d6..d761370c74 100644
--- a/calendar/cal-client/cal-client.c
+++ b/calendar/cal-client/cal-client.c
@@ -50,6 +50,11 @@ struct _CalClientPrivate {
/* The calendar client interface object we are contacting */
GNOME_Evolution_Calendar_Cal cal;
+
+ /* An array of CalTimezone structs containing information on builtin
+ timezones. We cache this so we only request it once from the
+ server. */
+ GArray *timezone_info;
};
@@ -66,6 +71,8 @@ static void cal_client_class_init (CalClientClass *class);
static void cal_client_init (CalClient *client);
static void cal_client_destroy (GtkObject *object);
+static void cal_client_free_builtin_timezone_info (GArray *zones);
+
static guint cal_client_signals[LAST_SIGNAL];
static GtkObjectClass *parent_class;
@@ -155,6 +162,7 @@ cal_client_init (CalClient *client)
priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED;
priv->uri = NULL;
priv->factory = CORBA_OBJECT_NIL;
+ priv->timezone_info = NULL;
}
/* Gets rid of the factory that a client knows about */
@@ -269,6 +277,11 @@ cal_client_destroy (GtkObject *object)
priv->uri = NULL;
}
+ if (priv->timezone_info) {
+ cal_client_free_builtin_timezone_info (priv->timezone_info);
+ priv->timezone_info = NULL;
+ }
+
g_free (priv);
client->priv = NULL;
@@ -1506,6 +1519,95 @@ cal_client_remove_object (CalClient *client, const char *uid)
return retval;
}
+/* Builds a list of CalComponentAlarms structures */
+static GArray *
+build_timezone_info_array (GNOME_Evolution_Calendar_CalTimezoneInfoSeq *seq)
+{
+ GArray *zones;
+ CalTimezoneInfo zone;
+ int i;
+
+ zones = g_array_new (FALSE, FALSE, sizeof (CalTimezoneInfo));
+
+ for (i = 0; i < seq->_length; i++) {
+ GNOME_Evolution_Calendar_CalTimezoneInfo *tzinfo;
+
+ tzinfo = seq->_buffer + i;
+
+ zone.location = g_strdup (tzinfo->location);
+ zone.latitude = tzinfo->latitude;
+ zone.longitude = tzinfo->longitude;
+
+ g_array_append_val (zones, zone);
+ }
+
+ return zones;
+}
+
+/**
+ * cal_client_get_builtin_timezone_info:
+ * @client: A calendar client.
+ *
+ * Returns information on the builtin timezones, i.e. their names and
+ * locations. This is so we can use the map to select a timezone.
+ *
+ * Return value: An array of #CalTimezoneInfo structures. The caller should not
+ * change or free this array. The CalClient will free it when it is destroyed.
+ **/
+GArray *
+cal_client_get_builtin_timezone_info (CalClient *client)
+{
+ CalClientPrivate *priv;
+ CORBA_Environment ev;
+ GNOME_Evolution_Calendar_CalTimezoneInfoSeq *seq;
+
+ g_return_val_if_fail (client != NULL, NULL);
+ g_return_val_if_fail (IS_CAL_CLIENT (client), NULL);
+
+ priv = client->priv;
+
+ /* If we have already got this data from the server just return it. */
+ if (priv->timezone_info)
+ return priv->timezone_info;
+
+ CORBA_exception_init (&ev);
+
+ seq = GNOME_Evolution_Calendar_Cal_getBuiltinTimezoneInfo (priv->cal,
+ &ev);
+ if (ev._major != CORBA_NO_EXCEPTION) {
+ g_message ("cal_client_get_builtin_timezone_info(): could not get the builtin timezone info");
+ CORBA_exception_free (&ev);
+ return NULL;
+ }
+ CORBA_exception_free (&ev);
+
+ priv->timezone_info = build_timezone_info_array (seq);
+ CORBA_free (seq);
+
+ return priv->timezone_info;
+}
+
+/**
+ * cal_client_free_builtin_timezone_info:
+ * @zones: An array of timezone info returned from
+ * cal_client_get_builtin_timezone_info().
+ *
+ * Frees the builtin timezone information structures.
+ **/
+static void
+cal_client_free_builtin_timezone_info (GArray *zones)
+{
+ CalTimezoneInfo *zone;
+ int i;
+
+ for (i = 0; i < zones->len; i++) {
+ zone = &g_array_index (zones, CalTimezoneInfo, i);
+ g_free (zone->location);
+ }
+
+ g_array_free (zones, TRUE);
+}
+
/**
* cal_client_get_query:
* @client: A calendar client.
diff --git a/calendar/cal-client/cal-client.h b/calendar/cal-client/cal-client.h
index 1f0211ef32..6d5891f7e1 100644
--- a/calendar/cal-client/cal-client.h
+++ b/calendar/cal-client/cal-client.h
@@ -65,6 +65,13 @@ typedef enum {
CAL_CLIENT_LOAD_LOADED
} CalClientLoadState;
+/* A timezone name and its coordinates in the world. */
+typedef struct _CalTimezoneInfo CalTimezoneInfo;
+struct _CalTimezoneInfo {
+ char *location;
+ double latitude;
+ double longitude;
+};
struct _CalClient {
GtkObject object;
@@ -126,6 +133,8 @@ gboolean cal_client_remove_object (CalClient *client, const char *uid);
CalQuery *cal_client_get_query (CalClient *client, const char *sexp);
+GArray *cal_client_get_builtin_timezone_info (CalClient *client);
+
END_GNOME_DECLS
diff --git a/calendar/gui/dialogs/Makefile.am b/calendar/gui/dialogs/Makefile.am
index 74c65d72ab..de97ea2d45 100644
--- a/calendar/gui/dialogs/Makefile.am
+++ b/calendar/gui/dialogs/Makefile.am
@@ -32,6 +32,8 @@ libcal_dialogs_a_SOURCES = \
comp-editor-util.h \
delete-comp.c \
delete-comp.h \
+ e-timezone-dialog.c \
+ e-timezone-dialog.h \
event-editor.c \
event-editor.h \
event-page.c \
@@ -51,6 +53,7 @@ glade_DATA = \
alarm-notify.glade \
alarm-page.glade \
cal-prefs-dialog.glade \
+ e-timezone-dialog.glade \
event-page.glade \
recurrence-page.glade \
task-details-page.glade \
diff --git a/calendar/gui/dialogs/e-timezone-dialog.c b/calendar/gui/dialogs/e-timezone-dialog.c
new file mode 100644
index 0000000000..7e9fce6cb8
--- /dev/null
+++ b/calendar/gui/dialogs/e-timezone-dialog.c
@@ -0,0 +1,526 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* Evolution calendar - Timezone selector dialog
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Authors: Damon Chaplin <damon@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkcombo.h>
+#include <gtk/gtkentry.h>
+#include <gtk/gtklabel.h>
+#include <gnome.h>
+#include <glade/glade.h>
+#include <widgets/misc/e-map.h>
+#include "e-timezone-dialog.h"
+
+#define E_TIMEZONE_DIALOG_MAP_POINT_NORMAL_RGBA 0xc070a0ff
+#define E_TIMEZONE_DIALOG_MAP_POINT_HOVER_RGBA 0xffff60ff
+#define E_TIMEZONE_DIALOG_MAP_POINT_SELECTED_1_RGBA 0xff60e0ff
+#define E_TIMEZONE_DIALOG_MAP_POINT_SELECTED_2_RGBA 0x000000ff
+
+struct _ETimezoneDialogPrivate {
+ /* Glade XML data */
+ GladeXML *xml;
+
+ /* Client to use */
+ CalClient *client;
+
+ GArray *zones;
+
+ EMapPoint *point_selected;
+ EMapPoint *point_hover;
+
+ EMap *map;
+
+ /* The timeout used to flash the nearest point. */
+ guint timeout_id;
+
+ /* Widgets from the Glade file */
+ GtkWidget *app;
+ GtkWidget *map_window;
+ GtkWidget *timezone_preview;
+ GtkWidget *timezone_combo;
+};
+
+
+static void e_timezone_dialog_class_init (ETimezoneDialogClass *class);
+static void e_timezone_dialog_init (ETimezoneDialog *etd);
+static void e_timezone_dialog_destroy (GtkObject *object);
+
+static gboolean get_widgets (ETimezoneDialog *etd);
+static gboolean on_map_timeout (gpointer data);
+static gboolean on_map_motion (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer data);
+static gboolean on_map_visibility_changed (GtkWidget *w,
+ GdkEventVisibility *event,
+ gpointer data);
+static gboolean on_map_button_pressed (GtkWidget *w,
+ GdkEventButton *event,
+ gpointer data);
+
+static char* get_zone_from_point (ETimezoneDialog *etd,
+ EMapPoint *point);
+
+static GtkObjectClass *parent_class;
+
+
+GtkType
+e_timezone_dialog_get_type (void)
+{
+ static GtkType e_timezone_dialog_type = 0;
+
+ if (!e_timezone_dialog_type) {
+ static const GtkTypeInfo e_timezone_dialog_info = {
+ "ETimezoneDialog",
+ sizeof (ETimezoneDialog),
+ sizeof (ETimezoneDialogClass),
+ (GtkClassInitFunc) e_timezone_dialog_class_init,
+ (GtkObjectInitFunc) e_timezone_dialog_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ e_timezone_dialog_type = gtk_type_unique (GTK_TYPE_OBJECT,
+ &e_timezone_dialog_info);
+ }
+
+ return e_timezone_dialog_type;
+}
+
+/* Class initialization function for the event editor */
+static void
+e_timezone_dialog_class_init (ETimezoneDialogClass *class)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass *) class;
+
+ parent_class = gtk_type_class (GTK_TYPE_OBJECT);
+
+ object_class->destroy = e_timezone_dialog_destroy;
+}
+
+/* Object initialization function for the event editor */
+static void
+e_timezone_dialog_init (ETimezoneDialog *etd)
+{
+ ETimezoneDialogPrivate *priv;
+
+ priv = g_new0 (ETimezoneDialogPrivate, 1);
+ etd->priv = priv;
+
+ priv->point_selected = NULL;
+ priv->point_hover = NULL;
+ priv->timeout_id = 0;
+}
+
+/* Destroy handler for the event editor */
+static void
+e_timezone_dialog_destroy (GtkObject *object)
+{
+ ETimezoneDialog *etd;
+ ETimezoneDialogPrivate *priv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (E_IS_TIMEZONE_DIALOG (object));
+
+ etd = E_TIMEZONE_DIALOG (object);
+ priv = etd->priv;
+
+ if (priv->timeout_id) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
+
+ if (priv->client) {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (priv->client), etd);
+ gtk_object_unref (GTK_OBJECT (priv->client));
+ priv->client = NULL;
+ }
+
+ if (priv->xml) {
+ gtk_object_unref (GTK_OBJECT (priv->xml));
+ priv->xml = NULL;
+ }
+
+ g_free (priv);
+ etd->priv = NULL;
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+
+ETimezoneDialog *
+e_timezone_dialog_construct (ETimezoneDialog *etd)
+{
+ ETimezoneDialogPrivate *priv;
+ GtkWidget *map;
+
+ g_return_val_if_fail (etd != NULL, NULL);
+ g_return_val_if_fail (E_IS_TIMEZONE_DIALOG (etd), NULL);
+
+ priv = etd->priv;
+
+ /* Load the content widgets */
+
+ priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/e-timezone-dialog.glade",
+ NULL);
+ if (!priv->xml) {
+ g_message ("e_timezone_dialog_construct(): Could not load the Glade XML file!");
+ goto error;
+ }
+
+ if (!get_widgets (etd)) {
+ g_message ("e_timezone_dialog_construct(): Could not find all widgets in the XML file!");
+ goto error;
+ }
+
+ map = GTK_WIDGET (e_map_new ());
+ priv->map = E_MAP (map);
+ gtk_widget_set_events (map, gtk_widget_get_events (map)
+ | GDK_VISIBILITY_NOTIFY_MASK);
+
+ gtk_entry_set_editable (GTK_ENTRY (GTK_COMBO (priv->timezone_combo)->entry), FALSE);
+
+ gtk_container_add (GTK_CONTAINER (priv->map_window), map);
+ gtk_widget_show (map);
+
+ gtk_signal_connect (GTK_OBJECT (map), "motion-notify-event",
+ GTK_SIGNAL_FUNC (on_map_motion), etd);
+ gtk_signal_connect (GTK_OBJECT (map), "visibility-notify-event",
+ GTK_SIGNAL_FUNC (on_map_visibility_changed), etd);
+ gtk_signal_connect (GTK_OBJECT (map), "button-press-event",
+ GTK_SIGNAL_FUNC (on_map_button_pressed), etd);
+
+ return etd;
+
+ error:
+
+ gtk_object_unref (GTK_OBJECT (etd));
+ return NULL;
+}
+
+/* Gets the widgets from the XML file and returns if they are all available.
+ * For the widgets whose values can be simply set with e-dialog-utils, it does
+ * that as well.
+ */
+static gboolean
+get_widgets (ETimezoneDialog *etd)
+{
+ ETimezoneDialogPrivate *priv;
+
+ priv = etd->priv;
+
+#define GW(name) glade_xml_get_widget (priv->xml, name)
+
+ priv->app = GW ("timezone-dialog");
+ priv->map_window = GW ("map-window");
+ priv->timezone_combo = GW ("timezone-combo");
+ priv->timezone_preview = GW ("timezone-preview");
+
+ return (priv->app
+ && priv->map_window
+ && priv->timezone_combo
+ && priv->timezone_preview);
+}
+
+
+/**
+ * e_timezone_dialog_new:
+ *
+ * Creates a new event editor dialog.
+ *
+ * Return value: A newly-created event editor dialog, or NULL if the event
+ * editor could not be created.
+ **/
+ETimezoneDialog *
+e_timezone_dialog_new (void)
+{
+ ETimezoneDialog *etd;
+
+ etd = E_TIMEZONE_DIALOG (gtk_type_new (E_TYPE_TIMEZONE_DIALOG));
+ return e_timezone_dialog_construct (E_TIMEZONE_DIALOG (etd));
+}
+
+
+
+/* This flashes the currently selected timezone in the map. */
+static gboolean
+on_map_timeout (gpointer data)
+{
+ ETimezoneDialog *etd;
+ ETimezoneDialogPrivate *priv;
+
+ etd = E_TIMEZONE_DIALOG (data);
+ priv = etd->priv;
+
+ if (!priv->point_selected)
+ return TRUE;
+
+ if (e_map_point_get_color_rgba (priv->point_selected)
+ == E_TIMEZONE_DIALOG_MAP_POINT_SELECTED_1_RGBA)
+ e_map_point_set_color_rgba (priv->map, priv->point_selected,
+ E_TIMEZONE_DIALOG_MAP_POINT_SELECTED_2_RGBA);
+ else
+ e_map_point_set_color_rgba (priv->map, priv->point_selected,
+ E_TIMEZONE_DIALOG_MAP_POINT_SELECTED_1_RGBA);
+
+ return TRUE;
+}
+
+
+static gboolean
+on_map_motion (GtkWidget *widget, GdkEventMotion *event, gpointer data)
+{
+ ETimezoneDialog *etd;
+ ETimezoneDialogPrivate *priv;
+ double longitude, latitude;
+ char *old_zone, *new_zone;
+
+ etd = E_TIMEZONE_DIALOG (data);
+ priv = etd->priv;
+
+ e_map_window_to_world (priv->map, (double) event->x, (double) event->y,
+ &longitude, &latitude);
+
+ if (priv->point_hover && priv->point_hover != priv->point_selected)
+ e_map_point_set_color_rgba (priv->map, priv->point_hover,
+ E_TIMEZONE_DIALOG_MAP_POINT_NORMAL_RGBA);
+
+ priv->point_hover = e_map_get_closest_point (priv->map, longitude,
+ latitude, TRUE);
+
+ if (priv->point_hover != priv->point_selected)
+ e_map_point_set_color_rgba (priv->map, priv->point_hover,
+ E_TIMEZONE_DIALOG_MAP_POINT_HOVER_RGBA);
+
+ gtk_label_get (GTK_LABEL (priv->timezone_preview), &old_zone);
+ new_zone = get_zone_from_point (etd, priv->point_hover);
+ if (strcmp (old_zone, new_zone))
+ gtk_label_set_text (GTK_LABEL (priv->timezone_preview),
+ new_zone);
+
+ return TRUE;
+}
+
+
+static gboolean
+on_map_visibility_changed (GtkWidget *w, GdkEventVisibility *event,
+ gpointer data)
+{
+ ETimezoneDialog *etd;
+ ETimezoneDialogPrivate *priv;
+
+ etd = E_TIMEZONE_DIALOG (data);
+ priv = etd->priv;
+
+ if (event->state != GDK_VISIBILITY_FULLY_OBSCURED) {
+ /* Map is visible, at least partly, so make sure we flash the
+ selected point. */
+ if (!priv->timeout_id)
+ priv->timeout_id = gtk_timeout_add (100, on_map_timeout, etd);
+ } else {
+ /* Map is invisible, so don't waste resources on the timeout.*/
+ if (priv->timeout_id) {
+ g_source_remove (priv->timeout_id);
+ priv->timeout_id = 0;
+ }
+ }
+
+ return FALSE;
+}
+
+
+static gboolean
+on_map_button_pressed (GtkWidget *w, GdkEventButton *event, gpointer data)
+{
+ ETimezoneDialog *etd;
+ ETimezoneDialogPrivate *priv;
+ double longitude, latitude;
+
+ etd = E_TIMEZONE_DIALOG (data);
+ priv = etd->priv;
+
+ e_map_window_to_world (priv->map, (double) event->x, (double) event->y,
+ &longitude, &latitude);
+
+ if (event->button != 1) {
+ e_map_zoom_out (priv->map);
+ } else {
+ if (e_map_get_magnification (priv->map) <= 1.0)
+ e_map_zoom_to_location (priv->map, longitude,
+ latitude);
+
+ if (priv->point_selected)
+ e_map_point_set_color_rgba (priv->map,
+ priv->point_selected,
+ E_TIMEZONE_DIALOG_MAP_POINT_NORMAL_RGBA);
+ priv->point_selected = priv->point_hover;
+
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (priv->timezone_combo)->entry),
+ get_zone_from_point (etd, priv->point_selected));
+ }
+
+ return TRUE;
+}
+
+
+static char*
+get_zone_from_point (ETimezoneDialog *etd,
+ EMapPoint *point)
+{
+ ETimezoneDialogPrivate *priv;
+ CalTimezoneInfo *zone;
+ double longitude, latitude;
+ int i;
+
+ priv = etd->priv;
+
+ if (point == NULL || priv->zones == NULL)
+ return "";
+
+ e_map_point_get_location (point, &longitude, &latitude);
+
+ for (i = 0; i < priv->zones->len; i++) {
+ zone = &g_array_index (priv->zones, CalTimezoneInfo, i);
+
+ if (zone->longitude - 0.005 <= longitude &&
+ zone->longitude + 0.005 >= longitude &&
+ zone->latitude - 0.005 <= latitude &&
+ zone->latitude + 0.005 >= latitude)
+ {
+ return zone->location;
+ }
+ }
+
+ g_assert_not_reached ();
+
+ return NULL;
+}
+
+
+CalClient*
+e_timezone_dialog_get_cal_client (ETimezoneDialog *etd)
+{
+
+ return etd->priv->client;
+}
+
+
+void
+e_timezone_dialog_set_cal_client (ETimezoneDialog *etd,
+ CalClient *client)
+{
+ ETimezoneDialogPrivate *priv;
+ CalTimezoneInfo *zone;
+ GList *tzlist = NULL;
+ char *current_zone;
+ int i;
+
+ g_return_if_fail (etd != NULL);
+ g_return_if_fail (E_IS_TIMEZONE_DIALOG (etd));
+ g_return_if_fail (IS_CAL_CLIENT (client));
+
+ priv = etd->priv;
+
+ priv->zones = cal_client_get_builtin_timezone_info (client);
+
+ if (!priv->zones) {
+ g_warning ("No timezone info found");
+ return;
+ }
+
+ /* Put the "None" and "UTC" entries at the top of the combo's list. */
+ tzlist = g_list_prepend (tzlist, _("None"));
+ tzlist = g_list_prepend (tzlist, _("UTC"));
+
+ current_zone = gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (priv->timezone_combo)->entry));
+
+ for (i = 0; i < priv->zones->len; i++) {
+ zone = &g_array_index (priv->zones, CalTimezoneInfo, i);
+ if (!strcmp (current_zone, zone->location)) {
+ priv->point_selected = e_map_add_point (priv->map,
+ zone->location,
+ zone->longitude,
+ zone->latitude,
+ E_TIMEZONE_DIALOG_MAP_POINT_NORMAL_RGBA);
+ } else {
+ e_map_add_point (priv->map, zone->location,
+ zone->longitude, zone->latitude,
+ E_TIMEZONE_DIALOG_MAP_POINT_NORMAL_RGBA);
+ }
+ tzlist = g_list_prepend (tzlist, zone->location);
+ }
+
+ tzlist = g_list_reverse (tzlist);
+ gtk_combo_set_popdown_strings (GTK_COMBO (priv->timezone_combo),
+ tzlist);
+ g_list_free (tzlist);
+
+}
+
+
+char*
+e_timezone_dialog_get_timezone (ETimezoneDialog *etd)
+{
+ ETimezoneDialogPrivate *priv;
+
+ g_return_val_if_fail (etd != NULL, NULL);
+ g_return_val_if_fail (E_IS_TIMEZONE_DIALOG (etd), NULL);
+
+ priv = etd->priv;
+
+ return gtk_entry_get_text (GTK_ENTRY (GTK_COMBO (priv->timezone_combo)->entry));
+}
+
+
+void
+e_timezone_dialog_set_timezone (ETimezoneDialog *etd,
+ char *timezone)
+{
+ ETimezoneDialogPrivate *priv;
+
+ g_return_if_fail (etd != NULL);
+ g_return_if_fail (E_IS_TIMEZONE_DIALOG (etd));
+
+ priv = etd->priv;
+
+ gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (priv->timezone_combo)->entry),
+ get_zone_from_point (etd, priv->point_selected));
+
+}
+
+
+GtkWidget*
+e_timezone_dialog_get_toplevel (ETimezoneDialog *etd)
+{
+ ETimezoneDialogPrivate *priv;
+
+ g_return_val_if_fail (etd != NULL, NULL);
+ g_return_val_if_fail (E_IS_TIMEZONE_DIALOG (etd), NULL);
+
+ priv = etd->priv;
+
+ return priv->app;
+}
+
diff --git a/calendar/gui/dialogs/e-timezone-dialog.glade b/calendar/gui/dialogs/e-timezone-dialog.glade
new file mode 100644
index 0000000000..2b2019dfc2
--- /dev/null
+++ b/calendar/gui/dialogs/e-timezone-dialog.glade
@@ -0,0 +1,264 @@
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>timezone-dialog</name>
+ <program_name>timezone-dialog</program_name>
+ <directory></directory>
+ <source_directory>src</source_directory>
+ <pixmaps_directory>pixmaps</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>True</gnome_support>
+ <gettext_support>True</gettext_support>
+</project>
+
+<widget>
+ <class>GnomeDialog</class>
+ <name>timezone-dialog</name>
+ <visible>False</visible>
+ <title>Select a Time Zone</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <default_width>500</default_width>
+ <default_height>400</default_height>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+ <auto_close>False</auto_close>
+ <hide_on_close>True</hide_on_close>
+
+ <widget>
+ <class>GtkVBox</class>
+ <child_name>GnomeDialog:vbox</child_name>
+ <name>dialog-vbox1</name>
+ <homogeneous>False</homogeneous>
+ <spacing>8</spacing>
+ <child>
+ <padding>4</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHButtonBox</class>
+ <child_name>GnomeDialog:action_area</child_name>
+ <name>dialog-action_area1</name>
+ <layout_style>GTK_BUTTONBOX_END</layout_style>
+ <spacing>8</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ <pack>GTK_PACK_END</pack>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>ok-button</name>
+ <can_default>True</can_default>
+ <has_default>True</has_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>cancel-button</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table1</name>
+ <rows>3</rows>
+ <columns>1</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>4</row_spacing>
+ <column_spacing>0</column_spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label1</name>
+ <label>Use the left mouse button to zoom in on an area of the map and select a time zone.
+ Use the right mouse button to zoom out.</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>2</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>False</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame1</name>
+ <label>Time Zones</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>True</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox1</name>
+ <border_width>4</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>map-window</name>
+ <hscrollbar_policy>GTK_POLICY_ALWAYS</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_ALWAYS</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox2</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>timezone-preview</name>
+ <label></label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox1</name>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>2</top_attach>
+ <bottom_attach>3</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label3</name>
+ <label>Selection:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkCombo</class>
+ <name>timezone-combo</name>
+ <value_in_list>False</value_in_list>
+ <ok_if_empty>True</ok_if_empty>
+ <case_sensitive>False</case_sensitive>
+ <use_arrows>True</use_arrows>
+ <use_arrows_always>False</use_arrows_always>
+ <items></items>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkEntry</class>
+ <child_name>GtkCombo:entry</child_name>
+ <name>combo-entry1</name>
+ <can_focus>True</can_focus>
+ <editable>False</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
diff --git a/calendar/gui/dialogs/e-timezone-dialog.h b/calendar/gui/dialogs/e-timezone-dialog.h
new file mode 100644
index 0000000000..bb253934f7
--- /dev/null
+++ b/calendar/gui/dialogs/e-timezone-dialog.h
@@ -0,0 +1,72 @@
+/* Evolution calendar - Timezone selector dialog
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Authors: Damon Chaplin <damon@ximian.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __E_TIMEZONE_DIALOG_H__
+#define __E_TIMEZONE_DIALOG_H__
+
+#include <libgnome/gnome-defs.h>
+#include <gtk/gtkobject.h>
+#include <cal-client/cal-client.h>
+
+
+
+#define E_TYPE_TIMEZONE_DIALOG (e_timezone_dialog_get_type ())
+#define E_TIMEZONE_DIALOG(obj) (GTK_CHECK_CAST ((obj), E_TYPE_TIMEZONE_DIALOG, ETimezoneDialog))
+#define E_TIMEZONE_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_TIMEZONE_DIALOG, \
+ ETimezoneDialogClass))
+#define E_IS_TIMEZONE_DIALOG(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_TIMEZONE_DIALOG))
+#define E_IS_TIMEZONE_DIALOG_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_TYPE_TIMEZONE_DIALOG))
+
+
+typedef struct _ETimezoneDialog ETimezoneDialog;
+typedef struct _ETimezoneDialogClass ETimezoneDialogClass;
+typedef struct _ETimezoneDialogPrivate ETimezoneDialogPrivate;
+
+struct _ETimezoneDialog {
+ GtkObject object;
+
+ /* Private data */
+ ETimezoneDialogPrivate *priv;
+};
+
+struct _ETimezoneDialogClass {
+ GtkObjectClass parent_class;
+};
+
+
+GtkType e_timezone_dialog_get_type (void);
+ETimezoneDialog* e_timezone_dialog_construct (ETimezoneDialog *etd);
+
+ETimezoneDialog* e_timezone_dialog_new (void);
+
+CalClient* e_timezone_dialog_get_cal_client (ETimezoneDialog *etd);
+void e_timezone_dialog_set_cal_client (ETimezoneDialog *etd,
+ CalClient *client);
+
+char* e_timezone_dialog_get_timezone (ETimezoneDialog *etd);
+void e_timezone_dialog_set_timezone (ETimezoneDialog *etd,
+ char *timezone);
+
+GtkWidget* e_timezone_dialog_get_toplevel (ETimezoneDialog *etd);
+
+
+
+#endif /* __E_TIMEZONE_DIALOG_H__ */
diff --git a/calendar/idl/evolution-calendar.idl b/calendar/idl/evolution-calendar.idl
index e21f77fe2e..cec986210a 100644
--- a/calendar/idl/evolution-calendar.idl
+++ b/calendar/idl/evolution-calendar.idl
@@ -98,6 +98,18 @@ module Calendar {
/* Used to represent a list of components plus their triggers */
typedef sequence<CalComponentAlarms> CalComponentAlarmsSeq;
+
+ /* Used to transfer builtin timezone information. */
+ struct CalTimezoneInfo {
+ string location;
+ double latitude;
+ double longitude;
+ };
+
+ /* Used to transfer a list of timezone info */
+ typedef sequence<CalTimezoneInfo> CalTimezoneInfoSeq;
+
+
interface Query;
interface Listener;
@@ -163,6 +175,10 @@ module Calendar {
*/
Query getQuery (in string sexp, in QueryListener ql)
raises (CouldNotCreate);
+
+ /* Returns information about all the builtin timezones. */
+ CalTimezoneInfoSeq getBuiltinTimezoneInfo ()
+ raises (NotFound);
};
/* Listener for changes in a calendar */
diff --git a/calendar/pcs/cal.c b/calendar/pcs/cal.c
index 6eb951133b..a76d3a7f38 100644
--- a/calendar/pcs/cal.c
+++ b/calendar/pcs/cal.c
@@ -21,6 +21,7 @@
*/
#include <config.h>
+#include <ical.h>
#include "cal.h"
#include "query.h"
@@ -377,6 +378,46 @@ impl_Cal_get_query (PortableServer_Servant servant,
return query_copy;
}
+/* Cal::getBuiltinTimezoneInfo method */
+static GNOME_Evolution_Calendar_CalTimezoneInfoSeq *
+impl_Cal_get_builtin_timezone_info (PortableServer_Servant servant,
+ CORBA_Environment *ev)
+{
+ GNOME_Evolution_Calendar_CalTimezoneInfoSeq *seq;
+ icalarray *zones;
+ icaltimezone *zone;
+ int n, i;
+ char *location;
+
+ zones = icaltimezone_get_builtin_timezones ();
+ if (!zones) {
+ CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
+ ex_GNOME_Evolution_Calendar_Cal_NotFound,
+ NULL);
+ return CORBA_OBJECT_NIL;
+ }
+
+ n = zones->num_elements;
+
+ seq = GNOME_Evolution_Calendar_CalTimezoneInfoSeq__alloc ();
+ CORBA_sequence_set_release (seq, TRUE);
+ seq->_length = n;
+ seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalTimezoneInfo_allocbuf (n);
+
+ /* Fill the sequence */
+
+ for (i = 0; i < n; i++) {
+ zone = icalarray_element_at (zones, i);
+ location = icaltimezone_get_location (zone);
+
+ seq->_buffer[i].location = CORBA_string_dup (location);
+ seq->_buffer[i].latitude = icaltimezone_get_latitude (zone);
+ seq->_buffer[i].longitude = icaltimezone_get_longitude (zone);
+ }
+
+ return seq;
+}
+
/**
* cal_construct:
* @cal: A calendar client interface.
@@ -507,6 +548,7 @@ cal_class_init (CalClass *klass)
epv->updateObject = impl_Cal_update_object;
epv->removeObject = impl_Cal_remove_object;
epv->getQuery = impl_Cal_get_query;
+ epv->getBuiltinTimezoneInfo = impl_Cal_get_builtin_timezone_info;
}