diff options
-rw-r--r-- | calendar/ChangeLog | 13 | ||||
-rw-r--r-- | calendar/gui/Makefile.am | 2 | ||||
-rw-r--r-- | calendar/gui/dialogs/recurrence-page.c | 179 | ||||
-rw-r--r-- | calendar/gui/e-date-time-list.c | 555 | ||||
-rw-r--r-- | calendar/gui/e-date-time-list.h | 83 | ||||
-rw-r--r-- | calendar/gui/e-meeting-time-sel.c | 13 |
6 files changed, 757 insertions, 88 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 8ad5556c85..10917d46c1 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,16 @@ +2003-01-15 Hans Petter Jansson <hpj@ximian.com> + + * gui/e-meeting-time-sel.c (e_meeting_time_selector_construct): + Create accel groups for popup menus. Fixes crash. + + * gui/e-date-time-list.[ch]: Implement EDateTimeList as + CalComponentDateTime list with a GtkTreeModel interface. + + * gui/Makefile.am: Add e-date-time-list.[ch]. + + * gui/dialogs/recurrence-page.c: Use GtkTreeView with the new + EDateTimeList as model for the exception list. + 2003-01-15 Rodney Dawes <dobey@ximian.com> * gui/Makefile.am: Added libevolution_calendar_la_LDFLAGS, and diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 589b0d592b..345220f627 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -98,6 +98,8 @@ libevolution_calendar_la_SOURCES = \ e-cell-date-edit-text.c \ e-comp-editor-registry.c \ e-comp-editor-registry.h \ + e-date-time-list.c \ + e-date-time-list.h \ e-day-view-layout.c \ e-day-view-layout.h \ e-day-view-main-item.c \ diff --git a/calendar/gui/dialogs/recurrence-page.c b/calendar/gui/dialogs/recurrence-page.c index f88b79ad9b..e9667e943b 100644 --- a/calendar/gui/dialogs/recurrence-page.c +++ b/calendar/gui/dialogs/recurrence-page.c @@ -1,3 +1,5 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + /* Evolution calendar - Recurrence page of the calendar component dialogs * * Copyright (C) 2001 Ximian, Inc. @@ -30,6 +32,8 @@ #include <gtk/gtktogglebutton.h> #include <gtk/gtksignal.h> #include <gtk/gtkspinbutton.h> +#include <gtk/gtkliststore.h> +#include <gtk/gtktreeview.h> #include <libgnome/gnome-i18n.h> #include <glade/glade.h> #include <gal/widgets/e-unicode.h> @@ -41,6 +45,7 @@ #include "../tag-calendar.h" #include "../weekday-picker.h" #include "comp-editor-util.h" +#include "../e-date-time-list.h" #include "recurrence-page.h" @@ -166,7 +171,6 @@ struct _RecurrencePagePrivate { GladeXML *xml; /* Widgets from the Glade file */ - GtkWidget *main; GtkWidget *summary; @@ -207,15 +211,17 @@ struct _RecurrencePagePrivate { int ending_count; /* More widgets from the Glade file */ - GtkWidget *exception_date; - GtkWidget *exception_list; + GtkWidget *exception_list; /* This is a GtkTreeView now */ GtkWidget *exception_add; GtkWidget *exception_modify; GtkWidget *exception_delete; GtkWidget *preview_bin; + /* Store for exception_list */ + EDateTimeList *exception_list_store; + /* For the recurrence preview, the actual widget */ GtkWidget *preview_calendar; @@ -347,6 +353,11 @@ recurrence_page_finalize (GObject *object) priv->comp = NULL; } + if (priv->exception_list_store) { + g_object_unref (priv->exception_list_store); + priv->exception_list_store = NULL; + } + g_free (priv); rpage->priv = NULL; @@ -436,7 +447,7 @@ clear_widgets (RecurrencePage *rpage) g_signal_handlers_unblock_matched (menu, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, rpage); /* Exceptions list */ - gtk_clist_clear (GTK_CLIST (priv->exception_list)); + e_date_time_list_clear (priv->exception_list_store); } /* Builds a static string out of an exception date */ @@ -468,39 +479,15 @@ static void append_exception (RecurrencePage *rpage, CalComponentDateTime *datetime) { RecurrencePagePrivate *priv; - CalComponentDateTime *dt; - char *c[1]; - int i; - GtkCList *clist; + GtkTreeView *view; + GtkTreeIter iter; struct icaltimetype *tt; priv = rpage->priv; + view = GTK_TREE_VIEW (priv->exception_list); - dt = g_new (CalComponentDateTime, 1); - dt->value = g_new (struct icaltimetype, 1); - *dt->value = *datetime->value; - dt->tzid = g_strdup (datetime->tzid); - - clist = GTK_CLIST (priv->exception_list); - - g_signal_handlers_block_matched (clist, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, rpage); - - c[0] = get_exception_string (dt); - i = gtk_clist_append (clist, c); - - gtk_clist_set_row_data_full (clist, i, dt, (GtkDestroyNotify) free_exception_date_time); - - gtk_clist_select_row (clist, i, 0); - g_signal_handlers_unblock_matched (clist, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, rpage); - - tt = dt->value; - e_date_edit_set_date (E_DATE_EDIT (priv->exception_date), - tt->year, tt->month, tt->day); - e_date_edit_set_time_of_day (E_DATE_EDIT (priv->exception_date), - tt->hour, tt->minute); - - gtk_widget_set_sensitive (priv->exception_modify, TRUE); - gtk_widget_set_sensitive (priv->exception_delete, TRUE); + e_date_time_list_append (priv->exception_list_store, &iter, datetime); + gtk_tree_selection_select_iter (gtk_tree_view_get_selection (view), &iter); } /* Fills in the exception widgets with the data from the calendar component */ @@ -833,11 +820,15 @@ fill_component (RecurrencePage *rpage, CalComponent *comp) { RecurrencePagePrivate *priv; enum recur_type recur_type; - GtkCList *exception_list; + GtkTreeView *exception_list; + GtkTreeModel *model; + GtkTreeIter iter; + gboolean valid_iter; GSList *list; int i; priv = rpage->priv; + model = GTK_TREE_MODEL (priv->exception_list_store); recur_type = e_dialog_radio_get (priv->none, type_map); @@ -865,29 +856,28 @@ fill_component (RecurrencePage *rpage, CalComponent *comp) /* Set exceptions */ list = NULL; - exception_list = GTK_CLIST (priv->exception_list); - for (i = 0; i < exception_list->rows; i++) { - CalComponentDateTime *cdt, *dt; + + for (valid_iter = gtk_tree_model_get_iter_first (model, &iter); valid_iter; + valid_iter = gtk_tree_model_iter_next (model, &iter)) { + const CalComponentDateTime *dt; + CalComponentDateTime *cdt; cdt = g_new (CalComponentDateTime, 1); cdt->value = g_new (struct icaltimetype, 1); - dt = gtk_clist_get_row_data (exception_list, i); + dt = e_date_time_list_get_date_time (E_DATE_TIME_LIST (model), &iter); g_assert (dt != NULL); + if (!icaltime_is_valid_time (*dt->value)) { comp_editor_page_display_validation_error (COMP_EDITOR_PAGE (rpage), _("Recurrent date is wrong"), - exception_list); + priv->exception_list); return FALSE; } *cdt->value = *dt->value; cdt->tzid = g_strdup (dt->tzid); -#if 0 - g_print ("Adding exception is_date: %i\n", cdt->value->is_date); -#endif - list = g_slist_prepend (list, cdt); } @@ -2198,24 +2188,24 @@ exception_modify_cb (GtkWidget *widget, gpointer data) { RecurrencePage *rpage; RecurrencePagePrivate *priv; - GtkCList *clist; - CalComponentDateTime *dt; + GtkTreeSelection *selection; + CalComponentDateTime dt; + struct icaltimetype icaltime = icaltime_null_time (); struct icaltimetype *tt; - int sel; + GtkTreeIter iter; rpage = RECURRENCE_PAGE (data); priv = rpage->priv; - clist = GTK_CLIST (priv->exception_list); - if (!clist->selection) + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->exception_list)); + if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) { + g_warning ("Could not get a selection to modify."); return; - + } field_changed (rpage); - sel = GPOINTER_TO_INT (clist->selection->data); - - dt = gtk_clist_get_row_data (clist, sel); - tt = dt->value; + dt.value = &icaltime; + tt = dt.value; e_date_edit_get_date (E_DATE_EDIT (priv->exception_date), &tt->year, &tt->month, &tt->day); tt->hour = 0; @@ -2223,12 +2213,10 @@ exception_modify_cb (GtkWidget *widget, gpointer data) tt->second = 0; tt->is_date = 1; - /* We get rid of any old TZID, since we are using a DATE value now. */ - g_free ((char*)dt->tzid); - dt->tzid = NULL; - - gtk_clist_set_text (clist, sel, 0, get_exception_string (dt)); + /* No TZID, since we are using a DATE value now. */ + dt.tzid = NULL; + e_date_time_list_set_date_time (priv->exception_list_store, &iter, &dt); preview_recur (rpage); } @@ -2238,31 +2226,37 @@ exception_delete_cb (GtkWidget *widget, gpointer data) { RecurrencePage *rpage; RecurrencePagePrivate *priv; - GtkCList *clist; + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreePath *path; + gboolean valid_iter; int sel; rpage = RECURRENCE_PAGE (data); priv = rpage->priv; - clist = GTK_CLIST (priv->exception_list); - if (!clist->selection) + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->exception_list)); + if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) { + g_warning ("Could not get a selection to delete."); return; + } field_changed (rpage); - sel = GPOINTER_TO_INT (clist->selection->data); - - gtk_clist_remove (clist, sel); - if (sel >= clist->rows) - sel--; + path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->exception_list_store), &iter); + e_date_time_list_remove (priv->exception_list_store, &iter); - if (clist->rows > 0) - gtk_clist_select_row (clist, sel, 0); - else { - gtk_widget_set_sensitive (priv->exception_modify, FALSE); - gtk_widget_set_sensitive (priv->exception_delete, FALSE); + /* Select closest item after removal */ + valid_iter = gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->exception_list_store), &iter, path); + if (!valid_iter) { + gtk_tree_path_prev (path); + valid_iter = gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->exception_list_store), &iter, path); } + if (valid_iter) + gtk_tree_selection_select_iter (selection, &iter); + + gtk_tree_path_free (path); preview_recur (rpage); } @@ -2271,24 +2265,27 @@ exception_delete_cb (GtkWidget *widget, gpointer data) * exception's value. */ static void -exception_select_row_cb (GtkCList *clist, gint row, gint col, - GdkEvent *event, gpointer data) +exception_selection_changed_cb (GtkTreeSelection *selection, gpointer data) { RecurrencePage *rpage; RecurrencePagePrivate *priv; - CalComponentDateTime *dt; + const CalComponentDateTime *dt; struct icaltimetype *t; + GtkTreeIter iter; rpage = RECURRENCE_PAGE (data); priv = rpage->priv; - /* Sometimes GtkCList emits a 'row-selected' signal for row 0 when - there are 0 rows in the list (after you delete the last row). - So we check that the row is valid here. */ - if (row >= clist->rows) + if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) { + gtk_widget_set_sensitive (priv->exception_modify, FALSE); + gtk_widget_set_sensitive (priv->exception_delete, FALSE); return; + } - dt = gtk_clist_get_row_data (clist, row); + gtk_widget_set_sensitive (priv->exception_modify, TRUE); + gtk_widget_set_sensitive (priv->exception_delete, TRUE); + + dt = e_date_time_list_get_date_time (priv->exception_list_store, &iter); g_assert (dt != NULL); t = dt->value; @@ -2319,6 +2316,8 @@ init_widgets (RecurrencePage *rpage) ECalendar *ecal; GtkAdjustment *adj; GtkWidget *menu; + GtkTreeViewColumn *column; + GtkCellRenderer *cell_renderer; priv = rpage->priv; @@ -2383,10 +2382,26 @@ init_widgets (RecurrencePage *rpage) g_signal_connect((priv->exception_delete), "clicked", G_CALLBACK (exception_delete_cb), rpage); - /* Selections in the exceptions list */ + gtk_widget_set_sensitive (priv->exception_modify, FALSE); + gtk_widget_set_sensitive (priv->exception_delete, FALSE); + + /* Exception list */ + + /* Model */ + priv->exception_list_store = e_date_time_list_new (); + gtk_tree_view_set_model (GTK_TREE_VIEW (priv->exception_list), + GTK_TREE_MODEL (priv->exception_list_store)); + + /* View */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_title (column, "Date/Time"); + cell_renderer = GTK_CELL_RENDERER (gtk_cell_renderer_text_new ()); + gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); + gtk_tree_view_column_add_attribute (column, cell_renderer, "text", E_DATE_TIME_LIST_COLUMN_DESCRIPTION); + gtk_tree_view_append_column (GTK_TREE_VIEW (priv->exception_list), column); - g_signal_connect((priv->exception_list), "select_row", - G_CALLBACK (exception_select_row_cb), rpage); + g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->exception_list)), "changed", + G_CALLBACK (exception_selection_changed_cb), rpage); } diff --git a/calendar/gui/e-date-time-list.c b/calendar/gui/e-date-time-list.c new file mode 100644 index 0000000000..f5d3608122 --- /dev/null +++ b/calendar/gui/e-date-time-list.c @@ -0,0 +1,555 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* EDateTimeList - list of calendar dates/times with GtkTreeModel interface. + * + * Copyright (C) 2003 Ximian, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Hans Petter Jansson <hpj@ximian.com> + */ + +#include <string.h> +#include <gtk/gtktreemodel.h> +#include <gtk/gtksignal.h> +#include <gtk/gtktreednd.h> +#include <glib.h> +#include "e-date-time-list.h" + +#define G_LIST(x) ((GList *) x) +#define E_DATE_TIME_LIST_IS_SORTED(list) (E_DATE_TIME_LIST (list)->sort_column_id != -2) +#define IS_VALID_ITER(dt_list, iter) (iter!= NULL && iter->user_data != NULL && \ + dt_list->stamp == iter->stamp) + +static GType column_types [E_DATE_TIME_LIST_NUM_COLUMNS]; + +static void e_date_time_list_init (EDateTimeList *file_list); +static void e_date_time_list_class_init (EDateTimeListClass *class); +static void e_date_time_list_tree_model_init (GtkTreeModelIface *iface); +static void e_date_time_list_finalize (GObject *object); +static guint e_date_time_list_get_flags (GtkTreeModel *tree_model); +static gint e_date_time_list_get_n_columns (GtkTreeModel *tree_model); +static GType e_date_time_list_get_column_type (GtkTreeModel *tree_model, + gint index); +static gboolean e_date_time_list_get_iter (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreePath *path); +static GtkTreePath *e_date_time_list_get_path (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static void e_date_time_list_get_value (GtkTreeModel *tree_model, + GtkTreeIter *iter, + gint column, + GValue *value); +static gboolean e_date_time_list_iter_next (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static gboolean e_date_time_list_iter_children (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent); +static gboolean e_date_time_list_iter_has_child (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static gint e_date_time_list_iter_n_children (GtkTreeModel *tree_model, + GtkTreeIter *iter); +static gboolean e_date_time_list_iter_nth_child (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent, + gint n); +static gboolean e_date_time_list_iter_parent (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *child); + +static GObjectClass *parent_class = NULL; + +GtkType +e_date_time_list_get_type (void) +{ + static GType date_time_list_type = 0; + + if (!date_time_list_type) { + static const GTypeInfo date_time_list_info = + { + sizeof (EDateTimeListClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) e_date_time_list_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (EDateTimeList), + 0, + (GInstanceInitFunc) e_date_time_list_init, + }; + + static const GInterfaceInfo tree_model_info = + { + (GInterfaceInitFunc) e_date_time_list_tree_model_init, + NULL, + NULL + }; + + column_types [E_DATE_TIME_LIST_COLUMN_DESCRIPTION] = G_TYPE_STRING; + + date_time_list_type = g_type_register_static (G_TYPE_OBJECT, "EDateTimeList", + &date_time_list_info, 0); + g_type_add_interface_static (date_time_list_type, + GTK_TYPE_TREE_MODEL, + &tree_model_info); + } + + return date_time_list_type; +} + +static void +e_date_time_list_class_init (EDateTimeListClass *class) +{ + GObjectClass *object_class; + + parent_class = g_type_class_peek_parent (class); + object_class = (GObjectClass*) class; + + object_class->finalize = e_date_time_list_finalize; +} + +static void +e_date_time_list_tree_model_init (GtkTreeModelIface *iface) +{ + iface->get_flags = e_date_time_list_get_flags; + iface->get_n_columns = e_date_time_list_get_n_columns; + iface->get_column_type = e_date_time_list_get_column_type; + iface->get_iter = e_date_time_list_get_iter; + iface->get_path = e_date_time_list_get_path; + iface->get_value = e_date_time_list_get_value; + iface->iter_next = e_date_time_list_iter_next; + iface->iter_children = e_date_time_list_iter_children; + iface->iter_has_child = e_date_time_list_iter_has_child; + iface->iter_n_children = e_date_time_list_iter_n_children; + iface->iter_nth_child = e_date_time_list_iter_nth_child; + iface->iter_parent = e_date_time_list_iter_parent; +} + +static void +e_date_time_list_init (EDateTimeList *date_time_list) +{ + date_time_list->stamp = g_random_int (); + date_time_list->columns_dirty = FALSE; + date_time_list->list = NULL; +} + +EDateTimeList * +e_date_time_list_new (void) +{ + EDateTimeList *date_time_list; + + date_time_list = E_DATE_TIME_LIST (g_object_new (e_date_time_list_get_type (), NULL)); + + return date_time_list; +} + +static void +all_rows_deleted (EDateTimeList *date_time_list) +{ + GtkTreePath *path; + gint i; + + if (!date_time_list->list) + return; + + path = gtk_tree_path_new (); + i = g_list_length (date_time_list->list); + gtk_tree_path_append_index (path, i); + + for ( ; i >= 0; i--) { + gtk_tree_model_row_deleted (GTK_TREE_MODEL (date_time_list), path); + gtk_tree_path_prev (path); + } + + gtk_tree_path_free (path); +} + +static void +row_deleted (EDateTimeList *date_time_list, gint n) +{ + GtkTreePath *path; + gint i; + + path = gtk_tree_path_new (); + gtk_tree_path_append_index (path, n); + gtk_tree_model_row_deleted (GTK_TREE_MODEL (date_time_list), path); + gtk_tree_path_free (path); +} + +static void +row_added (EDateTimeList *date_time_list, gint n) +{ + GtkTreePath *path; + GtkTreeIter iter; + + path = gtk_tree_path_new (); + gtk_tree_path_append_index (path, n); + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (date_time_list), &iter, path)) + gtk_tree_model_row_inserted (GTK_TREE_MODEL (date_time_list), path, &iter); + + gtk_tree_path_free (path); +} + +static void +row_updated (EDateTimeList *date_time_list, gint n) +{ + GtkTreePath *path; + GtkTreeIter iter; + + path = gtk_tree_path_new (); + gtk_tree_path_append_index (path, n); + + if (gtk_tree_model_get_iter (GTK_TREE_MODEL (date_time_list), &iter, path)) + gtk_tree_model_row_changed (GTK_TREE_MODEL (date_time_list), path, &iter); + + gtk_tree_path_free (path); +} + +static void +e_date_time_list_finalize (GObject *object) +{ + EDateTimeList *date_time_list = E_DATE_TIME_LIST (object); +} + +/* Fulfill the GtkTreeModel requirements */ +static guint +e_date_time_list_get_flags (GtkTreeModel *tree_model) +{ + g_return_val_if_fail (E_IS_DATE_TIME_LIST (tree_model), 0); + + return GTK_TREE_MODEL_LIST_ONLY; +} + +static gint +e_date_time_list_get_n_columns (GtkTreeModel *tree_model) +{ + EDateTimeList *date_time_list = (EDateTimeList *) tree_model; + + g_return_val_if_fail (E_IS_DATE_TIME_LIST (tree_model), 0); + + date_time_list->columns_dirty = TRUE; + return E_DATE_TIME_LIST_NUM_COLUMNS; +} + +static GType +e_date_time_list_get_column_type (GtkTreeModel *tree_model, + gint index) +{ + EDateTimeList *date_time_list = (EDateTimeList *) tree_model; + + g_return_val_if_fail (E_IS_DATE_TIME_LIST (tree_model), G_TYPE_INVALID); + g_return_val_if_fail (index < E_DATE_TIME_LIST_NUM_COLUMNS && + index >= 0, G_TYPE_INVALID); + + date_time_list->columns_dirty = TRUE; + return column_types [index]; +} + +const CalComponentDateTime * +e_date_time_list_get_date_time (EDateTimeList *date_time_list, GtkTreeIter *iter) +{ + g_return_val_if_fail (IS_VALID_ITER (date_time_list, iter), NULL); + + return G_LIST (iter->user_data)->data; +} + +static void +free_datetime (CalComponentDateTime *datetime) +{ + g_free (datetime->value); + if (datetime->tzid) + g_free ((gchar *) datetime->tzid); + g_free (datetime); +} + +static CalComponentDateTime * +copy_datetime (const CalComponentDateTime *datetime) +{ + CalComponentDateTime *datetime_copy; + + datetime_copy = g_new0 (CalComponentDateTime, 1); + datetime_copy->value = g_new (struct icaltimetype, 1); + *datetime_copy->value = *datetime->value; + + if (datetime->tzid) + datetime_copy->tzid = g_strdup (datetime->tzid); + + return datetime_copy; +} + +void +e_date_time_list_set_date_time (EDateTimeList *date_time_list, GtkTreeIter *iter, + const CalComponentDateTime *datetime) +{ + CalComponentDateTime *datetime_old; + + g_return_if_fail (IS_VALID_ITER (date_time_list, iter)); + + datetime_old = G_LIST (iter->user_data)->data; + free_datetime (datetime_old); + G_LIST (iter->user_data)->data = copy_datetime (datetime); + row_updated (date_time_list, g_list_position (date_time_list->list, G_LIST (iter->user_data))); +} + +void +e_date_time_list_append (EDateTimeList *date_time_list, GtkTreeIter *iter, + const CalComponentDateTime *datetime) +{ + CalComponentDateTime *datetime_copy; + + g_return_if_fail (datetime != NULL); + + date_time_list->list = g_list_append (date_time_list->list, copy_datetime (datetime)); + row_added (date_time_list, g_list_length (date_time_list->list) - 1); + + if (iter) { + iter->user_data = g_list_last (date_time_list->list); + iter->stamp = date_time_list->stamp; + } +} + +void +e_date_time_list_remove (EDateTimeList *date_time_list, GtkTreeIter *iter) +{ + gint n; + + g_return_if_fail (IS_VALID_ITER (date_time_list, iter)); + + n = g_list_position (date_time_list->list, G_LIST (iter->user_data)); + free_datetime ((CalComponentDateTime *) G_LIST (iter->user_data)->data); + date_time_list->list = g_list_delete_link (date_time_list->list, G_LIST (iter->user_data)); + row_deleted (date_time_list, n); +} + +void +e_date_time_list_clear (EDateTimeList *date_time_list) +{ + GList *l; + + all_rows_deleted (date_time_list); + + for (l = date_time_list->list; l; l = g_list_next (l)) { + free_datetime ((CalComponentDateTime *) l->data); + } + + g_list_free (date_time_list->list); + date_time_list->list = NULL; +} + +static gboolean +e_date_time_list_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path) +{ + EDateTimeList *date_time_list = (EDateTimeList *) tree_model; + GList *l; + gint i; + + g_return_val_if_fail (E_IS_DATE_TIME_LIST (tree_model), FALSE); + g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE); + + if (!date_time_list->list) + return FALSE; + + date_time_list->columns_dirty = TRUE; + + i = gtk_tree_path_get_indices (path)[0]; + l = g_list_nth (date_time_list->list, i); + if (!l) + return FALSE; + + iter->user_data = l; + iter->stamp = date_time_list->stamp; + return TRUE; +} + +static GtkTreePath * +e_date_time_list_get_path (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + EDateTimeList *date_time_list = (EDateTimeList *) tree_model; + GtkTreePath *retval; + GList *l; + + g_return_val_if_fail (E_IS_DATE_TIME_LIST (tree_model), NULL); + g_return_val_if_fail (iter->stamp == E_DATE_TIME_LIST (tree_model)->stamp, NULL); + + l = iter->user_data; + retval = gtk_tree_path_new (); + gtk_tree_path_append_index (retval, g_list_position (date_time_list->list, l)); + return retval; +} + +/* Builds a static string out of an exception date */ +static char * +get_exception_string (CalComponentDateTime *dt) +{ + static char buf [256]; + struct tm tmp_tm; + + tmp_tm.tm_year = dt->value->year - 1900; + tmp_tm.tm_mon = dt->value->month - 1; + tmp_tm.tm_mday = dt->value->day; + tmp_tm.tm_hour = dt->value->hour; + tmp_tm.tm_min = dt->value->minute; + tmp_tm.tm_sec = dt->value->second; + tmp_tm.tm_isdst = -1; + + tmp_tm.tm_wday = time_day_of_week (dt->value->day, + dt->value->month - 1, + dt->value->year); + + e_time_format_date_and_time (&tmp_tm, calendar_config_get_24_hour_format (), + FALSE, FALSE, buf, sizeof (buf)); + + return buf; +} + +static void +e_date_time_list_get_value (GtkTreeModel *tree_model, + GtkTreeIter *iter, + gint column, + GValue *value) +{ + EDateTimeList *date_time_list = E_DATE_TIME_LIST (tree_model); + CalComponentDateTime *datetime; + GList *l; + const gchar *str; + + g_return_if_fail (E_IS_DATE_TIME_LIST (tree_model)); + g_return_if_fail (column < E_DATE_TIME_LIST_NUM_COLUMNS); + g_return_if_fail (E_DATE_TIME_LIST (tree_model)->stamp == iter->stamp); + g_return_if_fail (IS_VALID_ITER (date_time_list, iter)); + + g_value_init (value, column_types [column]); + + if (!date_time_list->list) + return; + + l = iter->user_data; + datetime = l->data; + + if (!datetime) + return; + + switch (column) { + case E_DATE_TIME_LIST_COLUMN_DESCRIPTION: + str = get_exception_string (datetime); + g_value_set_string (value, str); + break; + } +} + +static gboolean +e_date_time_list_iter_next (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GList *l; + + g_return_val_if_fail (E_IS_DATE_TIME_LIST (tree_model), FALSE); + g_return_val_if_fail (IS_VALID_ITER (E_DATE_TIME_LIST (tree_model), iter), FALSE); + + if (!E_DATE_TIME_LIST (tree_model)->list) + return FALSE; + + l = iter->user_data; + l = g_list_next (l); + if (l) { + iter->user_data = l; + return TRUE; + } + + return FALSE; +} + +static gboolean +e_date_time_list_iter_children (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent) +{ + EDateTimeList *date_time_list = E_DATE_TIME_LIST (tree_model); + + /* this is a list, nodes have no children */ + if (parent) + return FALSE; + + /* but if parent == NULL we return the list itself as children of the + * "root" */ + + if (!date_time_list->list) + return FALSE; + + iter->stamp = E_DATE_TIME_LIST (tree_model)->stamp; + iter->user_data = date_time_list->list; + return TRUE; +} + +static gboolean +e_date_time_list_iter_has_child (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + g_return_val_if_fail (IS_VALID_ITER (E_DATE_TIME_LIST (tree_model), iter), FALSE); + return FALSE; +} + +static gint +e_date_time_list_iter_n_children (GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + EDateTimeList *date_time_list = E_DATE_TIME_LIST (tree_model); + + g_return_val_if_fail (E_IS_DATE_TIME_LIST (tree_model), -1); + g_return_val_if_fail (IS_VALID_ITER (date_time_list, iter), -1); + + if (iter == NULL) + return g_list_length (date_time_list->list); + + g_return_val_if_fail (E_DATE_TIME_LIST (tree_model)->stamp == iter->stamp, -1); + return 0; +} + +static gboolean +e_date_time_list_iter_nth_child (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *parent, + gint n) +{ + EDateTimeList *date_time_list = E_DATE_TIME_LIST (tree_model); + + g_return_val_if_fail (E_IS_DATE_TIME_LIST (tree_model), FALSE); + + if (parent) + return FALSE; + + if (date_time_list->list) { + GList *l; + + l = g_list_nth (date_time_list->list, n); + if (!l) + return FALSE; + + iter->stamp = date_time_list->stamp; + iter->user_data = l; + return TRUE; + } + + return FALSE; +} + +static gboolean +e_date_time_list_iter_parent (GtkTreeModel *tree_model, + GtkTreeIter *iter, + GtkTreeIter *child) +{ + return FALSE; +} diff --git a/calendar/gui/e-date-time-list.h b/calendar/gui/e-date-time-list.h new file mode 100644 index 0000000000..07a7c77b02 --- /dev/null +++ b/calendar/gui/e-date-time-list.h @@ -0,0 +1,83 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + +/* EDateTimeList - list of calendar dates/times with GtkTreeModel interface. + * + * Copyright (C) 2003 Ximian, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Hans Petter Jansson <hpj@ximian.com> + */ + +#ifndef E_DATE_TIME_LIST_H +#define E_DATE_TIME_LIST_H + +#include <gtk/gtktreemodel.h> +#include <cal-util/cal-component.h> + +G_BEGIN_DECLS + +#define E_TYPE_DATE_TIME_LIST (e_date_time_list_get_type ()) +#define E_DATE_TIME_LIST(obj) (GTK_CHECK_CAST ((obj), E_TYPE_DATE_TIME_LIST, EDateTimeList)) +#define E_DATE_TIME_LIST_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TYPE_DATE_TIME_LIST, EDateTimeListClass)) +#define E_IS_DATE_TIME_LIST(obj) (GTK_CHECK_TYPE ((obj), E_TYPE_DATE_TIME_LIST)) +#define E_IS_DATE_TIME_LIST_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), E_TYPE_DATE_TIME_LIST)) +#define E_DATE_TIME_LIST_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), E_TYPE_DATE_TIME_LIST, EDateTimeListClass)) + +typedef struct _EDateTimeList EDateTimeList; +typedef struct _EDateTimeListClass EDateTimeListClass; + +typedef enum +{ + E_DATE_TIME_LIST_COLUMN_DESCRIPTION, + + E_DATE_TIME_LIST_NUM_COLUMNS +} +EDateTimeListColumnType; + +struct _EDateTimeList +{ + GObject parent; + + /* Private */ + + gint stamp; + GList *list; + + guint columns_dirty : 1; +}; + +struct _EDateTimeListClass +{ + GObjectClass parent_class; +}; + +GtkType e_date_time_list_get_type (void); +EDateTimeList *e_date_time_list_new (void); + +const CalComponentDateTime *e_date_time_list_get_date_time (EDateTimeList *date_time_list, + GtkTreeIter *iter); +void e_date_time_list_set_date_time (EDateTimeList *date_time_list, + GtkTreeIter *iter, + const CalComponentDateTime *datetime); +void e_date_time_list_append (EDateTimeList *date_time_list, + GtkTreeIter *iter, + const CalComponentDateTime *datetime); +void e_date_time_list_remove (EDateTimeList *date_time_list, + GtkTreeIter *iter); +void e_date_time_list_clear (EDateTimeList *date_time_list); + +G_END_DECLS + +#endif /* E_DATE_TIME_LIST_H */ diff --git a/calendar/gui/e-meeting-time-sel.c b/calendar/gui/e-meeting-time-sel.c index 557fcc068b..ad52ecc5bf 100644 --- a/calendar/gui/e-meeting-time-sel.c +++ b/calendar/gui/e-meeting-time-sel.c @@ -458,15 +458,16 @@ e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingModel *em mts->options_menu = gtk_menu_new (); gtk_menu_attach_to_widget (GTK_MENU (mts->options_menu), mts->options_button, e_meeting_time_selector_options_menu_detacher); -#if 0 - menu_accel_group = gtk_menu_ensure_uline_accel_group (GTK_MENU (mts->options_menu)); -#endif + + menu_accel_group = gtk_accel_group_new (); + gtk_menu_set_accel_group (GTK_MENU (mts->options_menu), menu_accel_group); menuitem = gtk_check_menu_item_new_with_label (""); accel_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menuitem)->child), _("Show _Only Working Hours")); gtk_menu_append (GTK_MENU (mts->options_menu), menuitem); gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), mts->working_hours_only); + gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, accel_key, 0, 0); gtk_widget_add_accelerator (menuitem, "activate", menu_accel_group, @@ -555,9 +556,9 @@ e_meeting_time_selector_construct (EMeetingTimeSelector * mts, EMeetingModel *em mts->autopick_menu = gtk_menu_new (); gtk_menu_attach_to_widget (GTK_MENU (mts->autopick_menu), mts->autopick_button, e_meeting_time_selector_autopick_menu_detacher); -#if 0 - menu_accel_group = gtk_menu_ensure_uline_accel_group (GTK_MENU (mts->autopick_menu)); -#endif + + menu_accel_group = gtk_accel_group_new (); + gtk_menu_set_accel_group (GTK_MENU (mts->autopick_menu), menu_accel_group); menuitem = gtk_radio_menu_item_new_with_label (NULL, ""); mts->autopick_all_item = menuitem; |