diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2012-12-10 21:09:59 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2012-12-13 03:33:43 +0800 |
commit | d09d8de870b6697c8a8b262e7e077b871a69b315 (patch) | |
tree | 3b718882e7a0bb0a996daf2967a033d91714c9b5 /widgets/misc/e-dateedit.c | |
parent | b61331ed03ac1c7a9b8614e25510040b9c60ae02 (diff) | |
download | gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.gz gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.bz2 gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.lz gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.xz gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.zst gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.zip |
Consolidate base utility libraries into libeutil.
Evolution consists of entirely too many small utility libraries, which
increases linking and loading time, places a burden on higher layers of
the application (e.g. modules) which has to remember to link to all the
small in-tree utility libraries, and makes it difficult to generate API
documentation for these utility libraries in one Gtk-Doc module.
Merge the following utility libraries under the umbrella of libeutil,
and enforce a single-include policy on libeutil so we can reorganize
the files as desired without disrupting its pseudo-public API.
libemail-utils/libemail-utils.la
libevolution-utils/libevolution-utils.la
filter/libfilter.la
widgets/e-timezone-dialog/libetimezonedialog.la
widgets/menus/libmenus.la
widgets/misc/libemiscwidgets.la
widgets/table/libetable.la
widgets/text/libetext.la
This also merges libedataserverui from the Evolution-Data-Server module,
since Evolution is its only consumer nowadays, and I'd like to make some
improvements to those APIs without concern for backward-compatibility.
And finally, start a Gtk-Doc module for libeutil. It's going to be a
project just getting all the symbols _listed_ much less _documented_.
But the skeletal structure is in place and I'm off to a good start.
Diffstat (limited to 'widgets/misc/e-dateedit.c')
-rw-r--r-- | widgets/misc/e-dateedit.c | 2498 |
1 files changed, 0 insertions, 2498 deletions
diff --git a/widgets/misc/e-dateedit.c b/widgets/misc/e-dateedit.c deleted file mode 100644 index fd2676a6b4..0000000000 --- a/widgets/misc/e-dateedit.c +++ /dev/null @@ -1,2498 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * Authors: - * Damon Chaplin <damon@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - */ - -/* - * EDateEdit - a widget based on GnomeDateEdit to provide a date & optional - * time field with popups for entering a date. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-dateedit.h" - -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <gdk/gdkkeysyms.h> -#include <atk/atkrelation.h> -#include <atk/atkrelationset.h> -#include <glib/gi18n.h> - -#include <libebackend/libebackend.h> - -#include <e-util/e-util.h> -#include "e-calendar.h" - -#define E_DATE_EDIT_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_DATE_EDIT, EDateEditPrivate)) - -struct _EDateEditPrivate { - GtkWidget *date_entry; - GtkWidget *date_button; - - GtkWidget *space; - - GtkWidget *time_combo; - - GtkWidget *cal_popup; - GtkWidget *calendar; - GtkWidget *now_button; - GtkWidget *today_button; - GtkWidget *none_button; /* This will only be visible if a - * 'None' date/time is permitted. */ - - GdkDevice *grabbed_keyboard; - GdkDevice *grabbed_pointer; - - gboolean show_date; - gboolean show_time; - gboolean use_24_hour_format; - - /* This is TRUE if we want to make the time field insensitive rather - * than hide it when set_show_time() is called. */ - gboolean make_time_insensitive; - - /* This is the range of hours we show in the time popup. */ - gint lower_hour; - gint upper_hour; - - /* This indicates whether the last date committed was invalid. - * (A date is committed by hitting Return, moving the keyboard focus, - * or selecting a date in the popup). Note that this only indicates - * that the date couldn't be parsed. A date set to 'None' is valid - * here, though e_date_edit_date_is_valid() will return FALSE if an - * empty date isn't actually permitted. */ - gboolean date_is_valid; - - /* This is the last valid date which was set. If the date was set to - * 'None' or empty, date_set_to_none will be TRUE and the other fields - * are undefined, so don't use them. */ - gboolean date_set_to_none; - gint year; - gint month; - gint day; - - /* This indicates whether the last time committed was invalid. - * (A time is committed by hitting Return, moving the keyboard focus, - * or selecting a time in the popup). Note that this only indicates - * that the time couldn't be parsed. An empty/None time is valid - * here, though e_date_edit_time_is_valid() will return FALSE if an - * empty time isn't actually permitted. */ - gboolean time_is_valid; - - /* This is the last valid time which was set. If the time was set to - * 'None' or empty, time_set_to_none will be TRUE and the other fields - * are undefined, so don't use them. */ - gboolean time_set_to_none; - gint hour; - gint minute; - - EDateEditGetTimeCallback time_callback; - gpointer time_callback_data; - GDestroyNotify time_callback_destroy; - - gboolean twodigit_year_can_future; - - /* set to TRUE when the date has been changed by typing to the entry */ - gboolean has_been_changed; - - gboolean allow_no_date_set; -}; - -enum { - PROP_0, - PROP_ALLOW_NO_DATE_SET, - PROP_SHOW_DATE, - PROP_SHOW_TIME, - PROP_SHOW_WEEK_NUMBERS, - PROP_USE_24_HOUR_FORMAT, - PROP_WEEK_START_DAY, - PROP_TWODIGIT_YEAR_CAN_FUTURE, - PROP_SET_NONE -}; - -enum { - CHANGED, - LAST_SIGNAL -}; - -static void create_children (EDateEdit *dedit); -static gboolean e_date_edit_mnemonic_activate (GtkWidget *widget, - gboolean group_cycling); -static void e_date_edit_grab_focus (GtkWidget *widget); - -static gint on_date_entry_key_press (GtkWidget *widget, - GdkEvent *key_event, - EDateEdit *dedit); -static gint on_date_entry_key_release (GtkWidget *widget, - GdkEvent *key_event, - EDateEdit *dedit); -static void on_date_button_clicked (GtkWidget *widget, - EDateEdit *dedit); -static void e_date_edit_show_date_popup (EDateEdit *dedit, - GdkEvent *event); -static void position_date_popup (EDateEdit *dedit); -static void on_date_popup_none_button_clicked (GtkWidget *button, - EDateEdit *dedit); -static void on_date_popup_today_button_clicked (GtkWidget *button, - EDateEdit *dedit); -static void on_date_popup_now_button_clicked (GtkWidget *button, - EDateEdit *dedit); -static gint on_date_popup_delete_event (GtkWidget *widget, - EDateEdit *dedit); -static gint on_date_popup_key_press (GtkWidget *widget, - GdkEventKey *event, - EDateEdit *dedit); -static gint on_date_popup_button_press (GtkWidget *widget, - GdkEvent *button_event, - gpointer data); -static void on_date_popup_date_selected (ECalendarItem *calitem, - EDateEdit *dedit); -static void hide_date_popup (EDateEdit *dedit); -static void rebuild_time_popup (EDateEdit *dedit); -static gboolean field_set_to_none (const gchar *text); -static gboolean e_date_edit_parse_date (EDateEdit *dedit, - const gchar *date_text, - struct tm *date_tm); -static gboolean e_date_edit_parse_time (EDateEdit *dedit, - const gchar *time_text, - struct tm *time_tm); -static void on_date_edit_time_selected (GtkComboBox *combo, - EDateEdit *dedit); -static gint on_time_entry_key_press (GtkWidget *widget, - GdkEvent *key_event, - EDateEdit *dedit); -static gint on_time_entry_key_release (GtkWidget *widget, - GdkEvent *key_event, - EDateEdit *dedit); -static gint on_date_entry_focus_out (GtkEntry *entry, - GdkEventFocus *event, - EDateEdit *dedit); -static gint on_time_entry_focus_out (GtkEntry *entry, - GdkEventFocus *event, - EDateEdit *dedit); -static void e_date_edit_update_date_entry (EDateEdit *dedit); -static void e_date_edit_update_time_entry (EDateEdit *dedit); -static void e_date_edit_update_time_combo_state (EDateEdit *dedit); -static void e_date_edit_check_date_changed (EDateEdit *dedit); -static void e_date_edit_check_time_changed (EDateEdit *dedit); -static gboolean e_date_edit_set_date_internal (EDateEdit *dedit, - gboolean valid, - gboolean none, - gint year, - gint month, - gint day); -static gboolean e_date_edit_set_time_internal (EDateEdit *dedit, - gboolean valid, - gboolean none, - gint hour, - gint minute); - -static gint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE_WITH_CODE ( - EDateEdit, - e_date_edit, - GTK_TYPE_HBOX, - G_IMPLEMENT_INTERFACE ( - E_TYPE_EXTENSIBLE, NULL)) - -static void -date_edit_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ALLOW_NO_DATE_SET: - e_date_edit_set_allow_no_date_set ( - E_DATE_EDIT (object), - g_value_get_boolean (value)); - return; - - case PROP_SHOW_DATE: - e_date_edit_set_show_date ( - E_DATE_EDIT (object), - g_value_get_boolean (value)); - return; - - case PROP_SHOW_TIME: - e_date_edit_set_show_time ( - E_DATE_EDIT (object), - g_value_get_boolean (value)); - return; - - case PROP_SHOW_WEEK_NUMBERS: - e_date_edit_set_show_week_numbers ( - E_DATE_EDIT (object), - g_value_get_boolean (value)); - return; - - case PROP_USE_24_HOUR_FORMAT: - e_date_edit_set_use_24_hour_format ( - E_DATE_EDIT (object), - g_value_get_boolean (value)); - return; - - case PROP_WEEK_START_DAY: - e_date_edit_set_week_start_day ( - E_DATE_EDIT (object), - g_value_get_int (value)); - return; - - case PROP_TWODIGIT_YEAR_CAN_FUTURE: - e_date_edit_set_twodigit_year_can_future ( - E_DATE_EDIT (object), - g_value_get_boolean (value)); - return; - - case PROP_SET_NONE: - if (g_value_get_boolean (value)) - e_date_edit_set_time (E_DATE_EDIT (object), -1); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -date_edit_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ALLOW_NO_DATE_SET: - g_value_set_boolean ( - value, e_date_edit_get_allow_no_date_set ( - E_DATE_EDIT (object))); - return; - - case PROP_SHOW_DATE: - g_value_set_boolean ( - value, e_date_edit_get_show_date ( - E_DATE_EDIT (object))); - return; - - case PROP_SHOW_TIME: - g_value_set_boolean ( - value, e_date_edit_get_show_time ( - E_DATE_EDIT (object))); - return; - - case PROP_SHOW_WEEK_NUMBERS: - g_value_set_boolean ( - value, e_date_edit_get_show_week_numbers ( - E_DATE_EDIT (object))); - return; - - case PROP_USE_24_HOUR_FORMAT: - g_value_set_boolean ( - value, e_date_edit_get_use_24_hour_format ( - E_DATE_EDIT (object))); - return; - - case PROP_WEEK_START_DAY: - g_value_set_int ( - value, e_date_edit_get_week_start_day ( - E_DATE_EDIT (object))); - return; - - case PROP_TWODIGIT_YEAR_CAN_FUTURE: - g_value_set_boolean ( - value, e_date_edit_get_twodigit_year_can_future ( - E_DATE_EDIT (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -date_edit_dispose (GObject *object) -{ - EDateEdit *dedit; - - dedit = E_DATE_EDIT (object); - - e_date_edit_set_get_time_callback (dedit, NULL, NULL, NULL); - - if (dedit->priv->cal_popup != NULL) { - gtk_widget_destroy (dedit->priv->cal_popup); - dedit->priv->cal_popup = NULL; - } - - if (dedit->priv->grabbed_keyboard != NULL) { - gdk_device_ungrab ( - dedit->priv->grabbed_keyboard, - GDK_CURRENT_TIME); - g_object_unref (dedit->priv->grabbed_keyboard); - dedit->priv->grabbed_keyboard = NULL; - } - - if (dedit->priv->grabbed_pointer != NULL) { - gdk_device_ungrab ( - dedit->priv->grabbed_pointer, - GDK_CURRENT_TIME); - g_object_unref (dedit->priv->grabbed_pointer); - dedit->priv->grabbed_pointer = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_date_edit_parent_class)->dispose (object); -} - -static void -e_date_edit_class_init (EDateEditClass *class) -{ - GObjectClass *object_class; - GtkWidgetClass *widget_class; - - g_type_class_add_private (class, sizeof (EDateEditPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = date_edit_set_property; - object_class->get_property = date_edit_get_property; - object_class->dispose = date_edit_dispose; - - widget_class = GTK_WIDGET_CLASS (class); - widget_class->mnemonic_activate = e_date_edit_mnemonic_activate; - widget_class->grab_focus = e_date_edit_grab_focus; - - g_object_class_install_property ( - object_class, - PROP_ALLOW_NO_DATE_SET, - g_param_spec_boolean ( - "allow-no-date-set", - "Allow No Date Set", - NULL, - FALSE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SHOW_DATE, - g_param_spec_boolean ( - "show-date", - "Show Date", - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SHOW_TIME, - g_param_spec_boolean ( - "show-time", - "Show Time", - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SHOW_WEEK_NUMBERS, - g_param_spec_boolean ( - "show-week-numbers", - "Show Week Numbers", - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_USE_24_HOUR_FORMAT, - g_param_spec_boolean ( - "use-24-hour-format", - "Use 24-Hour Format", - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_WEEK_START_DAY, - g_param_spec_int ( - "week-start-day", - "Week Start Day", - NULL, - 0, /* Monday */ - 6, /* Sunday */ - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_TWODIGIT_YEAR_CAN_FUTURE, - g_param_spec_boolean ( - "twodigit-year-can-future", - "Two-digit year can be treated as future", - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SET_NONE, - g_param_spec_boolean ( - "set-none", - "Sets None as selected date", - NULL, - FALSE, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - signals[CHANGED] = g_signal_new ( - "changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EDateEditClass, changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -e_date_edit_init (EDateEdit *dedit) -{ - dedit->priv = E_DATE_EDIT_GET_PRIVATE (dedit); - - dedit->priv->show_date = TRUE; - dedit->priv->show_time = TRUE; - dedit->priv->use_24_hour_format = TRUE; - - dedit->priv->make_time_insensitive = FALSE; - - dedit->priv->lower_hour = 0; - dedit->priv->upper_hour = 24; - - dedit->priv->date_is_valid = TRUE; - dedit->priv->date_set_to_none = TRUE; - dedit->priv->time_is_valid = TRUE; - dedit->priv->time_set_to_none = TRUE; - dedit->priv->time_callback = NULL; - dedit->priv->time_callback_data = NULL; - dedit->priv->time_callback_destroy = NULL; - - dedit->priv->twodigit_year_can_future = TRUE; - dedit->priv->has_been_changed = FALSE; - - create_children (dedit); - - /* Set it to the current time. */ - e_date_edit_set_time (dedit, 0); - - e_extensible_load_extensions (E_EXTENSIBLE (dedit)); -} - -/** - * e_date_edit_new: - * - * Description: Creates a new #EDateEdit widget which can be used - * to provide an easy to use way for entering dates and times. - * - * Returns: a new #EDateEdit widget. - */ -GtkWidget * -e_date_edit_new (void) -{ - EDateEdit *dedit; - AtkObject *a11y; - - dedit = g_object_new (E_TYPE_DATE_EDIT, NULL); - a11y = gtk_widget_get_accessible (GTK_WIDGET (dedit)); - atk_object_set_name (a11y, _("Date and Time")); - - return GTK_WIDGET (dedit); -} - -static void -create_children (EDateEdit *dedit) -{ - EDateEditPrivate *priv; - ECalendar *calendar; - GtkWidget *frame, *arrow; - GtkWidget *vbox, *bbox; - GtkWidget *child; - AtkObject *a11y; - GtkListStore *time_store; - GList *cells; - GtkCssProvider *css_provider; - GtkStyleContext *style_context; - const gchar *css; - GError *error = NULL; - - priv = dedit->priv; - - priv->date_entry = gtk_entry_new (); - a11y = gtk_widget_get_accessible (priv->date_entry); - atk_object_set_description (a11y, _("Text entry to input date")); - atk_object_set_name (a11y, _("Date")); - gtk_box_pack_start (GTK_BOX (dedit), priv->date_entry, FALSE, TRUE, 0); - gtk_widget_set_size_request (priv->date_entry, 100, -1); - - g_signal_connect ( - priv->date_entry, "key_press_event", - G_CALLBACK (on_date_entry_key_press), dedit); - g_signal_connect ( - priv->date_entry, "key_release_event", - G_CALLBACK (on_date_entry_key_release), dedit); - g_signal_connect_after ( - priv->date_entry, "focus_out_event", - G_CALLBACK (on_date_entry_focus_out), dedit); - - priv->date_button = gtk_button_new (); - g_signal_connect ( - priv->date_button, "clicked", - G_CALLBACK (on_date_button_clicked), dedit); - gtk_box_pack_start ( - GTK_BOX (dedit), priv->date_button, - FALSE, FALSE, 0); - a11y = gtk_widget_get_accessible (priv->date_button); - atk_object_set_description (a11y, _("Click this button to show a calendar")); - atk_object_set_name (a11y, _("Date")); - - arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE); - gtk_container_add (GTK_CONTAINER (priv->date_button), arrow); - gtk_widget_show (arrow); - - if (priv->show_date) { - gtk_widget_show (priv->date_entry); - gtk_widget_show (priv->date_button); - } - - /* This is just to create a space between the date & time parts. */ - priv->space = gtk_drawing_area_new (); - gtk_box_pack_start (GTK_BOX (dedit), priv->space, FALSE, FALSE, 2); - - time_store = gtk_list_store_new (1, G_TYPE_STRING); - priv->time_combo = gtk_combo_box_new_with_model_and_entry ( - GTK_TREE_MODEL (time_store)); - gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (priv->time_combo), 0); - g_object_unref (time_store); - - css_provider = gtk_css_provider_new (); - css = "GtkComboBox { -GtkComboBox-appears-as-list: 1; }"; - gtk_css_provider_load_from_data (css_provider, css, -1, &error); - style_context = gtk_widget_get_style_context (priv->time_combo); - if (error == NULL) { - gtk_style_context_add_provider ( - style_context, - GTK_STYLE_PROVIDER (css_provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - } else { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_clear_error (&error); - } - g_object_unref (css_provider); - - child = gtk_bin_get_child (GTK_BIN (priv->time_combo)); - - /* We need to make sure labels are right-aligned, since we want - * digits to line up, and with a nonproportional font, the width - * of a space != width of a digit. Technically, only 12-hour - * format needs this, but we do it always, for consistency. */ - g_object_set (child, "xalign", 1.0, NULL); - cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->time_combo)); - if (cells) { - g_object_set (GTK_CELL_RENDERER (cells->data), "xalign", 1.0, NULL); - g_list_free (cells); - } - - gtk_box_pack_start (GTK_BOX (dedit), priv->time_combo, FALSE, TRUE, 0); - gtk_widget_set_size_request (priv->time_combo, 110, -1); - rebuild_time_popup (dedit); - a11y = gtk_widget_get_accessible (priv->time_combo); - atk_object_set_description (a11y, _("Drop-down combination box to select time")); - atk_object_set_name (a11y, _("Time")); - - g_signal_connect ( - child, "key_press_event", - G_CALLBACK (on_time_entry_key_press), dedit); - g_signal_connect ( - child, "key_release_event", - G_CALLBACK (on_time_entry_key_release), dedit); - g_signal_connect_after ( - child, "focus_out_event", - G_CALLBACK (on_time_entry_focus_out), dedit); - g_signal_connect_after ( - priv->time_combo, "changed", - G_CALLBACK (on_date_edit_time_selected), dedit); - - if (priv->show_time || priv->make_time_insensitive) - gtk_widget_show (priv->time_combo); - - if (!priv->show_time && priv->make_time_insensitive) - gtk_widget_set_sensitive (priv->time_combo, FALSE); - - if (priv->show_date - && (priv->show_time || priv->make_time_insensitive)) - gtk_widget_show (priv->space); - - priv->cal_popup = gtk_window_new (GTK_WINDOW_POPUP); - gtk_window_set_type_hint ( - GTK_WINDOW (priv->cal_popup), - GDK_WINDOW_TYPE_HINT_COMBO); - gtk_widget_set_events ( - priv->cal_popup, - gtk_widget_get_events (priv->cal_popup) - | GDK_KEY_PRESS_MASK); - g_signal_connect ( - priv->cal_popup, "delete_event", - G_CALLBACK (on_date_popup_delete_event), dedit); - g_signal_connect ( - priv->cal_popup, "key_press_event", - G_CALLBACK (on_date_popup_key_press), dedit); - g_signal_connect ( - priv->cal_popup, "button_press_event", - G_CALLBACK (on_date_popup_button_press), dedit); - gtk_window_set_resizable (GTK_WINDOW (priv->cal_popup), TRUE); - - frame = gtk_frame_new (NULL); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); - gtk_container_add (GTK_CONTAINER (priv->cal_popup), frame); - gtk_widget_show (frame); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (frame), vbox); - gtk_widget_show (vbox); - - priv->calendar = e_calendar_new (); - calendar = E_CALENDAR (priv->calendar); - gnome_canvas_item_set ( - GNOME_CANVAS_ITEM (calendar->calitem), - "maximum_days_selected", 1, - "move_selection_when_moving", FALSE, - NULL); - - g_signal_connect ( - calendar->calitem, "selection_changed", - G_CALLBACK (on_date_popup_date_selected), dedit); - - gtk_box_pack_start (GTK_BOX (vbox), priv->calendar, FALSE, FALSE, 0); - gtk_widget_show (priv->calendar); - - bbox = gtk_hbutton_box_new (); - gtk_container_set_border_width (GTK_CONTAINER (bbox), 4); - gtk_box_set_spacing (GTK_BOX (bbox), 2); - gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0); - gtk_widget_show (bbox); - - priv->now_button = gtk_button_new_with_mnemonic (_("No_w")); - gtk_container_add (GTK_CONTAINER (bbox), priv->now_button); - gtk_widget_show (priv->now_button); - g_signal_connect ( - priv->now_button, "clicked", - G_CALLBACK (on_date_popup_now_button_clicked), dedit); - - priv->today_button = gtk_button_new_with_mnemonic (_("_Today")); - gtk_container_add (GTK_CONTAINER (bbox), priv->today_button); - gtk_widget_show (priv->today_button); - g_signal_connect ( - priv->today_button, "clicked", - G_CALLBACK (on_date_popup_today_button_clicked), dedit); - - /* Note that we don't show this here, since by default a 'None' date - * is not permitted. */ - priv->none_button = gtk_button_new_with_mnemonic (_("_None")); - gtk_container_add (GTK_CONTAINER (bbox), priv->none_button); - g_signal_connect ( - priv->none_button, "clicked", - G_CALLBACK (on_date_popup_none_button_clicked), dedit); - g_object_bind_property ( - dedit, "allow-no-date-set", - priv->none_button, "visible", - G_BINDING_SYNC_CREATE); -} - -/* GtkWidget::mnemonic_activate() handler for the EDateEdit */ -static gboolean -e_date_edit_mnemonic_activate (GtkWidget *widget, - gboolean group_cycling) -{ - e_date_edit_grab_focus (widget); - return TRUE; -} - -/* Grab_focus handler for the EDateEdit. If the date field is being shown, we - * grab the focus to that, otherwise we grab it to the time field. */ -static void -e_date_edit_grab_focus (GtkWidget *widget) -{ - EDateEdit *dedit; - GtkWidget *child; - - g_return_if_fail (E_IS_DATE_EDIT (widget)); - - dedit = E_DATE_EDIT (widget); - child = gtk_bin_get_child (GTK_BIN (dedit->priv->time_combo)); - - if (dedit->priv->show_date) - gtk_widget_grab_focus (dedit->priv->date_entry); - else - gtk_widget_grab_focus (child); -} - -/** - * e_date_edit_set_editable: - * @dedit: an #EDateEdit widget. - * @editable: whether or not the widget should accept edits. - * - * Allows the programmer to disallow editing (and the popping up of - * the calendar widget), while still allowing the user to select the - * date from the GtkEntry. - */ -void -e_date_edit_set_editable (EDateEdit *dedit, - gboolean editable) -{ - EDateEditPrivate *priv; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - priv = dedit->priv; - - gtk_editable_set_editable (GTK_EDITABLE (priv->date_entry), editable); - gtk_widget_set_sensitive (priv->date_button, editable); -} - -/** - * e_date_edit_get_time: - * @dedit: an #EDateEdit widget. - * @the_time: returns the last valid time entered. - * @Returns: the last valid time entered, or -1 if the time is not set. - * - * Returns the last valid time entered. If empty times are valid, by calling - * e_date_edit_set_allow_no_date_set(), then it may return -1. - * - * Note that the last time entered may actually have been invalid. You can - * check this with e_date_edit_time_is_valid(). - */ -time_t -e_date_edit_get_time (EDateEdit *dedit) -{ - EDateEditPrivate *priv; - struct tm tmp_tm = { 0 }; - - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), -1); - - priv = dedit->priv; - - /* Try to parse any new value now. */ - e_date_edit_check_date_changed (dedit); - e_date_edit_check_time_changed (dedit); - - if (priv->date_set_to_none) - return -1; - - tmp_tm.tm_year = priv->year; - tmp_tm.tm_mon = priv->month; - tmp_tm.tm_mday = priv->day; - - if (!priv->show_time || priv->time_set_to_none) { - tmp_tm.tm_hour = 0; - tmp_tm.tm_min = 0; - } else { - tmp_tm.tm_hour = priv->hour; - tmp_tm.tm_min = priv->minute; - } - tmp_tm.tm_sec = 0; - tmp_tm.tm_isdst = -1; - - return mktime (&tmp_tm); -} - -/** - * e_date_edit_set_time: - * @dedit: the EDateEdit widget - * @the_time: The time and date that should be set on the widget - * - * Description: Changes the displayed date and time in the EDateEdit - * widget to be the one represented by @the_time. If @the_time is 0 - * then current time is used. If it is -1, then the date is set to None. - * - * Note that the time is converted to local time using the Unix timezone, - * so if you are using your own timezones then you should use - * e_date_edit_set_date() and e_date_edit_set_time_of_day() instead. - */ -void -e_date_edit_set_time (EDateEdit *dedit, - time_t the_time) -{ - EDateEditPrivate *priv; - struct tm tmp_tm; - gboolean date_changed = FALSE, time_changed = FALSE; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - priv = dedit->priv; - - if (the_time == -1) { - date_changed = e_date_edit_set_date_internal ( - dedit, TRUE, - TRUE, 0, 0, 0); - time_changed = e_date_edit_set_time_internal ( - dedit, TRUE, - TRUE, 0, 0); - } else { - if (the_time == 0) { - if (priv->time_callback) { - tmp_tm = (*priv->time_callback) (dedit, priv->time_callback_data); - } else { - the_time = time (NULL); - tmp_tm = *localtime (&the_time); - } - } else { - tmp_tm = *localtime (&the_time); - } - - date_changed = e_date_edit_set_date_internal ( - dedit, TRUE, - FALSE, - tmp_tm.tm_year, - tmp_tm.tm_mon, - tmp_tm.tm_mday); - time_changed = e_date_edit_set_time_internal ( - dedit, TRUE, - FALSE, - tmp_tm.tm_hour, - tmp_tm.tm_min); - } - - e_date_edit_update_date_entry (dedit); - e_date_edit_update_time_entry (dedit); - e_date_edit_update_time_combo_state (dedit); - - /* Emit the signals if the date and/or time has actually changed. */ - if (date_changed || time_changed) - g_signal_emit (dedit, signals[CHANGED], 0); -} - -/** - * e_date_edit_get_date: - * @dedit: an #EDateEdit widget. - * @year: returns the year set. - * @month: returns the month set (1 - 12). - * @day: returns the day set (1 - 31). - * @Returns: TRUE if a time was set, or FALSE if the field is empty or 'None'. - * - * Returns the last valid date entered into the date field. - */ -gboolean -e_date_edit_get_date (EDateEdit *dedit, - gint *year, - gint *month, - gint *day) -{ - EDateEditPrivate *priv; - - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE); - - priv = dedit->priv; - - /* Try to parse any new value now. */ - e_date_edit_check_date_changed (dedit); - - *year = priv->year + 1900; - *month = priv->month + 1; - *day = priv->day; - - if (priv->date_set_to_none - && e_date_edit_get_allow_no_date_set (dedit)) - return FALSE; - - return TRUE; -} - -/** - * e_date_edit_set_date: - * @dedit: an #EDateEdit widget. - * @year: the year to set. - * @month: the month to set (1 - 12). - * @day: the day to set (1 - 31). - * - * Sets the date in the date field. - */ -void -e_date_edit_set_date (EDateEdit *dedit, - gint year, - gint month, - gint day) -{ - gboolean date_changed = FALSE; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - date_changed = e_date_edit_set_date_internal ( - dedit, TRUE, FALSE, - year - 1900, month - 1, - day); - - e_date_edit_update_date_entry (dedit); - e_date_edit_update_time_combo_state (dedit); - - /* Emit the signals if the date has actually changed. */ - if (date_changed) - g_signal_emit (dedit, signals[CHANGED], 0); -} - -/** - * e_date_edit_get_time_of_day: - * @dedit: an #EDateEdit widget. - * @hour: returns the hour set, or 0 if the time isn't set. - * @minute: returns the minute set, or 0 if the time isn't set. - * @Returns: TRUE if a time was set, or FALSE if the field is empty or 'None'. - * - * Returns the last valid time entered into the time field. - */ -gboolean -e_date_edit_get_time_of_day (EDateEdit *dedit, - gint *hour, - gint *minute) -{ - EDateEditPrivate *priv; - - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE); - - priv = dedit->priv; - - /* Try to parse any new value now. */ - e_date_edit_check_time_changed (dedit); - - if (priv->time_set_to_none) { - *hour = 0; - *minute = 0; - return FALSE; - } else { - *hour = priv->hour; - *minute = priv->minute; - return TRUE; - } -} - -/** - * e_date_edit_set_time_of_day: - * @dedit: an #EDateEdit widget. - * @hour: the hour to set, or -1 to set the time to None (i.e. empty). - * @minute: the minute to set. - * - * Description: Sets the time in the time field. - */ -void -e_date_edit_set_time_of_day (EDateEdit *dedit, - gint hour, - gint minute) -{ - EDateEditPrivate *priv; - gboolean time_changed = FALSE; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - priv = dedit->priv; - - if (hour == -1) { - gboolean allow_no_date_set = e_date_edit_get_allow_no_date_set (dedit); - g_return_if_fail (allow_no_date_set); - if (!priv->time_set_to_none) { - priv->time_set_to_none = TRUE; - time_changed = TRUE; - } - } else if (priv->time_set_to_none - || priv->hour != hour - || priv->minute != minute) { - priv->time_set_to_none = FALSE; - priv->hour = hour; - priv->minute = minute; - time_changed = TRUE; - } - - e_date_edit_update_time_entry (dedit); - - if (time_changed) - g_signal_emit (dedit, signals[CHANGED], 0); -} - -void -e_date_edit_set_date_and_time_of_day (EDateEdit *dedit, - gint year, - gint month, - gint day, - gint hour, - gint minute) -{ - gboolean date_changed, time_changed; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - date_changed = e_date_edit_set_date_internal ( - dedit, TRUE, FALSE, - year - 1900, month - 1, day); - time_changed = e_date_edit_set_time_internal ( - dedit, TRUE, FALSE, - hour, minute); - - e_date_edit_update_date_entry (dedit); - e_date_edit_update_time_entry (dedit); - e_date_edit_update_time_combo_state (dedit); - - if (date_changed || time_changed) - g_signal_emit (dedit, signals[CHANGED], 0); -} - -/** - * e_date_edit_get_show_date: - * @dedit: an #EDateEdit widget. - * @Returns: Whether the date field is shown. - * - * Description: Returns TRUE if the date field is currently shown. - */ -gboolean -e_date_edit_get_show_date (EDateEdit *dedit) -{ - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), TRUE); - - return dedit->priv->show_date; -} - -/** - * e_date_edit_set_show_date: - * @dedit: an #EDateEdit widget. - * @show_date: TRUE if the date field should be shown. - * - * Description: Specifies whether the date field should be shown. The date - * field would be hidden if only a time needed to be entered. - */ -void -e_date_edit_set_show_date (EDateEdit *dedit, - gboolean show_date) -{ - EDateEditPrivate *priv; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - priv = dedit->priv; - - if (priv->show_date == show_date) - return; - - priv->show_date = show_date; - - if (show_date) { - gtk_widget_show (priv->date_entry); - gtk_widget_show (priv->date_button); - } else { - gtk_widget_hide (priv->date_entry); - gtk_widget_hide (priv->date_button); - } - - e_date_edit_update_time_combo_state (dedit); - - if (priv->show_date - && (priv->show_time || priv->make_time_insensitive)) - gtk_widget_show (priv->space); - else - gtk_widget_hide (priv->space); - - g_object_notify (G_OBJECT (dedit), "show-date"); -} - -/** - * e_date_edit_get_show_time: - * @dedit: an #EDateEdit widget - * @Returns: Whether the time field is shown. - * - * Description: Returns TRUE if the time field is currently shown. - */ -gboolean -e_date_edit_get_show_time (EDateEdit *dedit) -{ - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), TRUE); - - return dedit->priv->show_time; -} - -/** - * e_date_edit_set_show_time: - * @dedit: an #EDateEdit widget - * @show_time: TRUE if the time field should be shown. - * - * Description: Specifies whether the time field should be shown. The time - * field would be hidden if only a date needed to be entered. - */ -void -e_date_edit_set_show_time (EDateEdit *dedit, - gboolean show_time) -{ - EDateEditPrivate *priv; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - priv = dedit->priv; - - if (priv->show_time == show_time) - return; - - priv->show_time = show_time; - - e_date_edit_update_time_combo_state (dedit); - - g_object_notify (G_OBJECT (dedit), "show-time"); -} - -/** - * e_date_edit_get_make_time_insensitive: - * @dedit: an #EDateEdit widget - * @Returns: Whether the time field is be made insensitive instead of hiding - * it. - * - * Description: Returns TRUE if the time field is made insensitive instead of - * hiding it. - */ -gboolean -e_date_edit_get_make_time_insensitive (EDateEdit *dedit) -{ - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), TRUE); - - return dedit->priv->make_time_insensitive; -} - -/** - * e_date_edit_set_make_time_insensitive: - * @dedit: an #EDateEdit widget - * @make_insensitive: TRUE if the time field should be made insensitive instead - * of hiding it. - * - * Description: Specifies whether the time field should be made insensitive - * rather than hiding it. Note that this doesn't make it insensitive - you - * need to call e_date_edit_set_show_time() with FALSE as show_time to do that. - * - * This is useful if you want to disable the time field, but don't want it to - * disappear as that may affect the layout of the widgets. - */ -void -e_date_edit_set_make_time_insensitive (EDateEdit *dedit, - gboolean make_insensitive) -{ - EDateEditPrivate *priv; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - priv = dedit->priv; - - if (priv->make_time_insensitive == make_insensitive) - return; - - priv->make_time_insensitive = make_insensitive; - - e_date_edit_update_time_combo_state (dedit); -} - -/** - * e_date_edit_get_week_start_day: - * @dedit: an #EDateEdit widget - * @Returns: the week start day, from 0 (Monday) to 6 (Sunday). - * - * Description: Returns the week start day currently used in the calendar - * popup. - */ -gint -e_date_edit_get_week_start_day (EDateEdit *dedit) -{ - gint week_start_day; - - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), 1); - - g_object_get ( - E_CALENDAR (dedit->priv->calendar)->calitem, - "week_start_day", &week_start_day, NULL); - - return week_start_day; -} - -/** - * e_date_edit_set_week_start_day: - * @dedit: an #EDateEdit widget - * @week_start_day: the week start day, from 0 (Monday) to 6 (Sunday). - * - * Description: Sets the week start day to use in the calendar popup. - */ -void -e_date_edit_set_week_start_day (EDateEdit *dedit, - gint week_start_day) -{ - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - gnome_canvas_item_set ( - GNOME_CANVAS_ITEM (E_CALENDAR (dedit->priv->calendar)->calitem), - "week_start_day", week_start_day, NULL); - - g_object_notify (G_OBJECT (dedit), "week-start-day"); -} - -/* Whether we show week numbers in the date popup. */ -gboolean -e_date_edit_get_show_week_numbers (EDateEdit *dedit) -{ - gboolean show_week_numbers; - - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE); - - g_object_get ( - E_CALENDAR (dedit->priv->calendar)->calitem, - "show_week_numbers", &show_week_numbers, NULL); - - return show_week_numbers; -} - -void -e_date_edit_set_show_week_numbers (EDateEdit *dedit, - gboolean show_week_numbers) -{ - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - gnome_canvas_item_set ( - GNOME_CANVAS_ITEM (E_CALENDAR (dedit->priv->calendar)->calitem), - "show_week_numbers", show_week_numbers, NULL); - - g_object_notify (G_OBJECT (dedit), "show-week-numbers"); -} - -/* Whether we use 24 hour format in the time field & popup. */ -gboolean -e_date_edit_get_use_24_hour_format (EDateEdit *dedit) -{ - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), TRUE); - - return dedit->priv->use_24_hour_format; -} - -void -e_date_edit_set_use_24_hour_format (EDateEdit *dedit, - gboolean use_24_hour_format) -{ - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - if (dedit->priv->use_24_hour_format == use_24_hour_format) - return; - - dedit->priv->use_24_hour_format = use_24_hour_format; - - rebuild_time_popup (dedit); - - e_date_edit_update_time_entry (dedit); - - g_object_notify (G_OBJECT (dedit), "use-24-hour-format"); -} - -/* Whether we allow the date to be set to 'None'. e_date_edit_get_time() will - * return (time_t) -1 in this case. */ -gboolean -e_date_edit_get_allow_no_date_set (EDateEdit *dedit) -{ - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE); - - return dedit->priv->allow_no_date_set; -} - -void -e_date_edit_set_allow_no_date_set (EDateEdit *dedit, - gboolean allow_no_date_set) -{ - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - if (dedit->priv->allow_no_date_set == allow_no_date_set) - return; - - dedit->priv->allow_no_date_set = allow_no_date_set; - - if (!allow_no_date_set) { - /* If the date is showing, we make sure it isn't 'None' (we - * don't really mind if the time is empty), else if just the - * time is showing we make sure it isn't 'None'. */ - if (dedit->priv->show_date) { - if (dedit->priv->date_set_to_none) - e_date_edit_set_time (dedit, 0); - } else { - if (dedit->priv->time_set_to_none) - e_date_edit_set_time (dedit, 0); - } - } - - g_object_notify (G_OBJECT (dedit), "allow-no-date-set"); -} - -/* The range of time to show in the time combo popup. */ -void -e_date_edit_get_time_popup_range (EDateEdit *dedit, - gint *lower_hour, - gint *upper_hour) -{ - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - *lower_hour = dedit->priv->lower_hour; - *upper_hour = dedit->priv->upper_hour; -} - -void -e_date_edit_set_time_popup_range (EDateEdit *dedit, - gint lower_hour, - gint upper_hour) -{ - EDateEditPrivate *priv; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - priv = dedit->priv; - - if (priv->lower_hour == lower_hour - && priv->upper_hour == upper_hour) - return; - - priv->lower_hour = lower_hour; - priv->upper_hour = upper_hour; - - rebuild_time_popup (dedit); - - /* Setting the combo list items seems to mess up the time entry, so - * we set it again. We have to reset it to its last valid time. */ - priv->time_is_valid = TRUE; - e_date_edit_update_time_entry (dedit); -} - -/* The arrow button beside the date field has been clicked, so we show the - * popup with the ECalendar in. */ -static void -on_date_button_clicked (GtkWidget *widget, - EDateEdit *dedit) -{ - GdkEvent *event; - - /* Obtain the GdkEvent that triggered - * the date button's "clicked" signal. */ - event = gtk_get_current_event (); - e_date_edit_show_date_popup (dedit, event); -} - -static void -e_date_edit_show_date_popup (EDateEdit *dedit, - GdkEvent *event) -{ - EDateEditPrivate *priv; - ECalendar *calendar; - GdkDevice *event_device; - GdkDevice *assoc_device; - GdkDevice *keyboard_device; - GdkDevice *pointer_device; - GdkWindow *window; - GdkGrabStatus grab_status; - struct tm mtm; - const gchar *date_text; - GDate selected_day; - gboolean clear_selection = FALSE; - guint event_time; - - priv = dedit->priv; - calendar = E_CALENDAR (priv->calendar); - - date_text = gtk_entry_get_text (GTK_ENTRY (priv->date_entry)); - if (field_set_to_none (date_text) - || !e_date_edit_parse_date (dedit, date_text, &mtm)) - clear_selection = TRUE; - - if (clear_selection) { - e_calendar_item_set_selection (calendar->calitem, NULL, NULL); - } else { - g_date_clear (&selected_day, 1); - g_date_set_dmy ( - &selected_day, mtm.tm_mday, mtm.tm_mon + 1, - mtm.tm_year + 1900); - e_calendar_item_set_selection ( - calendar->calitem, - &selected_day, NULL); - } - - /* FIXME: Hack. Change ECalendarItem so it doesn't queue signal - * emissions. */ - calendar->calitem->selection_changed = FALSE; - - position_date_popup (dedit); - gtk_widget_show (priv->cal_popup); - gtk_widget_grab_focus (priv->cal_popup); - gtk_grab_add (priv->cal_popup); - - window = gtk_widget_get_window (priv->cal_popup); - - g_return_if_fail (priv->grabbed_keyboard == NULL); - g_return_if_fail (priv->grabbed_pointer == NULL); - - event_device = gdk_event_get_device (event); - assoc_device = gdk_device_get_associated_device (event_device); - - event_time = gdk_event_get_time (event); - - if (gdk_device_get_source (event_device) == GDK_SOURCE_KEYBOARD) { - keyboard_device = event_device; - pointer_device = assoc_device; - } else { - keyboard_device = assoc_device; - pointer_device = event_device; - } - - if (keyboard_device != NULL) { - grab_status = gdk_device_grab ( - keyboard_device, - window, - GDK_OWNERSHIP_WINDOW, - TRUE, - GDK_KEY_PRESS_MASK | - GDK_KEY_RELEASE_MASK, - NULL, - event_time); - if (grab_status == GDK_GRAB_SUCCESS) { - priv->grabbed_keyboard = - g_object_ref (keyboard_device); - } - } - - if (pointer_device != NULL) { - grab_status = gdk_device_grab ( - pointer_device, - window, - GDK_OWNERSHIP_WINDOW, - TRUE, - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | - GDK_POINTER_MOTION_MASK, - NULL, - event_time); - if (grab_status == GDK_GRAB_SUCCESS) { - priv->grabbed_pointer = - g_object_ref (pointer_device); - } else if (priv->grabbed_keyboard != NULL) { - gdk_device_ungrab ( - priv->grabbed_keyboard, - event_time); - g_object_unref (priv->grabbed_keyboard); - priv->grabbed_keyboard = NULL; - } - } - - gdk_window_focus (window, event_time); -} - -/* This positions the date popup below and to the left of the arrow button, - * just before it is shown. */ -static void -position_date_popup (EDateEdit *dedit) -{ - gint x, y; - gint win_x, win_y; - gint bwidth, bheight; - GtkWidget *toplevel; - GdkWindow *window; - GtkRequisition cal_req, button_req; - gint screen_width, screen_height; - - gtk_widget_get_preferred_size (dedit->priv->cal_popup, &cal_req, NULL); - - gtk_widget_get_preferred_size (dedit->priv->date_button, &button_req, NULL); - bwidth = button_req.width; - gtk_widget_get_preferred_size ( - gtk_widget_get_parent (dedit->priv->date_button), &button_req, NULL); - bheight = button_req.height; - - gtk_widget_translate_coordinates ( - dedit->priv->date_button, - gtk_widget_get_toplevel (dedit->priv->date_button), - bwidth - cal_req.width, bheight, &x, &y); - - toplevel = gtk_widget_get_toplevel (dedit->priv->date_button); - window = gtk_widget_get_window (toplevel); - gdk_window_get_origin (window, &win_x, &win_y); - - x += win_x; - y += win_y; - - screen_width = gdk_screen_width (); - screen_height = gdk_screen_height (); - - x = CLAMP (x, 0, MAX (0, screen_width - cal_req.width)); - y = CLAMP (y, 0, MAX (0, screen_height - cal_req.height)); - - gtk_window_move (GTK_WINDOW (dedit->priv->cal_popup), x, y); -} - -/* A date has been selected in the date popup, so we set the date field - * and hide the popup. */ -static void -on_date_popup_date_selected (ECalendarItem *calitem, - EDateEdit *dedit) -{ - GDate start_date, end_date; - - hide_date_popup (dedit); - - if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) - return; - - e_date_edit_set_date ( - dedit, g_date_get_year (&start_date), - g_date_get_month (&start_date), - g_date_get_day (&start_date)); -} - -static void -on_date_popup_now_button_clicked (GtkWidget *button, - EDateEdit *dedit) -{ - hide_date_popup (dedit); - e_date_edit_set_time (dedit, 0); -} - -static void -on_date_popup_today_button_clicked (GtkWidget *button, - EDateEdit *dedit) -{ - EDateEditPrivate *priv; - struct tm tmp_tm; - time_t t; - - priv = dedit->priv; - - hide_date_popup (dedit); - - if (priv->time_callback) { - tmp_tm = (*priv->time_callback) (dedit, priv->time_callback_data); - } else { - t = time (NULL); - tmp_tm = *localtime (&t); - } - - e_date_edit_set_date ( - dedit, tmp_tm.tm_year + 1900, - tmp_tm.tm_mon + 1, tmp_tm.tm_mday); -} - -static void -on_date_popup_none_button_clicked (GtkWidget *button, - EDateEdit *dedit) -{ - hide_date_popup (dedit); - e_date_edit_set_time (dedit, -1); -} - -/* A key has been pressed while the date popup is showing. If it is the Escape - * key we hide the popup. */ -static gint -on_date_popup_key_press (GtkWidget *widget, - GdkEventKey *event, - EDateEdit *dedit) -{ - if (event->keyval == GDK_KEY_Escape) { - g_signal_stop_emission_by_name (widget, "key_press_event"); - hide_date_popup (dedit); - return TRUE; - } - - return FALSE; -} - -/* A mouse button has been pressed while the date popup is showing. - * Any button press events used to select days etc. in the popup will have - * have been handled elsewhere, so here we just hide the popup. - * (This function is yanked from gtkcombo.c) */ -static gint -on_date_popup_button_press (GtkWidget *widget, - GdkEvent *button_event, - gpointer data) -{ - EDateEdit *dedit; - GtkWidget *child; - - dedit = data; - - child = gtk_get_event_widget (button_event); - - /* We don't ask for button press events on the grab widget, so - * if an event is reported directly to the grab widget, it must - * be on a window outside the application (and thus we remove - * the popup window). Otherwise, we check if the widget is a child - * of the grab widget, and only remove the popup window if it - * is not. - */ - if (child != widget) { - while (child) { - if (child == widget) - return FALSE; - child = gtk_widget_get_parent (child); - } - } - - hide_date_popup (dedit); - - return TRUE; -} - -/* A delete event has been received for the date popup, so we hide it and - * return TRUE so it doesn't get destroyed. */ -static gint -on_date_popup_delete_event (GtkWidget *widget, - EDateEdit *dedit) -{ - hide_date_popup (dedit); - return TRUE; -} - -/* Hides the date popup, removing any grabs. */ -static void -hide_date_popup (EDateEdit *dedit) -{ - gtk_widget_hide (dedit->priv->cal_popup); - gtk_grab_remove (dedit->priv->cal_popup); - - if (dedit->priv->grabbed_keyboard != NULL) { - gdk_device_ungrab ( - dedit->priv->grabbed_keyboard, - GDK_CURRENT_TIME); - g_object_unref (dedit->priv->grabbed_keyboard); - dedit->priv->grabbed_keyboard = NULL; - } - - if (dedit->priv->grabbed_pointer != NULL) { - gdk_device_ungrab ( - dedit->priv->grabbed_pointer, - GDK_CURRENT_TIME); - g_object_unref (dedit->priv->grabbed_pointer); - dedit->priv->grabbed_pointer = NULL; - } -} - -/* Clears the time popup and rebuilds it using the lower_hour, upper_hour - * and use_24_hour_format settings. */ -static void -rebuild_time_popup (EDateEdit *dedit) -{ - EDateEditPrivate *priv; - GtkTreeModel *model; - GtkListStore *list_store; - GtkTreeIter iter; - gchar buffer[40]; - struct tm tmp_tm; - gint hour, min; - - priv = dedit->priv; - - model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->time_combo)); - list_store = GTK_LIST_STORE (model); - gtk_list_store_clear (list_store); - - /* Fill the struct tm with some sane values. */ - tmp_tm.tm_year = 2000; - tmp_tm.tm_mon = 0; - tmp_tm.tm_mday = 1; - tmp_tm.tm_sec = 0; - tmp_tm.tm_isdst = 0; - - for (hour = priv->lower_hour; hour <= priv->upper_hour; hour++) { - - /* We don't want to display midnight at the end, - * since that is really in the next day. */ - if (hour == 24) - break; - - /* We want to finish on upper_hour, with min == 0. */ - for (min = 0; - min == 0 || (min < 60 && hour != priv->upper_hour); - min += 30) { - tmp_tm.tm_hour = hour; - tmp_tm.tm_min = min; - - if (priv->use_24_hour_format) - /* This is a strftime() format. - * %H = hour (0-23), %M = minute. */ - e_time_format_time ( - &tmp_tm, 1, 0, - buffer, sizeof (buffer)); - else - /* This is a strftime() format. - * %I = hour (1-12), %M = minute, - * %p = am/pm string. */ - e_time_format_time ( - &tmp_tm, 0, 0, - buffer, sizeof (buffer)); - - /* For 12-hour am/pm format, we want space padding, - * not zero padding. This can be done with strftime's - * %l, but it's a potentially unportable extension. */ - if (!priv->use_24_hour_format && buffer[0] == '0') - buffer[0] = ' '; - - gtk_list_store_append (list_store, &iter); - gtk_list_store_set (list_store, &iter, 0, buffer, -1); - } - } -} - -static gboolean -e_date_edit_parse_date (EDateEdit *dedit, - const gchar *date_text, - struct tm *date_tm) -{ - gboolean twodigit_year = FALSE; - - if (e_time_parse_date_ex (date_text, date_tm, &twodigit_year) != E_TIME_PARSE_OK) - return FALSE; - - if (twodigit_year && !dedit->priv->twodigit_year_can_future) { - time_t t = time (NULL); - struct tm *today_tm = localtime (&t); - - /* It was only 2 digit year in dedit and it was interpreted as - * in the future, but we don't want it as this, so decrease by - * 100 years to last century. */ - if (date_tm->tm_year > today_tm->tm_year) - date_tm->tm_year -= 100; - } - - return TRUE; -} - -static gboolean -e_date_edit_parse_time (EDateEdit *dedit, - const gchar *time_text, - struct tm *time_tm) -{ - if (field_set_to_none (time_text)) { - time_tm->tm_hour = 0; - time_tm->tm_min = 0; - return TRUE; - } - - if (e_time_parse_time (time_text, time_tm) != E_TIME_PARSE_OK) - return FALSE; - - return TRUE; -} - -/* Returns TRUE if the string is empty or is "None" in the current locale. - * It ignores whitespace. */ -static gboolean -field_set_to_none (const gchar *text) -{ - const gchar *pos; - const gchar *none_string; - gint n; - - pos = text; - while (n = (gint)((guchar) * pos), isspace (n)) - pos++; - - /* Translators: "None" for date field of a date edit, shown when - * there is no date set. */ - none_string = C_("date", "None"); - - if (*pos == '\0' || !strncmp (pos, none_string, strlen (none_string))) - return TRUE; - return FALSE; -} - -static void -on_date_edit_time_selected (GtkComboBox *combo, - EDateEdit *dedit) -{ - GtkWidget *child; - - child = gtk_bin_get_child (GTK_BIN (combo)); - - /* We only want to emit signals when an item is selected explicitly, - * not when it is selected by the silly combo update thing. */ - if (gtk_combo_box_get_active (combo) == -1) - return; - - if (!gtk_widget_get_mapped (child)) - return; - - e_date_edit_check_time_changed (dedit); -} - -static gint -on_date_entry_key_press (GtkWidget *widget, - GdkEvent *key_event, - EDateEdit *dedit) -{ - GdkModifierType event_state = 0; - guint event_keyval = 0; - - gdk_event_get_keyval (key_event, &event_keyval); - gdk_event_get_state (key_event, &event_state); - - if (event_state & GDK_MOD1_MASK - && (event_keyval == GDK_KEY_Up || event_keyval == GDK_KEY_Down - || event_keyval == GDK_KEY_Return)) { - g_signal_stop_emission_by_name (widget, "key_press_event"); - e_date_edit_show_date_popup (dedit, key_event); - return TRUE; - } - - /* If the user hits the return key emit a "date_changed" signal if - * needed. But let the signal carry on. */ - if (event_keyval == GDK_KEY_Return) { - e_date_edit_check_date_changed (dedit); - return FALSE; - } - - return FALSE; -} - -static gint -on_time_entry_key_press (GtkWidget *widget, - GdkEvent *key_event, - EDateEdit *dedit) -{ - GtkWidget *child; - GdkModifierType event_state = 0; - guint event_keyval = 0; - - gdk_event_get_keyval (key_event, &event_keyval); - gdk_event_get_state (key_event, &event_state); - - child = gtk_bin_get_child (GTK_BIN (dedit->priv->time_combo)); - - /* I'd like to use Alt+Up/Down for popping up the list, like Win32, - * but the combo steals any Up/Down keys, so we use Alt + Return. */ -#if 0 - if (event_state & GDK_MOD1_MASK - && (event_keyval == GDK_KEY_Up || event_keyval == GDK_KEY_Down)) { -#else - if (event_state & GDK_MOD1_MASK && event_keyval == GDK_KEY_Return) { -#endif - g_signal_stop_emission_by_name (widget, "key_press_event"); - g_signal_emit_by_name (child, "activate", 0); - return TRUE; - } - - /* Stop the return key from emitting the activate signal, and check - * if we need to emit a "time_changed" signal. */ - if (event_keyval == GDK_KEY_Return) { - g_signal_stop_emission_by_name (widget, "key_press_event"); - e_date_edit_check_time_changed (dedit); - return TRUE; - } - - return FALSE; -} - -static gint -on_date_entry_key_release (GtkWidget *widget, - GdkEvent *key_event, - EDateEdit *dedit) -{ - e_date_edit_check_date_changed (dedit); - return TRUE; -} - -static gint -on_time_entry_key_release (GtkWidget *widget, - GdkEvent *key_event, - EDateEdit *dedit) -{ - guint event_keyval = 0; - - gdk_event_get_keyval (key_event, &event_keyval); - - if (event_keyval == GDK_KEY_Up || event_keyval == GDK_KEY_Down) { - g_signal_stop_emission_by_name (widget, "key_release_event"); - e_date_edit_check_time_changed (dedit); - return TRUE; - } - - return FALSE; -} - -static gint -on_date_entry_focus_out (GtkEntry *entry, - GdkEventFocus *event, - EDateEdit *dedit) -{ - struct tm tmp_tm; - GtkWidget *msg_dialog; - - tmp_tm.tm_year = 0; - tmp_tm.tm_mon = 0; - tmp_tm.tm_mday = 0; - - e_date_edit_check_date_changed (dedit); - - if (!e_date_edit_date_is_valid (dedit)) { - msg_dialog = gtk_message_dialog_new ( - NULL, - GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, - "%s", _("Invalid Date Value")); - gtk_dialog_run (GTK_DIALOG (msg_dialog)); - gtk_widget_destroy (msg_dialog); - e_date_edit_get_date ( - dedit, &tmp_tm.tm_year, - &tmp_tm.tm_mon, &tmp_tm.tm_mday); - e_date_edit_set_date ( - dedit, tmp_tm.tm_year, - tmp_tm.tm_mon, tmp_tm.tm_mday); - gtk_widget_grab_focus (GTK_WIDGET (entry)); - return FALSE; - } else if (e_date_edit_get_date ( - dedit, &tmp_tm.tm_year, &tmp_tm.tm_mon, &tmp_tm.tm_mday)) { - - e_date_edit_set_date ( - dedit,tmp_tm.tm_year,tmp_tm.tm_mon,tmp_tm.tm_mday); - - if (dedit->priv->has_been_changed) { - /* The previous one didn't emit changed signal, - * but we want it even here, thus doing itself. */ - g_signal_emit (dedit, signals[CHANGED], 0); - dedit->priv->has_been_changed = FALSE; - } - } else { - dedit->priv->date_set_to_none = TRUE; - e_date_edit_update_date_entry (dedit); - } - return FALSE; -} - -static gint -on_time_entry_focus_out (GtkEntry *entry, - GdkEventFocus *event, - EDateEdit *dedit) -{ - GtkWidget *msg_dialog; - - e_date_edit_check_time_changed (dedit); - - if (!e_date_edit_time_is_valid (dedit)) { - msg_dialog = gtk_message_dialog_new ( - NULL, - GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, - "%s", _("Invalid Time Value")); - gtk_dialog_run (GTK_DIALOG (msg_dialog)); - gtk_widget_destroy (msg_dialog); - e_date_edit_set_time (dedit,e_date_edit_get_time (dedit)); - gtk_widget_grab_focus (GTK_WIDGET (entry)); - return FALSE; - } - return FALSE; -} - -static void -add_relation (EDateEdit *dedit, - GtkWidget *widget) -{ - AtkObject *a11yEdit, *a11yWidget; - AtkRelationSet *set; - AtkRelation *relation; - GPtrArray *target; - gpointer target_object; - - /* add a labelled_by relation for widget for accessibility */ - - a11yEdit = gtk_widget_get_accessible (GTK_WIDGET (dedit)); - a11yWidget = gtk_widget_get_accessible (widget); - - set = atk_object_ref_relation_set (a11yWidget); - if (set != NULL) { - relation = atk_relation_set_get_relation_by_type ( - set, ATK_RELATION_LABELLED_BY); - /* check whether has a labelled_by relation already */ - if (relation != NULL) - return; - } - - set = atk_object_ref_relation_set (a11yEdit); - if (!set) - return; - - relation = atk_relation_set_get_relation_by_type ( - set, ATK_RELATION_LABELLED_BY); - if (relation != NULL) { - target = atk_relation_get_target (relation); - target_object = g_ptr_array_index (target, 0); - if (ATK_IS_OBJECT (target_object)) { - atk_object_add_relationship ( - a11yWidget, - ATK_RELATION_LABELLED_BY, - ATK_OBJECT (target_object)); - } - } -} - -/* This sets the text in the date entry according to the current settings. */ -static void -e_date_edit_update_date_entry (EDateEdit *dedit) -{ - EDateEditPrivate *priv; - gchar buffer[100]; - struct tm tmp_tm = { 0 }; - - priv = dedit->priv; - - if (priv->date_set_to_none || !priv->date_is_valid) { - gtk_entry_set_text (GTK_ENTRY (priv->date_entry), C_("date", "None")); - } else { - /* This is a strftime() format for a short date. - * %x the preferred date representation for the current locale - * without the time, but is forced to use 4 digit year. */ - gchar *format = e_time_get_d_fmt_with_4digit_year (); - time_t tt; - - tmp_tm.tm_year = priv->year; - tmp_tm.tm_mon = priv->month; - tmp_tm.tm_mday = priv->day; - tmp_tm.tm_isdst = -1; - - /* initialize all 'struct tm' members properly */ - tt = mktime (&tmp_tm); - if (tt && localtime (&tt)) - tmp_tm = *localtime (&tt); - - e_utf8_strftime (buffer, sizeof (buffer), format, &tmp_tm); - g_free (format); - gtk_entry_set_text (GTK_ENTRY (priv->date_entry), buffer); - } - - add_relation (dedit, priv->date_entry); - add_relation (dedit, priv->date_button); -} - -/* This sets the text in the time entry according to the current settings. */ -static void -e_date_edit_update_time_entry (EDateEdit *dedit) -{ - EDateEditPrivate *priv; - GtkComboBox *combo_box; - GtkWidget *child; - gchar buffer[40]; - struct tm tmp_tm = { 0 }; - - priv = dedit->priv; - - combo_box = GTK_COMBO_BOX (priv->time_combo); - child = gtk_bin_get_child (GTK_BIN (priv->time_combo)); - - if (priv->time_set_to_none || !priv->time_is_valid) { - gtk_combo_box_set_active (combo_box, -1); - gtk_entry_set_text (GTK_ENTRY (child), ""); - } else { - GtkTreeModel *model; - GtkTreeIter iter; - gboolean valid; - gchar *b; - - /* Set these to reasonable values just in case. */ - tmp_tm.tm_year = 2000; - tmp_tm.tm_mon = 0; - tmp_tm.tm_mday = 1; - - tmp_tm.tm_hour = priv->hour; - tmp_tm.tm_min = priv->minute; - - tmp_tm.tm_sec = 0; - tmp_tm.tm_isdst = -1; - - if (priv->use_24_hour_format) - /* This is a strftime() format. - * %H = hour (0-23), %M = minute. */ - e_time_format_time ( - &tmp_tm, 1, 0, buffer, sizeof (buffer)); - else - /* This is a strftime() format. - * %I = hour (1-12), %M = minute, %p = am/pm. */ - e_time_format_time ( - &tmp_tm, 0, 0, buffer, sizeof (buffer)); - - /* For 12-hour am/pm format, we want space padding, not - * zero padding. This can be done with strftime's %l, - * but it's a potentially unportable extension. */ - if (!priv->use_24_hour_format && buffer[0] == '0') - buffer[0] = ' '; - - gtk_entry_set_text (GTK_ENTRY (child), buffer); - - /* truncate left spaces */ - b = buffer; - while (*b == ' ') - b++; - - model = gtk_combo_box_get_model (combo_box); - valid = gtk_tree_model_get_iter_first (model, &iter); - - while (valid) { - gchar *text = NULL; - - gtk_tree_model_get (model, &iter, 0, &text, -1); - if (text) { - gchar *t = text; - - /* truncate left spaces */ - while (*t == ' ') - t++; - - if (strcmp (b, t) == 0) { - gtk_combo_box_set_active_iter ( - combo_box, &iter); - g_free (text); - break; - } - } - - g_free (text); - - valid = gtk_tree_model_iter_next (model, &iter); - } - } - - add_relation (dedit, priv->time_combo); -} - -static void -e_date_edit_update_time_combo_state (EDateEdit *dedit) -{ - EDateEditPrivate *priv; - gboolean show = TRUE, show_now_button = TRUE; - gboolean clear_entry = FALSE, sensitive = TRUE; - const gchar *text; - - priv = dedit->priv; - - /* If the date entry is currently shown, and it is set to None, - * clear the time entry and disable the time combo. */ - if (priv->show_date && priv->date_set_to_none) { - clear_entry = TRUE; - sensitive = FALSE; - } - - if (!priv->show_time) { - if (priv->make_time_insensitive) { - clear_entry = TRUE; - sensitive = FALSE; - } else { - show = FALSE; - } - - show_now_button = FALSE; - } - - if (clear_entry) { - GtkWidget *child; - - /* Only clear it if it isn't empty already. */ - child = gtk_bin_get_child (GTK_BIN (priv->time_combo)); - text = gtk_entry_get_text (GTK_ENTRY (child)); - if (text[0]) - gtk_entry_set_text (GTK_ENTRY (child), ""); - } - - gtk_widget_set_sensitive (priv->time_combo, sensitive); - - if (show) - gtk_widget_show (priv->time_combo); - else - gtk_widget_hide (priv->time_combo); - - if (show_now_button) - gtk_widget_show (priv->now_button); - else - gtk_widget_hide (priv->now_button); - - if (priv->show_date - && (priv->show_time || priv->make_time_insensitive)) - gtk_widget_show (priv->space); - else - gtk_widget_hide (priv->space); -} - -/* Parses the date, and if it is different from the current settings it - * updates the settings and emits a "date_changed" signal. */ -static void -e_date_edit_check_date_changed (EDateEdit *dedit) -{ - EDateEditPrivate *priv; - const gchar *date_text; - struct tm tmp_tm; - gboolean none = FALSE, valid = TRUE, date_changed = FALSE; - - priv = dedit->priv; - - tmp_tm.tm_year = 0; - tmp_tm.tm_mon = 0; - tmp_tm.tm_mday = 0; - - date_text = gtk_entry_get_text (GTK_ENTRY (priv->date_entry)); - if (field_set_to_none (date_text)) { - none = TRUE; - } else if (!e_date_edit_parse_date (dedit, date_text, &tmp_tm)) { - valid = FALSE; - tmp_tm.tm_year = 0; - tmp_tm.tm_mon = 0; - tmp_tm.tm_mday = 0; - } - - date_changed = e_date_edit_set_date_internal ( - dedit, valid, none, - tmp_tm.tm_year, - tmp_tm.tm_mon, - tmp_tm.tm_mday); - - if (date_changed) { - priv->has_been_changed = TRUE; - g_signal_emit (dedit, signals[CHANGED], 0); - } -} - -/* Parses the time, and if it is different from the current settings it - * updates the settings and emits a "time_changed" signal. */ -static void -e_date_edit_check_time_changed (EDateEdit *dedit) -{ - EDateEditPrivate *priv; - GtkWidget *child; - const gchar *time_text; - struct tm tmp_tm; - gboolean none = FALSE, valid = TRUE, time_changed; - - priv = dedit->priv; - - tmp_tm.tm_hour = 0; - tmp_tm.tm_min = 0; - - child = gtk_bin_get_child (GTK_BIN (priv->time_combo)); - time_text = gtk_entry_get_text (GTK_ENTRY (child)); - if (field_set_to_none (time_text)) - none = TRUE; - else if (!e_date_edit_parse_time (dedit, time_text, &tmp_tm)) - valid = FALSE; - - time_changed = e_date_edit_set_time_internal ( - dedit, valid, none, - tmp_tm.tm_hour, - tmp_tm.tm_min); - - if (time_changed) { - e_date_edit_update_time_entry (dedit); - g_signal_emit (dedit, signals[CHANGED], 0); - } -} - -/** - * e_date_edit_date_is_valid: - * @dedit: an #EDateEdit widget. - * @Returns: TRUE if the last date entered was valid. - * - * Returns TRUE if the last date entered was valid. - * - * Note that if this returns FALSE, you can still use e_date_edit_get_time() - * or e_date_edit_get_date() to get the last time or date entered which was - * valid. - */ -gboolean -e_date_edit_date_is_valid (EDateEdit *dedit) -{ - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE); - - if (!dedit->priv->date_is_valid) - return FALSE; - - /* If the date is empty/None and that isn't permitted, return FALSE. */ - if (dedit->priv->date_set_to_none - && !e_date_edit_get_allow_no_date_set (dedit)) - return FALSE; - - return TRUE; -} - -/** - * e_date_edit_time_is_valid: - * @dedit: an #EDateEdit widget. - * @Returns: TRUE if the last time entered was valid. - * - * Returns TRUE if the last time entered was valid. - * - * Note that if this returns FALSE, you can still use e_date_edit_get_time() - * or e_date_edit_get_time_of_day() to get the last time or time of the day - * entered which was valid. - */ -gboolean -e_date_edit_time_is_valid (EDateEdit *dedit) -{ - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE); - - if (!dedit->priv->time_is_valid) - return FALSE; - - /* If the time is empty and that isn't permitted, return FALSE. - * Note that we don't mind an empty time if the date field is shown - * - in that case we just assume 0:00. */ - if (dedit->priv->time_set_to_none && !dedit->priv->show_date - && !e_date_edit_get_allow_no_date_set (dedit)) - return FALSE; - - return TRUE; -} - -static gboolean -e_date_edit_set_date_internal (EDateEdit *dedit, - gboolean valid, - gboolean none, - gint year, - gint month, - gint day) -{ - EDateEditPrivate *priv; - gboolean date_changed = FALSE; - - priv = dedit->priv; - - if (!valid) { - /* Date is invalid. */ - if (priv->date_is_valid) { - priv->date_is_valid = FALSE; - date_changed = TRUE; - } - } else if (none) { - /* Date has been set to 'None'. */ - if (!priv->date_is_valid - || !priv->date_set_to_none) { - priv->date_is_valid = TRUE; - priv->date_set_to_none = TRUE; - date_changed = TRUE; - } - } else { - /* Date has been set to a specific date. */ - if (!priv->date_is_valid - || priv->date_set_to_none - || priv->year != year - || priv->month != month - || priv->day != day) { - priv->date_is_valid = TRUE; - priv->date_set_to_none = FALSE; - priv->year = year; - priv->month = month; - priv->day = day; - date_changed = TRUE; - } - } - - return date_changed; -} - -static gboolean -e_date_edit_set_time_internal (EDateEdit *dedit, - gboolean valid, - gboolean none, - gint hour, - gint minute) -{ - EDateEditPrivate *priv; - gboolean time_changed = FALSE; - - priv = dedit->priv; - - if (!valid) { - /* Time is invalid. */ - if (priv->time_is_valid) { - priv->time_is_valid = FALSE; - time_changed = TRUE; - } - } else if (none) { - /* Time has been set to empty/'None'. */ - if (!priv->time_is_valid - || !priv->time_set_to_none) { - priv->time_is_valid = TRUE; - priv->time_set_to_none = TRUE; - time_changed = TRUE; - } - } else { - /* Time has been set to a specific time. */ - if (!priv->time_is_valid - || priv->time_set_to_none - || priv->hour != hour - || priv->minute != minute) { - priv->time_is_valid = TRUE; - priv->time_set_to_none = FALSE; - priv->hour = hour; - priv->minute = minute; - time_changed = TRUE; - } - } - - return time_changed; -} - -gboolean -e_date_edit_get_twodigit_year_can_future (EDateEdit *dedit) -{ - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), FALSE); - - return dedit->priv->twodigit_year_can_future; -} - -void -e_date_edit_set_twodigit_year_can_future (EDateEdit *dedit, - gboolean value) -{ - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - dedit->priv->twodigit_year_can_future = value; -} - -/* Sets a callback to use to get the current time. This is useful if the - * application needs to use its own timezone data rather than rely on the - * Unix timezone. */ -void -e_date_edit_set_get_time_callback (EDateEdit *dedit, - EDateEditGetTimeCallback cb, - gpointer data, - GDestroyNotify destroy) -{ - EDateEditPrivate *priv; - - g_return_if_fail (E_IS_DATE_EDIT (dedit)); - - priv = dedit->priv; - - if (priv->time_callback_data && priv->time_callback_destroy) - (*priv->time_callback_destroy) (priv->time_callback_data); - - priv->time_callback = cb; - priv->time_callback_data = data; - priv->time_callback_destroy = destroy; - -} - -GtkWidget * -e_date_edit_get_entry (EDateEdit *dedit) -{ - g_return_val_if_fail (E_IS_DATE_EDIT (dedit), NULL); - - return GTK_WIDGET (dedit->priv->date_entry); -} |