From 1df00c7d517794881faefd45b3ae230a6b0d8204 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Mon, 12 Jan 2009 14:49:16 +0000 Subject: ** Fix for bug #563364 2009-01-12 Milan Crha ** Fix for bug #563364 * gui/e-day-view-time-item.h: (EDayViewTimeItem): * gui/e-day-view-time-item.c: (e_day_view_time_item_class_init), (e_day_view_time_item_init), (e_day_view_time_item_finalize), (e_day_view_time_item_get_column_width), (edvti_draw_zone), (e_day_view_time_item_draw), (edvti_second_zone_changed_cb), (edvti_on_select_zone), (edvti_on_set_zone), (e_day_view_time_item_show_popup_menu): Show two timezones in the day view's time column. * gui/apps_evolution_calendar.schemas.in: * gui/calendar-config-keys.h: * gui/calendar-config.h: * gui/calendar-config.c: (calendar_config_get_day_second_zones), (calendar_config_free_day_second_zones), (calendar_config_set_day_second_zone), (calendar_config_get_day_second_zone), (calendar_config_select_day_second_zone), (calendar_config_add_notification_day_second_zone): Access configuration for the second day time zone. * gui/dialogs/cal-prefs-dialog.glade: * gui/dialogs/cal-prefs-dialog.h: (struct _CalendarPrefsDialog): * gui/dialogs/cal-prefs-dialog.c: (update_day_second_zone_caption), (on_set_day_second_zone), (on_select_day_second_zone), (day_second_zone_clicked), (setup_changes), (show_config), (calendar_prefs_dialog_construct): Manage the second day zone in a Preferences dialog. svn path=/trunk/; revision=37060 --- calendar/gui/apps_evolution_calendar.schemas.in | 37 ++++ calendar/gui/calendar-config-keys.h | 3 + calendar/gui/calendar-config.c | 129 ++++++++++++ calendar/gui/calendar-config.h | 7 + calendar/gui/dialogs/cal-prefs-dialog.c | 100 +++++++++ calendar/gui/dialogs/cal-prefs-dialog.glade | 188 ++++++++++++----- calendar/gui/dialogs/cal-prefs-dialog.h | 1 + calendar/gui/e-day-view-time-item.c | 268 ++++++++++++++++++++++-- calendar/gui/e-day-view-time-item.h | 4 + 9 files changed, 663 insertions(+), 74 deletions(-) (limited to 'calendar/gui') diff --git a/calendar/gui/apps_evolution_calendar.schemas.in b/calendar/gui/apps_evolution_calendar.schemas.in index bd3a8ab220..7da667a165 100644 --- a/calendar/gui/apps_evolution_calendar.schemas.in +++ b/calendar/gui/apps_evolution_calendar.schemas.in @@ -15,6 +15,43 @@ + + /schemas/apps/evolution/calendar/display/day_second_zone + /apps/evolution/calendar/display/day_second_zone + evolution-calendar + string + + + The second timezone for a Day View + Shows the second time zone in a Day View, if set. Value is similar to one used in a 'timezone' key. + + + + + /schemas/apps/evolution/calendar/display/day_second_zones + /apps/evolution/calendar/display/day_second_zones + evolution-calendar + list + string + [] + + Recently used second time zones in a Day View + List of recently used second time zones in a Day View. + + + + + /schemas/apps/evolution/calendar/display/day_second_zones_max + /apps/evolution/calendar/display/day_second_zones_max + evolution-calendar + int + 5 + + Maximum number of recently used timezones to remember. + Maximum number of recently used timezones to remember in a 'day_second_zones' list. + + + /schemas/apps/evolution/calendar/display/use_daylight_saving /apps/evolution/calendar/display/use_daylight_saving diff --git a/calendar/gui/calendar-config-keys.h b/calendar/gui/calendar-config-keys.h index 12b294b7a5..9d50d21c86 100644 --- a/calendar/gui/calendar-config-keys.h +++ b/calendar/gui/calendar-config-keys.h @@ -61,6 +61,9 @@ G_BEGIN_DECLS #define CALENDAR_CONFIG_COMPRESS_WEEKEND CALENDAR_CONFIG_PREFIX "/display/compress_weekend" #define CALENDAR_CONFIG_SHOW_EVENT_END CALENDAR_CONFIG_PREFIX "/display/show_event_end" #define CALENDAR_CONFIG_WORKING_DAYS CALENDAR_CONFIG_PREFIX "/display/working_days" +#define CALENDAR_CONFIG_DAY_SECOND_ZONE CALENDAR_CONFIG_PREFIX "/display/day_second_zone" +#define CALENDAR_CONFIG_DAY_SECOND_ZONES_LIST CALENDAR_CONFIG_PREFIX "/display/day_second_zones" +#define CALENDAR_CONFIG_DAY_SECOND_ZONES_MAX CALENDAR_CONFIG_PREFIX "/display/day_second_zones_max" /* Date navigator settings */ #define CALENDAR_CONFIG_DN_SHOW_WEEK_NUMBERS CALENDAR_CONFIG_PREFIX "/date_navigator/show_week_numbers" diff --git a/calendar/gui/calendar-config.c b/calendar/gui/calendar-config.c index 484695fee8..f4efd7e95e 100644 --- a/calendar/gui/calendar-config.c +++ b/calendar/gui/calendar-config.c @@ -1567,3 +1567,132 @@ calendar_config_get_dir_path (void) return path; } + +/* contains list of strings, locations, recently used as the second timezone in a day view. + Free with calendar_config_free_day_second_zones. */ +GSList * +calendar_config_get_day_second_zones (void) +{ + GSList *res; + + calendar_config_init (); + + res = gconf_client_get_list (config, CALENDAR_CONFIG_DAY_SECOND_ZONES_LIST, GCONF_VALUE_STRING, NULL); + + return res; +} + +/* frees list from calendar_config_get_day_second_zones */ +void +calendar_config_free_day_second_zones (GSList *zones) +{ + if (zones) { + g_slist_foreach (zones, (GFunc)g_free, NULL); + g_slist_free (zones); + } +} + +/* keeps max 'day_second_zones_max' zones, if 'location' is already in a list, then it'll became first there */ +void +calendar_config_set_day_second_zone (const char *location) +{ + calendar_config_init (); + + if (location && *location) { + GSList *lst, *l; + GError *error = NULL; + int max_zones; + + /* configurable max number of timezones to remember */ + max_zones = gconf_client_get_int (config, CALENDAR_CONFIG_DAY_SECOND_ZONES_MAX, &error); + + if (error) { + g_error_free (error); + max_zones = -1; + } + + if (max_zones <= 0) + max_zones = 5; + + lst = calendar_config_get_day_second_zones (); + for (l = lst; l; l = l->next) { + if (l->data && g_str_equal (l->data, location)) { + if (l != lst) { + /* isn't first in the list */ + char *val = l->data; + + lst = g_slist_remove (lst, val); + lst = g_slist_prepend (lst, val); + } + break; + } + } + + if (!l) { + /* not in the list yet */ + lst = g_slist_prepend (lst, g_strdup (location)); + } + + while (g_slist_length (lst) > max_zones) { + l = g_slist_last (lst); + g_free (l->data); + lst = g_slist_delete_link (lst, l); + } + + gconf_client_set_list (config, CALENDAR_CONFIG_DAY_SECOND_ZONES_LIST, GCONF_VALUE_STRING, lst, NULL); + + calendar_config_free_day_second_zones (lst); + } + + gconf_client_set_string (config, CALENDAR_CONFIG_DAY_SECOND_ZONE, location ? location : "", NULL); +} + +/* location of the second time zone user has selected. Free with g_free. */ +char * +calendar_config_get_day_second_zone (void) +{ + calendar_config_init (); + + return gconf_client_get_string (config, CALENDAR_CONFIG_DAY_SECOND_ZONE, NULL); +} + +void +calendar_config_select_day_second_zone (void) +{ + icaltimezone *zone = NULL; + ETimezoneDialog *tzdlg; + GtkWidget *dialog; + char *second_location; + + second_location = calendar_config_get_day_second_zone (); + if (second_location && *second_location) + zone = icaltimezone_get_builtin_timezone (second_location); + g_free (second_location); + + if (!zone) + zone = calendar_config_get_icaltimezone (); + + tzdlg = e_timezone_dialog_new (); + e_timezone_dialog_set_timezone (tzdlg, zone); + + dialog = e_timezone_dialog_get_toplevel (tzdlg); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { + zone = e_timezone_dialog_get_timezone (tzdlg); + calendar_config_set_day_second_zone (zone ? icaltimezone_get_location (zone) : NULL); + } + + g_object_unref (tzdlg); +} + +guint +calendar_config_add_notification_day_second_zone (GConfClientNotifyFunc func, gpointer data) +{ + guint id; + + calendar_config_init (); + + id = gconf_client_notify_add (config, CALENDAR_CONFIG_DAY_SECOND_ZONE, func, data, NULL, NULL); + + return id; +} diff --git a/calendar/gui/calendar-config.h b/calendar/gui/calendar-config.h index 72a5560dd5..495b5c591b 100644 --- a/calendar/gui/calendar-config.h +++ b/calendar/gui/calendar-config.h @@ -258,4 +258,11 @@ gboolean calendar_config_get_daylight_saving (void); void calendar_config_set_daylight_saving (gboolean daylight_saving); guint calendar_config_add_notification_daylight_saving (GConfClientNotifyFunc func, gpointer data); +GSList *calendar_config_get_day_second_zones (void); +void calendar_config_free_day_second_zones (GSList *zones); +void calendar_config_set_day_second_zone (const char *location); +char * calendar_config_get_day_second_zone (void); +void calendar_config_select_day_second_zone (void); +guint calendar_config_add_notification_day_second_zone (GConfClientNotifyFunc func, gpointer data); + #endif /* _CALENDAR_CONFIG_H_ */ diff --git a/calendar/gui/dialogs/cal-prefs-dialog.c b/calendar/gui/dialogs/cal-prefs-dialog.c index 8ba51259e5..38871c2f89 100644 --- a/calendar/gui/dialogs/cal-prefs-dialog.c +++ b/calendar/gui/dialogs/cal-prefs-dialog.c @@ -131,6 +131,101 @@ timezone_changed (GtkWidget *widget, CalendarPrefsDialog *prefs) calendar_config_set_timezone (icaltimezone_get_location (zone)); } +static void +update_day_second_zone_caption (CalendarPrefsDialog *prefs) +{ + char *location; + const char *caption; + icaltimezone *zone; + + g_return_if_fail (prefs != NULL); + + caption = _("None"); + + location = calendar_config_get_day_second_zone (); + if (location && *location) { + zone = icaltimezone_get_builtin_timezone (location); + if (zone && icaltimezone_get_display_name (zone)) { + caption = icaltimezone_get_display_name (zone); + } + } + g_free (location); + + gtk_button_set_label (GTK_BUTTON (prefs->day_second_zone), caption); +} + +static void +on_set_day_second_zone (GtkWidget *item, CalendarPrefsDialog *prefs) +{ + if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item))) + return; + + calendar_config_set_day_second_zone (g_object_get_data (G_OBJECT (item), "timezone")); + update_day_second_zone_caption (prefs); +} + +static void +on_select_day_second_zone (GtkWidget *item, CalendarPrefsDialog *prefs) +{ + g_return_if_fail (prefs != NULL); + + calendar_config_select_day_second_zone (); + update_day_second_zone_caption (prefs); +} + +static void +day_second_zone_clicked (GtkWidget *widget, CalendarPrefsDialog *prefs) +{ + GtkWidget *menu, *item; + GSList *group = NULL, *recent_zones, *s; + char *location; + icaltimezone *zone, *second_zone = NULL; + + menu = gtk_menu_new (); + + location = calendar_config_get_day_second_zone (); + if (location && *location) + second_zone = icaltimezone_get_builtin_timezone (location); + g_free (location); + + group = NULL; + item = gtk_radio_menu_item_new_with_label (group, _("None")); + group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item)); + if (!second_zone) + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + g_signal_connect (item, "toggled", G_CALLBACK (on_set_day_second_zone), prefs); + + recent_zones = calendar_config_get_day_second_zones (); + for (s = recent_zones; s != NULL; s = s->next) { + zone = icaltimezone_get_builtin_timezone (s->data); + if (!zone) + continue; + + item = gtk_radio_menu_item_new_with_label (group, icaltimezone_get_display_name (zone)); + group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item)); + /* both comes from builtin, thus no problem to compare pointers */ + if (zone == second_zone) + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + g_object_set_data_full (G_OBJECT (item), "timezone", g_strdup (s->data), g_free); + g_signal_connect (item, "toggled", G_CALLBACK (on_set_day_second_zone), prefs); + } + calendar_config_free_day_second_zones (recent_zones); + + item = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + item = gtk_menu_item_new_with_label (_("Select...")); + g_signal_connect (item, "activate", G_CALLBACK (on_select_day_second_zone), prefs); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + gtk_widget_show_all (menu); + + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, + 0, gtk_get_current_event_time ()); +} + static void daylight_saving_changed (GtkWidget *widget, CalendarPrefsDialog *prefs) { @@ -373,6 +468,7 @@ setup_changes (CalendarPrefsDialog *prefs) g_signal_connect (G_OBJECT (prefs->working_days[i]), "toggled", G_CALLBACK (working_days_changed), prefs); g_signal_connect (G_OBJECT (prefs->timezone), "changed", G_CALLBACK (timezone_changed), prefs); + g_signal_connect (G_OBJECT (prefs->day_second_zone), "clicked", G_CALLBACK (day_second_zone_clicked), prefs); g_signal_connect (G_OBJECT (prefs->daylight_saving), "toggled", G_CALLBACK (daylight_saving_changed), prefs); g_signal_connect (G_OBJECT (prefs->start_of_day), "changed", G_CALLBACK (start_of_day_changed), prefs); @@ -513,6 +609,9 @@ show_config (CalendarPrefsDialog *prefs) set = calendar_config_get_daylight_saving (); gtk_toggle_button_set_active ((GtkToggleButton *) prefs->daylight_saving, set); + /* Day's second zone */ + update_day_second_zone_caption (prefs); + /* Working Days. */ working_days = calendar_config_get_working_days (); mask = 1 << 0; @@ -637,6 +736,7 @@ calendar_prefs_dialog_construct (CalendarPrefsDialog *prefs) /* General tab */ prefs->timezone = glade_xml_get_widget (gui, "timezone"); + prefs->day_second_zone = glade_xml_get_widget (gui, "day_second_zone"); prefs->daylight_saving = glade_xml_get_widget (gui, "daylight_cb"); for (i = 0; i < 7; i++) prefs->working_days[i] = glade_xml_get_widget (gui, working_day_names[i]); diff --git a/calendar/gui/dialogs/cal-prefs-dialog.glade b/calendar/gui/dialogs/cal-prefs-dialog.glade index d3003bdb6f..0282d17d4d 100644 --- a/calendar/gui/dialogs/cal-prefs-dialog.glade +++ b/calendar/gui/dialogs/cal-prefs-dialog.glade @@ -6,7 +6,7 @@ True - window1 + window1 GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False @@ -96,46 +96,37 @@ True - 3 + 4 2 False 6 6 - + True - Time _zone: - True - False - GTK_JUSTIFY_LEFT - False - False - 0 - 0.5 - 0 - 0 - timezone - PANGO_ELLIPSIZE_NONE - -1 - False - 0 + make_timezone_entry + 0 + 0 + Thu, 13 Jan 2005 04:18:03 GMT + + + - 0 - 1 + 1 + 2 0 1 - fill - + fill - + True - Time format: - False + Time _zone: + True False GTK_JUSTIFY_LEFT False @@ -144,6 +135,7 @@ 0.5 0 0 + timezone PANGO_ELLIPSIZE_NONE -1 False @@ -152,30 +144,32 @@ 0 1 - 2 - 3 + 0 + 1 fill - + True - make_timezone_entry - 0 - 0 - Thu, 13 Jan 2005 04:18:03 GMT - - - + True + Adjust for daylight sa_ving time + True + GTK_RELIEF_NORMAL + True + False + False + True 1 2 - 0 - 1 - fill + 1 + 2 + fill + @@ -235,24 +229,116 @@ - + True - True - Adjust for daylight sa_ving time + Time format: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + Se_cond zone: True - GTK_RELIEF_NORMAL - True - False - False - True + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + day_second_zone + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + False + 0 + + + + True + True + None + True + GTK_RELIEF_NORMAL + True + + + 0 + True + True + + + + + + True + (Shown in a Day View) + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 6 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + 1 2 - 1 - 2 + 3 + 4 fill - + fill @@ -348,7 +434,7 @@ 0.5 0 0 - week_start_day + week_start_day PANGO_ELLIPSIZE_NONE -1 False @@ -405,7 +491,7 @@ 0.5 0 0 - start_of_day + start_of_day PANGO_ELLIPSIZE_NONE -1 False diff --git a/calendar/gui/dialogs/cal-prefs-dialog.h b/calendar/gui/dialogs/cal-prefs-dialog.h index 815080ea06..24682a6cc7 100644 --- a/calendar/gui/dialogs/cal-prefs-dialog.h +++ b/calendar/gui/dialogs/cal-prefs-dialog.h @@ -44,6 +44,7 @@ struct _CalendarPrefsDialog { /* General tab */ GtkWidget *timezone; + GtkWidget *day_second_zone; GtkWidget *daylight_saving; GtkWidget *working_days[7]; GtkWidget *week_start_day; diff --git a/calendar/gui/e-day-view-time-item.c b/calendar/gui/e-day-view-time-item.c index 6a31855262..dc3c2deba5 100644 --- a/calendar/gui/e-day-view-time-item.c +++ b/calendar/gui/e-day-view-time-item.c @@ -32,6 +32,8 @@ #include "e-day-view-time-item.h" #include "calendar-config.h" #include +#include +#include /* The spacing between items in the time column. GRID_X_PAD is the space down @@ -59,6 +61,8 @@ static void e_day_view_time_item_set_property (GObject *object, const GValue *value, GParamSpec *pspec); +static void e_day_view_time_item_finalize (GObject *object); + static void e_day_view_time_item_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); @@ -88,7 +92,7 @@ static void e_day_view_time_item_on_motion_notify (EDayViewTimeItem *dvtmitem, static gint e_day_view_time_item_convert_position_to_row (EDayViewTimeItem *dvtmitem, gint y); - +static void edvti_second_zone_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data); /* The arguments we take */ enum { PROP_0, @@ -105,6 +109,7 @@ e_day_view_time_item_class_init (EDayViewTimeItemClass *class) object_class = G_OBJECT_CLASS (class); object_class->set_property = e_day_view_time_item_set_property; + object_class->finalize = e_day_view_time_item_finalize; item_class = GNOME_CANVAS_ITEM_CLASS (class); item_class->update = e_day_view_time_item_update; @@ -126,9 +131,21 @@ e_day_view_time_item_class_init (EDayViewTimeItemClass *class) static void e_day_view_time_item_init (EDayViewTimeItem *dvtmitem) { + char *last; + dvtmitem->dragging_selection = FALSE; -} + dvtmitem->second_zone = NULL; + + last = calendar_config_get_day_second_zone(); + + if (last) { + if (*last) + dvtmitem->second_zone = icaltimezone_get_builtin_timezone (last); + g_free (last); + } + dvtmitem->second_zone_changed_id = calendar_config_add_notification_day_second_zone (edvti_second_zone_changed_cb, dvtmitem); +} static void e_day_view_time_item_set_property (GObject *object, @@ -149,6 +166,20 @@ e_day_view_time_item_set_property (GObject *object, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } +static void +e_day_view_time_item_finalize (GObject *object) +{ + EDayViewTimeItem *dvtmitem; + + dvtmitem = E_DAY_VIEW_TIME_ITEM (object); + + if (dvtmitem->second_zone_changed_id) + calendar_config_remove_notification (dvtmitem->second_zone_changed_id); + dvtmitem->second_zone_changed_id = 0; + + if (G_OBJECT_CLASS (e_day_view_time_item_parent_class)->finalize) + G_OBJECT_CLASS (e_day_view_time_item_parent_class)->finalize (object); +} static void e_day_view_time_item_update (GnomeCanvasItem *item, @@ -229,6 +260,10 @@ e_day_view_time_item_get_column_width (EDayViewTimeItem *dvtmitem) dvtmitem->column_width = MAX (column_width_default, column_width_60_min_rows); + + if (dvtmitem->second_zone) + return (2 * dvtmitem->column_width) - E_DVTMI_TIME_GRID_X_PAD; + return dvtmitem->column_width; } @@ -237,17 +272,19 @@ e_day_view_time_item_get_column_width (EDayViewTimeItem *dvtmitem) * DRAWING ROUTINES - functions to paint the canvas item. */ static void -e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, - GdkDrawable *drawable, - int x, - int y, - int width, - int height) +edvti_draw_zone (GnomeCanvasItem *canvas_item, + GdkDrawable *drawable, + int x, + int y, + int width, + int height, + int x_offset, + icaltimezone *use_zone) { EDayView *day_view; EDayViewTimeItem *dvtmitem; GtkStyle *style; - gchar buffer[64], *suffix; + gchar buffer[64], *suffix, *midnight_day = NULL, *midnight_month = NULL; gint hour, display_hour, minute, row; gint row_y, start_y, large_hour_y_offset, small_font_y_offset; gint long_line_x1, long_line_x2, short_line_x1; @@ -260,6 +297,7 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, PangoFontMetrics *large_font_metrics, *small_font_metrics; cairo_t *cr; GdkColor fg, dark; + GdkColor mb_color; cr = gdk_cairo_create (drawable); @@ -280,8 +318,8 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, dark = style->dark[GTK_STATE_NORMAL]; /* The start and end of the long horizontal line between hours. */ - long_line_x1 = E_DVTMI_TIME_GRID_X_PAD - x; - long_line_x2 = dvtmitem->column_width - E_DVTMI_TIME_GRID_X_PAD - x; + long_line_x1 = (use_zone ? 0 : E_DVTMI_TIME_GRID_X_PAD) - x + x_offset; + long_line_x2 = dvtmitem->column_width - E_DVTMI_TIME_GRID_X_PAD - x - (use_zone ? E_DVTMI_TIME_GRID_X_PAD : 0) + x_offset; if (day_view->mins_per_row == 60) { /* The right edge of the complete time string in 60-min @@ -315,6 +353,51 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, hour = day_view->first_hour_shown; minute = day_view->first_minute_shown; + if (use_zone) { + /* shift time with a difference between local time and the other timezone */ + icaltimezone *cal_zone = e_calendar_view_get_timezone (E_CALENDAR_VIEW (day_view)); + struct icaltimetype tt; + int diff; + struct tm mn; + + tt = icaltime_today (); + + /* diff is number of minutes */ + diff = (icaltimezone_get_utc_offset (use_zone, &tt, NULL) - + icaltimezone_get_utc_offset (cal_zone, &tt, NULL) + ) / 60; + + tt = icaltime_today (); + tt.is_date = FALSE; + icaltime_set_timezone (&tt, cal_zone); + tt = icaltime_convert_to_zone (tt, use_zone); + + if (diff != 0) { + /* shows the next midnight */ + icaltime_adjust (&tt, 1, 0, 0, 0); + } + + mn = icaltimetype_to_tm (&tt); + + /* up to two characters/numbers */ + e_utf8_strftime (buffer, sizeof (buffer), "%d", &mn); + midnight_day = g_strdup (buffer); + /* up to three characters, abbreviated month name */ + e_utf8_strftime (buffer, sizeof (buffer), "%b", &mn); + midnight_month = g_strdup (buffer); + + minute += (diff % 60); + hour += (diff / 60) + (minute / 60); + + minute = minute % 60; + if (minute < 0) { + hour--; + minute += 60; + } + + hour = (hour + 48) % 24; + } + /* The offset of the large hour string from the top of the row. */ large_hour_y_offset = E_DVTMI_LARGE_HOUR_Y_PAD; @@ -333,7 +416,6 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, if (e_day_view_get_show_marcus_bains (day_view)) { struct icaltimetype time_now; int marcus_bains_y; - GdkColor mb_color; cairo_save (cr); gdk_cairo_set_source_color (cr, &day_view->colors[E_DAY_VIEW_COLOR_MARCUS_BAINS_LINE]); @@ -345,15 +427,27 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, if (gdk_colormap_alloc_color (colormap, &mb_color, TRUE, TRUE)) { gdk_cairo_set_source_color (cr, &mb_color); } - } + } else + mb_color = day_view->colors[E_DAY_VIEW_COLOR_MARCUS_BAINS_LINE]; time_now = icaltime_current_time_with_zone (e_calendar_view_get_timezone (E_CALENDAR_VIEW (day_view))); marcus_bains_y = (time_now.hour * 60 + time_now.minute) * day_view->row_height / day_view->mins_per_row - y; cairo_set_line_width (cr, 1.5); - cairo_move_to (cr, long_line_x1, marcus_bains_y); + cairo_move_to (cr, long_line_x1 - (use_zone ? E_DVTMI_TIME_GRID_X_PAD : 0), marcus_bains_y); cairo_line_to (cr, long_line_x2, marcus_bains_y); cairo_stroke (cr); cairo_restore (cr); + } else { + mb_color = day_view->colors[E_DAY_VIEW_COLOR_MARCUS_BAINS_LINE]; + + if (day_view->marcus_bains_time_bar_color && gdk_color_parse (day_view->marcus_bains_time_bar_color, &mb_color)) { + GdkColormap *colormap; + + colormap = gtk_widget_get_colormap (GTK_WIDGET (day_view)); + if (gdk_colormap_alloc_color (colormap, &mb_color, TRUE, TRUE)) { + gdk_cairo_set_source_color (cr, &mb_color); + } + } } /* Step through each row, drawing the times and the horizontal lines @@ -361,6 +455,7 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, for (row = 0, row_y = 0 - y; row < day_view->rows && row_y < height; row++, row_y += day_view->row_height) { + gboolean show_midnight_date = use_zone && hour == 0 && (minute == 0 || day_view->mins_per_row == 60) && midnight_day && midnight_month; /* If the row is above the first row we want to draw just increment the time and skip to the next row. */ @@ -389,7 +484,11 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, cairo_stroke (cr); cairo_restore (cr); - if (e_calendar_view_get_use_24_hour_format (E_CALENDAR_VIEW (day_view))) { + if (show_midnight_date) { + strcpy (buffer, midnight_day); + strcat (buffer, " "); + strcat (buffer, midnight_month); + } else if (e_calendar_view_get_use_24_hour_format (E_CALENDAR_VIEW (day_view))) { g_snprintf (buffer, sizeof (buffer), "%i:%02i", display_hour, minute); } else { @@ -398,7 +497,10 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, } cairo_save (cr); - gdk_cairo_set_source_color (cr, &fg); + if (show_midnight_date) + gdk_cairo_set_source_color (cr, &mb_color); + else + gdk_cairo_set_source_color (cr, &fg); layout = pango_cairo_create_layout (cr); pango_layout_set_text (layout, buffer, -1); pango_layout_get_pixel_size (layout, &minute_width, NULL); @@ -418,8 +520,11 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, cairo_save (cr); gdk_cairo_set_source_color (cr, &dark); - g_snprintf (buffer, sizeof (buffer), "%i", - display_hour); + if (show_midnight_date) + strcpy (buffer, midnight_day); + else + g_snprintf (buffer, sizeof (buffer), "%i", + display_hour); cairo_set_line_width (cr, 0.7); cairo_move_to (cr, long_line_x1, row_y); @@ -428,7 +533,10 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, cairo_restore (cr); cairo_save (cr); - gdk_cairo_set_source_color (cr, &fg); + if (show_midnight_date) + gdk_cairo_set_source_color (cr, &mb_color); + else + gdk_cairo_set_source_color (cr, &fg); layout = pango_cairo_create_layout (cr); pango_layout_set_text (layout, buffer, -1); pango_layout_set_font_description (layout, day_view->large_font_desc); @@ -457,7 +565,9 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, if (day_view->mins_per_row != 30 || minute != 30) { /* In 12-hour format we display 'am' or 'pm' instead of '00'. */ - if (minute == 0 + if (show_midnight_date) + strcpy (buffer, midnight_month); + else if (minute == 0 && !e_calendar_view_get_use_24_hour_format (E_CALENDAR_VIEW (day_view))) { strcpy (buffer, suffix); } else { @@ -466,7 +576,10 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, } cairo_save (cr); - gdk_cairo_set_source_color (cr, &fg); + if (show_midnight_date) + gdk_cairo_set_source_color (cr, &mb_color); + else + gdk_cairo_set_source_color (cr, &fg); layout = pango_cairo_create_layout (cr); pango_layout_set_text (layout, buffer, -1); pango_layout_set_font_description (layout, day_view->small_font_desc); @@ -487,6 +600,28 @@ e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, pango_font_metrics_unref (large_font_metrics); pango_font_metrics_unref (small_font_metrics); cairo_destroy (cr); + + g_free (midnight_day); + g_free (midnight_month); +} + +static void +e_day_view_time_item_draw (GnomeCanvasItem *canvas_item, + GdkDrawable *drawable, + int x, + int y, + int width, + int height) +{ + EDayViewTimeItem *dvtmitem; + + dvtmitem = E_DAY_VIEW_TIME_ITEM (canvas_item); + g_return_if_fail (dvtmitem != NULL); + + edvti_draw_zone (canvas_item, drawable, x, y, width, height, 0, NULL); + + if (dvtmitem->second_zone) + edvti_draw_zone (canvas_item, drawable, x, y, width, height, dvtmitem->column_width, dvtmitem->second_zone); } /* Increment the time by the 5/10/15/30/60 minute interval. @@ -551,6 +686,37 @@ e_day_view_time_item_event (GnomeCanvasItem *item, return FALSE; } +static void +edvti_second_zone_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data) +{ + EDayViewTimeItem *dvtmitem = user_data; + char *location; + + g_return_if_fail (user_data != NULL); + g_return_if_fail (E_IS_DAY_VIEW_TIME_ITEM (dvtmitem)); + + location = calendar_config_get_day_second_zone (); + dvtmitem->second_zone = location ? icaltimezone_get_builtin_timezone (location) : NULL; + g_free (location); + + gtk_widget_set_size_request (dvtmitem->day_view->time_canvas, e_day_view_time_item_get_column_width (dvtmitem), -1); + gtk_widget_queue_draw (dvtmitem->day_view->time_canvas); +} + +static void +edvti_on_select_zone (GtkWidget *item, EDayViewTimeItem *dvtmitem) +{ + calendar_config_select_day_second_zone (); +} + +static void +edvti_on_set_zone (GtkWidget *item, EDayViewTimeItem *dvtmitem) +{ + if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item))) + return; + + calendar_config_set_day_second_zone (g_object_get_data (G_OBJECT (item), "timezone")); +} static void e_day_view_time_item_show_popup_menu (EDayViewTimeItem *dvtmitem, @@ -559,10 +725,11 @@ e_day_view_time_item_show_popup_menu (EDayViewTimeItem *dvtmitem, static gint divisions[] = { 60, 30, 15, 10, 5 }; EDayView *day_view; gint num_divisions = sizeof (divisions) / sizeof (divisions[0]); - GtkWidget *menu, *item; + GtkWidget *menu, *item, *submenu; gchar buffer[256]; - GSList *group = NULL; + GSList *group = NULL, *recent_zones, *s; gint current_divisions, i; + icaltimezone *zone; day_view = dvtmitem->day_view; g_return_if_fail (day_view != NULL); @@ -596,6 +763,61 @@ e_day_view_time_item_show_popup_menu (EDayViewTimeItem *dvtmitem, G_CALLBACK (e_day_view_time_item_on_set_divisions), dvtmitem); } + item = gtk_separator_menu_item_new (); + gtk_widget_show (item); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + + submenu = gtk_menu_new (); + item = gtk_menu_item_new_with_label (_("Show the second time zone")); + gtk_widget_show (item); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu); + + zone = e_calendar_view_get_timezone (E_CALENDAR_VIEW (day_view)); + if (zone) + item = gtk_menu_item_new_with_label (icaltimezone_get_display_name (zone)); + else + item = gtk_menu_item_new_with_label ("---"); + gtk_widget_set_sensitive (item, FALSE); + gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item); + + item = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item); + + group = NULL; + item = gtk_radio_menu_item_new_with_label (group, _("None")); + group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item)); + if (!dvtmitem->second_zone) + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE); + gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item); + g_signal_connect (item, "toggled", G_CALLBACK (edvti_on_set_zone), dvtmitem); + + recent_zones = calendar_config_get_day_second_zones (); + for (s = recent_zones; s != NULL; s = s->next) { + zone = icaltimezone_get_builtin_timezone (s->data); + if (!zone) + continue; + + item = gtk_radio_menu_item_new_with_label (group, icaltimezone_get_display_name (zone)); + group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item)); + /* both comes from builtin, thus no problem to compare pointers */ + if (zone == dvtmitem->second_zone) + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE); + gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item); + g_object_set_data_full (G_OBJECT (item), "timezone", g_strdup (s->data), g_free); + g_signal_connect (item, "toggled", G_CALLBACK (edvti_on_set_zone), dvtmitem); + } + calendar_config_free_day_second_zones (recent_zones); + + item = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item); + + item = gtk_menu_item_new_with_label (_("Select...")); + g_signal_connect (item, "activate", G_CALLBACK (edvti_on_select_zone), dvtmitem); + gtk_menu_shell_append (GTK_MENU_SHELL (submenu), item); + + gtk_widget_show_all (submenu); + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, event->button.button, event->button.time); } diff --git a/calendar/gui/e-day-view-time-item.h b/calendar/gui/e-day-view-time-item.h index 67d1213c7a..f3f2f64118 100644 --- a/calendar/gui/e-day-view-time-item.h +++ b/calendar/gui/e-day-view-time-item.h @@ -53,6 +53,10 @@ typedef struct { /* TRUE if we are currently dragging the selection times. */ gboolean dragging_selection; + + /* the second timezone shown here; NULL if none; do not free it, it's from the builtin zones */ + guint second_zone_changed_id; + icaltimezone *second_zone; } EDayViewTimeItem; typedef struct { -- cgit v1.2.3