aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog13
-rw-r--r--calendar/gui/Makefile.am2
-rw-r--r--calendar/gui/dialogs/recurrence-page.c179
-rw-r--r--calendar/gui/e-date-time-list.c555
-rw-r--r--calendar/gui/e-date-time-list.h83
-rw-r--r--calendar/gui/e-meeting-time-sel.c13
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;