diff options
Diffstat (limited to 'widgets/misc/e-cell-date-edit.c')
-rw-r--r-- | widgets/misc/e-cell-date-edit.c | 1033 |
1 files changed, 0 insertions, 1033 deletions
diff --git a/widgets/misc/e-cell-date-edit.c b/widgets/misc/e-cell-date-edit.c deleted file mode 100644 index 38aaf590c6..0000000000 --- a/widgets/misc/e-cell-date-edit.c +++ /dev/null @@ -1,1033 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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) - * - */ - -/* - * ECellDateEdit - a subclass of ECellPopup used to show a date with a popup - * window to edit it. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "e-cell-date-edit.h" - -#include <string.h> -#include <time.h> -#include <glib.h> - -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> - -#include <table/e-table-item.h> -#include <table/e-cell-text.h> - -#include <glib/gi18n.h> - -#include <libedataserver/e-time-utils.h> - -/* This depends on ECalendar which is why I didn't put it in gal. */ -#include "e-calendar.h" - -static void e_cell_date_edit_destroy (GtkObject *object); -static void e_cell_date_edit_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); -static void e_cell_date_edit_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); - -static gint e_cell_date_edit_do_popup (ECellPopup *ecp, - GdkEvent *event, - gint row, - gint view_col); -static void e_cell_date_edit_set_popup_values (ECellDateEdit *ecde); -static void e_cell_date_edit_select_matching_time(ECellDateEdit *ecde, - gchar *time); -static void e_cell_date_edit_show_popup (ECellDateEdit *ecde, - gint row, - gint view_col); -static void e_cell_date_edit_get_popup_pos (ECellDateEdit *ecde, - gint row, - gint view_col, - gint *x, - gint *y, - gint *height, - gint *width); - -static void e_cell_date_edit_rebuild_time_list (ECellDateEdit *ecde); - -static gint e_cell_date_edit_key_press (GtkWidget *popup_window, - GdkEventKey *event, - ECellDateEdit *ecde); -static gint e_cell_date_edit_button_press (GtkWidget *popup_window, - GdkEventButton *event, - ECellDateEdit *ecde); -static void e_cell_date_edit_on_ok_clicked (GtkWidget *button, - ECellDateEdit *ecde); -static void e_cell_date_edit_show_time_invalid_warning (ECellDateEdit *ecde); -static void e_cell_date_edit_on_now_clicked (GtkWidget *button, - ECellDateEdit *ecde); -static void e_cell_date_edit_on_none_clicked (GtkWidget *button, - ECellDateEdit *ecde); -static void e_cell_date_edit_on_today_clicked (GtkWidget *button, - ECellDateEdit *ecde); -static void e_cell_date_edit_update_cell (ECellDateEdit *ecde, - const gchar *text); -static void e_cell_date_edit_on_time_selected (GtkTreeSelection *selection, ECellDateEdit *ecde); -static void e_cell_date_edit_hide_popup (ECellDateEdit *ecde); - - -/* Our arguments. */ -enum { - PROP_0, - PROP_SHOW_TIME, - PROP_SHOW_NOW_BUTTON, - PROP_SHOW_TODAY_BUTTON, - PROP_ALLOW_NO_DATE_SET, - PROP_USE_24_HOUR_FORMAT, - PROP_LOWER_HOUR, - PROP_UPPER_HOUR -}; - -G_DEFINE_TYPE (ECellDateEdit, e_cell_date_edit, E_CELL_POPUP_TYPE) - - -static void -e_cell_date_edit_class_init (ECellDateEditClass *class) -{ - GObjectClass *object_class; - GtkObjectClass *gtk_object_class; - ECellPopupClass *ecpc; - - object_class = G_OBJECT_CLASS (class); - object_class->get_property = e_cell_date_edit_get_property; - object_class->set_property = e_cell_date_edit_set_property; - - gtk_object_class = GTK_OBJECT_CLASS (class); - gtk_object_class->destroy = e_cell_date_edit_destroy; - - ecpc = E_CELL_POPUP_CLASS (class); - ecpc->popup = e_cell_date_edit_do_popup; - - g_object_class_install_property ( - object_class, - PROP_SHOW_TIME, - g_param_spec_boolean ( - "show_time", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SHOW_NOW_BUTTON, - g_param_spec_boolean ( - "show_now_button", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_SHOW_TODAY_BUTTON, - g_param_spec_boolean ( - "show_today_button", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_ALLOW_NO_DATE_SET, - g_param_spec_boolean ( - "allow_no_date_set", - NULL, - 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", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_LOWER_HOUR, - g_param_spec_int ( - "lower_hour", - NULL, - NULL, - G_MININT, - G_MAXINT, - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property ( - object_class, - PROP_UPPER_HOUR, - g_param_spec_int ( - "upper_hour", - NULL, - NULL, - G_MININT, - G_MAXINT, - 24, - G_PARAM_READWRITE)); -} - - -static void -e_cell_date_edit_init (ECellDateEdit *ecde) -{ - GtkWidget *frame, *vbox, *hbox, *vbox2; - GtkWidget *scrolled_window, *bbox, *tree_view; - GtkWidget *now_button, *today_button, *none_button, *ok_button; - GtkListStore *store; - - ecde->lower_hour = 0; - ecde->upper_hour = 24; - ecde->use_24_hour_format = TRUE; - ecde->need_time_list_rebuild = TRUE; - ecde->freeze_count = 0; - ecde->time_callback = NULL; - ecde->time_callback_data = NULL; - ecde->time_callback_destroy = NULL; - - /* We create one popup window for the ECell, since there will only - ever be one popup in use at a time. */ - ecde->popup_window = gtk_window_new (GTK_WINDOW_POPUP); - - gtk_window_set_type_hint (GTK_WINDOW (ecde->popup_window), - GDK_WINDOW_TYPE_HINT_COMBO); - gtk_window_set_resizable (GTK_WINDOW (ecde->popup_window), TRUE); - - frame = gtk_frame_new (NULL); - gtk_container_add (GTK_CONTAINER (ecde->popup_window), frame); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); - gtk_widget_show (frame); - - vbox = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (frame), vbox); - gtk_widget_show (vbox); - - hbox = gtk_hbox_new (FALSE, 4); - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - ecde->calendar = e_calendar_new (); - gnome_canvas_item_set (GNOME_CANVAS_ITEM (E_CALENDAR (ecde->calendar)->calitem), - "move_selection_when_moving", FALSE, - NULL); - gtk_box_pack_start (GTK_BOX (hbox), ecde->calendar, TRUE, TRUE, 0); - gtk_widget_show (ecde->calendar); - - vbox2 = gtk_vbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0); - gtk_widget_show (vbox2); - - ecde->time_entry = gtk_entry_new (); - gtk_widget_set_size_request (ecde->time_entry, 50, -1); - gtk_box_pack_start (GTK_BOX (vbox2), ecde->time_entry, - FALSE, FALSE, 0); - gtk_widget_show (ecde->time_entry); - - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_box_pack_start (GTK_BOX (vbox2), scrolled_window, TRUE, TRUE, 0); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_NEVER, - GTK_POLICY_ALWAYS); - gtk_widget_show (scrolled_window); - - store = gtk_list_store_new (1, G_TYPE_STRING); - tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); - g_object_unref (store); - - gtk_tree_view_append_column ( - GTK_TREE_VIEW (tree_view), - gtk_tree_view_column_new_with_attributes ("Text", gtk_cell_renderer_text_new (), "text", 0, NULL)); - - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), FALSE); - - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), tree_view); - gtk_container_set_focus_vadjustment (GTK_CONTAINER (tree_view), - gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window))); - gtk_container_set_focus_hadjustment (GTK_CONTAINER (tree_view), - gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window))); - gtk_widget_show (tree_view); - ecde->time_tree_view = tree_view; - g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)), "changed", - G_CALLBACK (e_cell_date_edit_on_time_selected), - ecde); - - 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); - - now_button = gtk_button_new_with_label (_("Now")); - gtk_container_add (GTK_CONTAINER (bbox), now_button); - gtk_widget_show (now_button); - g_signal_connect((now_button), "clicked", - G_CALLBACK (e_cell_date_edit_on_now_clicked), - ecde); - ecde->now_button = now_button; - - today_button = gtk_button_new_with_label (_("Today")); - gtk_container_add (GTK_CONTAINER (bbox), today_button); - gtk_widget_show (today_button); - g_signal_connect((today_button), "clicked", - G_CALLBACK (e_cell_date_edit_on_today_clicked), - ecde); - ecde->today_button = today_button; - - none_button = gtk_button_new_with_label (_("None")); - gtk_container_add (GTK_CONTAINER (bbox), none_button); - gtk_widget_show (none_button); - g_signal_connect((none_button), "clicked", - G_CALLBACK (e_cell_date_edit_on_none_clicked), - ecde); - ecde->none_button = none_button; - - ok_button = gtk_button_new_with_label (_("OK")); - gtk_container_add (GTK_CONTAINER (bbox), ok_button); - gtk_widget_show (ok_button); - g_signal_connect((ok_button), "clicked", - G_CALLBACK (e_cell_date_edit_on_ok_clicked), - ecde); - - - g_signal_connect((ecde->popup_window), - "key_press_event", - G_CALLBACK (e_cell_date_edit_key_press), - ecde); - g_signal_connect((ecde->popup_window), - "button_press_event", - G_CALLBACK (e_cell_date_edit_button_press), - ecde); -} - - -/** - * e_cell_date_edit_new: - * - * Creates a new ECellDateEdit renderer. - * - * Returns: an ECellDateEdit object. - */ -ECell * -e_cell_date_edit_new (void) -{ - return g_object_new (e_cell_date_edit_get_type (), NULL); -} - - -/* - * GtkObject::destroy method - */ -static void -e_cell_date_edit_destroy (GtkObject *object) -{ - ECellDateEdit *ecde = E_CELL_DATE_EDIT (object); - - e_cell_date_edit_set_get_time_callback (ecde, NULL, NULL, NULL); - - gtk_widget_destroy (ecde->popup_window); - ecde->popup_window = NULL; - - GTK_OBJECT_CLASS (e_cell_date_edit_parent_class)->destroy (object); -} - - -static void -e_cell_date_edit_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - ECellDateEdit *ecde; - - ecde = E_CELL_DATE_EDIT (object); - - switch (property_id) { - case PROP_SHOW_TIME: - g_value_set_boolean (value, GTK_WIDGET_VISIBLE (ecde->time_entry)); - return; - case PROP_SHOW_NOW_BUTTON: - g_value_set_boolean (value, GTK_WIDGET_VISIBLE (ecde->now_button)); - return; - case PROP_SHOW_TODAY_BUTTON: - g_value_set_boolean (value, GTK_WIDGET_VISIBLE (ecde->today_button)); - return; - case PROP_ALLOW_NO_DATE_SET: - g_value_set_boolean (value, GTK_WIDGET_VISIBLE (ecde->none_button)); - return; - case PROP_USE_24_HOUR_FORMAT: - g_value_set_boolean (value, ecde->use_24_hour_format); - return; - case PROP_LOWER_HOUR: - g_value_set_int (value, ecde->lower_hour); - return; - case PROP_UPPER_HOUR: - g_value_set_int (value, ecde->upper_hour); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - - -static void -e_cell_date_edit_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - ECellDateEdit *ecde; - gint ivalue; - gboolean bvalue; - - ecde = E_CELL_DATE_EDIT (object); - - switch (property_id) { - case PROP_SHOW_TIME: - if (g_value_get_boolean (value)) { - gtk_widget_show (ecde->time_entry); - gtk_widget_show (ecde->time_tree_view); - } else { - gtk_widget_hide (ecde->time_entry); - gtk_widget_hide (ecde->time_tree_view); - } - return; - case PROP_SHOW_NOW_BUTTON: - if (g_value_get_boolean (value)) { - gtk_widget_show (ecde->now_button); - } else { - gtk_widget_hide (ecde->now_button); - } - return; - case PROP_SHOW_TODAY_BUTTON: - if (g_value_get_boolean (value)) { - gtk_widget_show (ecde->today_button); - } else { - gtk_widget_hide (ecde->today_button); - } - return; - case PROP_ALLOW_NO_DATE_SET: - if (g_value_get_boolean (value)) { - gtk_widget_show (ecde->none_button); - } else { - /* FIXME: What if we have no date set now. */ - gtk_widget_hide (ecde->none_button); - } - return; - case PROP_USE_24_HOUR_FORMAT: - bvalue = g_value_get_boolean (value); - if (ecde->use_24_hour_format != bvalue) { - ecde->use_24_hour_format = bvalue; - ecde->need_time_list_rebuild = TRUE; - } - return; - case PROP_LOWER_HOUR: - ivalue = g_value_get_int (value); - ivalue = CLAMP (ivalue, 0, 24); - if (ecde->lower_hour != ivalue) { - ecde->lower_hour = ivalue; - ecde->need_time_list_rebuild = TRUE; - } - return; - case PROP_UPPER_HOUR: - ivalue = g_value_get_int (value); - ivalue = CLAMP (ivalue, 0, 24); - if (ecde->upper_hour != ivalue) { - ecde->upper_hour = ivalue; - ecde->need_time_list_rebuild = TRUE; - } - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - - -static gint -e_cell_date_edit_do_popup (ECellPopup *ecp, - GdkEvent *event, - gint row, - gint view_col) -{ - ECellDateEdit *ecde = E_CELL_DATE_EDIT (ecp); - - e_cell_date_edit_show_popup (ecde, row, view_col); - e_cell_date_edit_set_popup_values (ecde); - - gtk_grab_add (ecde->popup_window); - - /* Set the focus to the first widget. */ - gtk_widget_grab_focus (ecde->time_entry); - gdk_window_focus (ecde->popup_window->window, GDK_CURRENT_TIME); - - return TRUE; -} - - -static void -e_cell_date_edit_set_popup_values (ECellDateEdit *ecde) -{ - ECellPopup *ecp = E_CELL_POPUP (ecde); - ECellText *ecell_text = E_CELL_TEXT (ecp->child); - ECellView *ecv = (ECellView*) ecp->popup_cell_view; - ETableItem *eti = E_TABLE_ITEM (ecp->popup_cell_view->cell_view.e_table_item_view); - ETableCol *ecol; - gchar *cell_text; - ETimeParseStatus status; - struct tm date_tm; - GDate date; - ECalendarItem *calitem; - gchar buffer[64]; - gboolean is_date = TRUE; - - ecol = e_table_header_get_column (eti->header, ecp->popup_view_col); - cell_text = e_cell_text_get_text (ecell_text, ecv->e_table_model, - ecol->col_idx, ecp->popup_row); - - /* Try to parse just a date first. If the value is only a date, we - use a DATE value. */ - status = e_time_parse_date (cell_text, &date_tm); - if (status == E_TIME_PARSE_INVALID) { - is_date = FALSE; - status = e_time_parse_date_and_time (cell_text, &date_tm); - } - - /* If there is no date and time set, or the date is invalid, we clear - the selections, else we select the appropriate date & time. */ - calitem = E_CALENDAR_ITEM (E_CALENDAR (ecde->calendar)->calitem); - if (status == E_TIME_PARSE_NONE || status == E_TIME_PARSE_INVALID) { - gtk_entry_set_text (GTK_ENTRY (ecde->time_entry), ""); - e_calendar_item_set_selection (calitem, NULL, NULL); - gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (ecde->time_tree_view))); - } else { - if (is_date) { - buffer[0] = '\0'; - } else { - e_time_format_time (&date_tm, ecde->use_24_hour_format, - FALSE, buffer, sizeof (buffer)); - } - gtk_entry_set_text (GTK_ENTRY (ecde->time_entry), buffer); - - g_date_clear (&date, 1); - g_date_set_dmy (&date, date_tm.tm_mday, date_tm.tm_mon + 1, - date_tm.tm_year + 1900); - e_calendar_item_set_selection (calitem, &date, &date); - - if (is_date) { - gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (ecde->time_tree_view))); - } else { - e_cell_date_edit_select_matching_time (ecde, buffer); - } - } - - e_cell_text_free_text (ecell_text, cell_text); -} - - -static void -e_cell_date_edit_select_matching_time (ECellDateEdit *ecde, - gchar *time) -{ - gboolean found = FALSE; - gboolean valid; - GtkTreeSelection *selection; - GtkTreeIter iter; - GtkTreeModel *model; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (ecde->time_tree_view)); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ecde->time_tree_view)); - - for (valid = gtk_tree_model_get_iter_first (model, &iter); - valid && !found; - valid = gtk_tree_model_iter_next (model, &iter)) { - gchar *str = NULL; - - gtk_tree_model_get (model, &iter, 0, &str, -1); - - if (g_str_equal (str, time)) { - GtkTreePath *path = gtk_tree_model_get_path (model, &iter); - - gtk_tree_view_set_cursor (GTK_TREE_VIEW (ecde->time_tree_view), path, NULL, FALSE); - gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (ecde->time_tree_view), path, NULL, FALSE, 0.0, 0.0); - gtk_tree_path_free (path); - - found = TRUE; - } - - g_free (str); - } - - if (!found) { - gtk_tree_selection_unselect_all (selection); - gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (ecde->time_tree_view), 0, 0); - } -} - - -static void -e_cell_date_edit_show_popup (ECellDateEdit *ecde, - gint row, - gint view_col) -{ - gint x, y, width, height; - - if (ecde->need_time_list_rebuild) - e_cell_date_edit_rebuild_time_list (ecde); - - /* This code is practically copied from GtkCombo. */ - - e_cell_date_edit_get_popup_pos (ecde, row, view_col, &x, &y, &height, &width); - - gtk_window_move (GTK_WINDOW (ecde->popup_window), x, y); - gtk_widget_set_size_request (ecde->popup_window, width, height); - gtk_widget_realize (ecde->popup_window); - gdk_window_resize (ecde->popup_window->window, width, height); - gtk_widget_show (ecde->popup_window); - - e_cell_popup_set_shown (E_CELL_POPUP (ecde), TRUE); -} - - -/* Calculates the size and position of the popup window (like GtkCombo). */ -static void -e_cell_date_edit_get_popup_pos (ECellDateEdit *ecde, - gint row, - gint view_col, - gint *x, - gint *y, - gint *height, - gint *width) -{ - ECellPopup *ecp = E_CELL_POPUP (ecde); - ETableItem *eti = E_TABLE_ITEM (ecp->popup_cell_view->cell_view.e_table_item_view); - GtkWidget *canvas = GTK_WIDGET (GNOME_CANVAS_ITEM (eti)->canvas); - GtkRequisition popup_requisition; - gint avail_height, screen_width, column_width, row_height; - double x1, y1, wx, wy; - - gdk_window_get_origin (canvas->window, x, y); - - x1 = e_table_header_col_diff (eti->header, 0, view_col + 1); - y1 = e_table_item_row_diff (eti, 0, row + 1); - column_width = e_table_header_col_diff (eti->header, view_col, - view_col + 1); - row_height = e_table_item_row_diff (eti, row, - row + 1); - gnome_canvas_item_i2w (GNOME_CANVAS_ITEM (eti), &x1, &y1); - - gnome_canvas_world_to_window (GNOME_CANVAS (canvas), - x1, - y1, - &wx, - &wy); - - x1 = wx; - y1 = wy; - - *x += x1; - /* The ETable positions don't include the grid lines, I think, so we - add 1. */ - *y += y1 + 1 - - (gint)((GnomeCanvas *)canvas)->layout.vadjustment->value - + ((GnomeCanvas *)canvas)->zoom_yofs; - - avail_height = gdk_screen_height () - *y; - - /* We'll use the entire screen width if needed, but we save space for - the vertical scrollbar in case we need to show that. */ - screen_width = gdk_screen_width (); - - gtk_widget_size_request (ecde->popup_window, &popup_requisition); - - /* Calculate the desired width. */ - *width = popup_requisition.width; - - /* Use at least the same width as the column. */ - if (*width < column_width) - *width = column_width; - - /* Check if it fits in the available height. */ - if (popup_requisition.height > avail_height) { - /* It doesn't fit, so we see if we have the minimum space - needed. */ - if (*y - row_height > avail_height) { - /* We don't, so we show the popup above the cell - instead of below it. */ - avail_height = *y - row_height; - *y -= (popup_requisition.height + row_height); - if (*y < 0) - *y = 0; - } - } - - /* We try to line it up with the right edge of the column, but we don't - want it to go off the edges of the screen. */ - if (*x > screen_width) - *x = screen_width; - *x -= *width; - if (*x < 0) - *x = 0; - - *height = popup_requisition.height; -} - - -/* This handles key press events in the popup window. If the Escape key is - pressed we hide the popup, and do not change the cell contents. */ -static gint -e_cell_date_edit_key_press (GtkWidget *popup_window, - GdkEventKey *event, - ECellDateEdit *ecde) -{ - /* If the Escape key is pressed we hide the popup. */ - if (event->keyval != GDK_Escape) - return FALSE; - - e_cell_date_edit_hide_popup (ecde); - - return TRUE; -} - - -/* This handles button press events in the popup window. If the button is - pressed outside the popup, we hide it and do not change the cell contents. -*/ -static gint -e_cell_date_edit_button_press (GtkWidget *popup_window, - GdkEventButton *event, - ECellDateEdit *ecde) -{ - GtkWidget *event_widget; - - event_widget = gtk_get_event_widget ((GdkEvent*) event); - if (gtk_widget_get_toplevel (event_widget) != popup_window) { - e_cell_date_edit_hide_popup (ecde); - } - - return TRUE; -} - - -/* Clears the time list and rebuilds it using the lower_hour, upper_hour - and use_24_hour_format settings. */ -static void -e_cell_date_edit_rebuild_time_list (ECellDateEdit *ecde) -{ - GtkListStore *store; - gchar buffer[40]; - struct tm tmp_tm; - gint hour, min; - - store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (ecde->time_tree_view))); - gtk_list_store_clear (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 = ecde->lower_hour; hour <= ecde->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 != ecde->upper_hour); - min += 30) { - GtkTreeIter iter; - - tmp_tm.tm_hour = hour; - tmp_tm.tm_min = min; - e_time_format_time (&tmp_tm, ecde->use_24_hour_format, - FALSE, buffer, sizeof (buffer)); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, buffer, -1); - } - } - - ecde->need_time_list_rebuild = FALSE; -} - - -static void -e_cell_date_edit_on_ok_clicked (GtkWidget *button, - ECellDateEdit *ecde) -{ - ECalendarItem *calitem; - GDate start_date, end_date; - gboolean day_selected; - struct tm date_tm; - gchar buffer[64]; - const gchar *text; - ETimeParseStatus status; - gboolean is_date = FALSE; - - calitem = E_CALENDAR_ITEM (E_CALENDAR (ecde->calendar)->calitem); - day_selected = e_calendar_item_get_selection (calitem, &start_date, - &end_date); - - text = gtk_entry_get_text (GTK_ENTRY (ecde->time_entry)); - status = e_time_parse_time (text, &date_tm); - if (status == E_TIME_PARSE_INVALID) { - e_cell_date_edit_show_time_invalid_warning (ecde); - return; - } else if (status == E_TIME_PARSE_NONE) { - is_date = TRUE; - } - - if (day_selected) { - date_tm.tm_year = g_date_get_year (&start_date) - 1900; - date_tm.tm_mon = g_date_get_month (&start_date) - 1; - date_tm.tm_mday = g_date_get_day (&start_date); - /* We need to call this to set the weekday. */ - mktime (&date_tm); - e_time_format_date_and_time (&date_tm, - ecde->use_24_hour_format, - !is_date, FALSE, - buffer, sizeof (buffer)); - } else { - buffer[0] = '\0'; - } - - e_cell_date_edit_update_cell (ecde, buffer); - e_cell_date_edit_hide_popup (ecde); -} - - -static void -e_cell_date_edit_show_time_invalid_warning (ECellDateEdit *ecde) -{ - GtkWidget *dialog; - struct tm date_tm; - gchar buffer[64]; - - /* Create a useful error message showing the correct format. */ - date_tm.tm_year = 100; - date_tm.tm_mon = 0; - date_tm.tm_mday = 1; - date_tm.tm_hour = 1; - date_tm.tm_min = 30; - date_tm.tm_sec = 0; - date_tm.tm_isdst = -1; - e_time_format_time (&date_tm, ecde->use_24_hour_format, FALSE, - buffer, sizeof (buffer)); - - /* FIXME: Fix transient settings - I'm not sure it works with popup - windows. Maybe we need to use a normal window without decorations.*/ - dialog = gtk_message_dialog_new ( - GTK_WINDOW (ecde->popup_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, - _("The time must be in the format: %s"), - buffer); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); -} - - -static void -e_cell_date_edit_on_now_clicked (GtkWidget *button, - ECellDateEdit *ecde) -{ - struct tm tmp_tm; - time_t t; - gchar buffer[64]; - - if (ecde->time_callback) { - tmp_tm = (*ecde->time_callback) (ecde, ecde->time_callback_data); - } else { - t = time (NULL); - tmp_tm = *localtime (&t); - } - e_time_format_date_and_time (&tmp_tm, - ecde->use_24_hour_format, - TRUE, FALSE, - buffer, sizeof (buffer)); - - e_cell_date_edit_update_cell (ecde, buffer); - e_cell_date_edit_hide_popup (ecde); -} - - -static void -e_cell_date_edit_on_none_clicked (GtkWidget *button, - ECellDateEdit *ecde) -{ - e_cell_date_edit_update_cell (ecde, ""); - e_cell_date_edit_hide_popup (ecde); -} - - -static void -e_cell_date_edit_on_today_clicked (GtkWidget *button, - ECellDateEdit *ecde) -{ - struct tm tmp_tm; - time_t t; - gchar buffer[64]; - - if (ecde->time_callback) { - tmp_tm = (*ecde->time_callback) (ecde, ecde->time_callback_data); - } else { - t = time (NULL); - tmp_tm = *localtime (&t); - } - - tmp_tm.tm_hour = 0; - tmp_tm.tm_min = 0; - tmp_tm.tm_sec = 0; - e_time_format_date_and_time (&tmp_tm, - ecde->use_24_hour_format, - FALSE, FALSE, - buffer, sizeof (buffer)); - - e_cell_date_edit_update_cell (ecde, buffer); - e_cell_date_edit_hide_popup (ecde); -} - - -static void -e_cell_date_edit_update_cell (ECellDateEdit *ecde, - const gchar *text) -{ - ECellPopup *ecp = E_CELL_POPUP (ecde); - ECellText *ecell_text = E_CELL_TEXT (ecp->child); - ECellView *ecv = (ECellView*) ecp->popup_cell_view; - ETableItem *eti = E_TABLE_ITEM (ecv->e_table_item_view); - ETableCol *ecol; - gchar *old_text; - - /* Compare the new text with the existing cell contents. */ - ecol = e_table_header_get_column (eti->header, ecp->popup_view_col); - - old_text = e_cell_text_get_text (ecell_text, ecv->e_table_model, - ecol->col_idx, ecp->popup_row); - - /* If they are different, update the cell contents. */ - if (strcmp (old_text, text)) { - e_cell_text_set_value (ecell_text, ecv->e_table_model, - ecol->col_idx, ecp->popup_row, text); - e_cell_leave_edit (ecv, ecp->popup_view_col, ecol->col_idx, ecp->popup_row, NULL); - } - - e_cell_text_free_text (ecell_text, old_text); -} - - -static void -e_cell_date_edit_on_time_selected (GtkTreeSelection *selection, ECellDateEdit *ecde) -{ - gchar *list_item_text = NULL; - GtkTreeIter iter; - GtkTreeModel *model; - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) - return; - - gtk_tree_model_get (model, &iter, 0, &list_item_text, -1); - - g_return_if_fail (list_item_text != NULL); - - gtk_entry_set_text (GTK_ENTRY (ecde->time_entry), list_item_text); - - g_free (list_item_text); -} - - -static void -e_cell_date_edit_hide_popup (ECellDateEdit *ecde) -{ - gtk_grab_remove (ecde->popup_window); - gtk_widget_hide (ecde->popup_window); - e_cell_popup_set_shown (E_CELL_POPUP (ecde), FALSE); -} - - -/* These freeze and thaw the rebuilding of the time list. They are useful when - setting several properties which result in rebuilds of the list, e.g. the - lower_hour, upper_hour and use_24_hour_format properties. */ -void -e_cell_date_edit_freeze (ECellDateEdit *ecde) -{ - g_return_if_fail (E_IS_CELL_DATE_EDIT (ecde)); - - ecde->freeze_count++; -} - - -void -e_cell_date_edit_thaw (ECellDateEdit *ecde) -{ - g_return_if_fail (E_IS_CELL_DATE_EDIT (ecde)); - - if (ecde->freeze_count > 0) { - ecde->freeze_count--; - - if (ecde->freeze_count == 0) - e_cell_date_edit_rebuild_time_list (ecde); - } -} - - -/* 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_cell_date_edit_set_get_time_callback (ECellDateEdit *ecde, - ECellDateEditGetTimeCallback cb, - gpointer data, - GDestroyNotify destroy) -{ - g_return_if_fail (E_IS_CELL_DATE_EDIT (ecde)); - - if (ecde->time_callback_data && ecde->time_callback_destroy) - (*ecde->time_callback_destroy) (ecde->time_callback_data); - - ecde->time_callback = cb; - ecde->time_callback_data = data; - ecde->time_callback_destroy = destroy; -} |